wip: initial disassembly of new gui and cli commands
This commit is contained in:
parent
b2bcbb3027
commit
0c9d1a472f
5 changed files with 413 additions and 291 deletions
418
GUI.py
418
GUI.py
|
|
@ -10,299 +10,275 @@
|
|||
# Source Generated with Decompyle++
|
||||
# File: GUI.pyc (Python 3.8)
|
||||
|
||||
import PySimpleGUI as ui
|
||||
import zlib
|
||||
import time
|
||||
import PySimpleGUI as sg
|
||||
import threading
|
||||
import os
|
||||
|
||||
ui.theme('SystemDefault')
|
||||
from pathlib import Path
|
||||
from MFOR import file_hash
|
||||
sg.theme('SystemDefault')
|
||||
tt_race = ' Generating a race seed will not generate a spoiler log. '
|
||||
tt_createpatch = ' Automatically creates a .bps patch after generating a randomized game, so you can easily share with others. '
|
||||
tt_difficulty = ' Higher difficulty means harder tricks. Difficulty 0 means no tricks are expected outside of vanilla strategies. '
|
||||
tt_itempool = ' Limit where important items can be placed. If checked, major upgrades will only be in Data rooms, \n at bosses, or at vanilla E-tank locations. If unchecked, any item can be anywhere within logic. '
|
||||
tt_missileswithupgrades = ' If checked, collecting any major Missile item will enable Missiles. Logic will account for this setting. '
|
||||
tt_pbswithoutbombs = ' If checked, Power Bombs can be used without having regular Bombs. Logic will account for this setting. '
|
||||
tt_damageruns = ' Allow logic to require Samus to run through damaging environments to acquire important items. \n Examples include heated rooms, electrified water, and lava. '
|
||||
tt_splitsecurity = ' If checked, each door color must be unlocked independently. \n If unchecked, unlocking higher security levels will unlock all security levels below it. \n E.G.: unlocking Level 2 (Green) doors will also unlock Level 1 (Blue) doors. '
|
||||
tt_SectorShuffle = ' Randomly shuffle the arrangement of the Sectors. '
|
||||
tt_HideItems = ' Make all items appear as ? tanks. '
|
||||
tt_patch = ' Create a .bps patch after generating a game, so you can easily share with others. '
|
||||
tt_difficulty = ' Higher difficulty means harder tricks can be required.\n Difficulty 0 means no tricks are expected outside of vanilla strategies. '
|
||||
tt_major_minor = ' Limit where important items can be placed. If checked, major items will only be in Data rooms, \n at bosses, or at vanilla E-tank locations. If unchecked, any item can be anywhere within logic. '
|
||||
tt_missile_data = ' If checked, collecting any Missile data will enable Missiles. Logic will account for this setting. '
|
||||
tt_pb_data = ' If checked, Power Bombs can be used without having regular Bombs. Logic will account for this setting. '
|
||||
tt_hazard_runs = ' Allow logic to require Samus to run through hazardous environments to acquire important items. \n Examples include heated rooms, electrified water, and lava. '
|
||||
tt_split_security = ' If checked, each security level must be unlocked independently. \n If unchecked, unlocking higher security levels will unlock all lesser security levels. \n E.G.: unlocking Level 2 (Green) doors will also unlock Level 1 (Blue) doors. '
|
||||
tt_shuffle_sectors = ' Randomly shuffle the arrangement of the Sectors. '
|
||||
tt_shuffle_tubes = ' Randomly shuffle the tube connections between the Sectors. '
|
||||
tt_hide_items = ' Make all items appear as ? tanks. '
|
||||
generating = False
|
||||
|
||||
def fileHash(fileName):
|
||||
with open(fileName, 'rb') as fh:
|
||||
hash = 0
|
||||
while True:
|
||||
s = fh.read(65536)
|
||||
if not s:
|
||||
break
|
||||
hash = zlib.crc32(s, hash)
|
||||
return hash & 0xFFFFFFFF
|
||||
|
||||
def rando_thread(window = None, values = None):
|
||||
global fileName, basegame, failedgen, randoerror, generating, finishGenerating
|
||||
global failed_gen, rando_error, generating, file_name, failed_gen, generating, finish_generating
|
||||
values.update({
|
||||
'Difficulty': int(values.get('Difficulty')) })
|
||||
if values['Num']:
|
||||
'-DIFFICULTY-': int(values.get('-DIFFICULTY-')) })
|
||||
if values['-NUM-']:
|
||||
values.update({
|
||||
'Num': int(values.get('Num')) })
|
||||
'-NUM-': int(values.get('-NUM-')) })
|
||||
else:
|
||||
values.update({
|
||||
'Num': 1 })
|
||||
if values['Num'] < 1:
|
||||
'-NUM-': 1 })
|
||||
if values['-NUM-'] < 1:
|
||||
values.update({
|
||||
'Num': 1 })
|
||||
'-NUM-': 1 })
|
||||
values.pop(0)
|
||||
failedgen = False
|
||||
randoerror = False
|
||||
# FIXME: whatever this is
|
||||
# values = (lambda .0 = None: pass# WARNING: Decompyle incomplete
|
||||
#)(sorted(values.keys()))
|
||||
failed_gen = False
|
||||
rando_error = False
|
||||
generating = True
|
||||
|
||||
from Randomizer import start_randomizer
|
||||
if values['Debug']:
|
||||
fileName = start_randomizer(basegame, values)
|
||||
file_name = start_randomizer(base_game, values)
|
||||
else:
|
||||
# FIXME: let it explode
|
||||
#try:
|
||||
fileName = start_randomizer(basegame, values)
|
||||
# finally:
|
||||
# pass
|
||||
#except SystemExit:
|
||||
# failedgen = True
|
||||
#except:
|
||||
# print('An error occurred, no game was generated.')
|
||||
# randoerror = True
|
||||
|
||||
try:
|
||||
file_name = start_randomizer(base_game, values)
|
||||
except SystemExit:
|
||||
failed_gen = True
|
||||
|
||||
generating = False
|
||||
finishGenerating = True
|
||||
finish_generating = True
|
||||
|
||||
|
||||
def main_window(debug):
|
||||
global fileName, basegame, generating, finishGenerating
|
||||
itemPool = [
|
||||
global file_name, finish_generating, base_game, finish_generating
|
||||
item_pool = [
|
||||
[
|
||||
ui.Text('Charge Beam'),
|
||||
ui.Radio('Shuffled', 'radioChargeBeam', default=True),
|
||||
ui.Radio('Starting', 'radioChargeBeam'),
|
||||
ui.Radio('Disabled', 'radioChargeBeam')],
|
||||
sg.Text('Charge Beam'),
|
||||
sg.Radio('Shuffled', 'radioChargeBeam', default=True),
|
||||
sg.Radio('Starting', 'radioChargeBeam'),
|
||||
sg.Radio('Disabled', 'radioChargeBeam')],
|
||||
[
|
||||
ui.Text('Wide Beam'),
|
||||
ui.Radio('Shuffled', 'radioWideBeam', default=True),
|
||||
ui.Radio('Starting', 'radioWideBeam'),
|
||||
ui.Radio('Disabled', 'radioWideBeam')],
|
||||
sg.Text('Wide Beam'),
|
||||
sg.Radio('Shuffled', 'radioWideBeam', default=True),
|
||||
sg.Radio('Starting', 'radioWideBeam'),
|
||||
sg.Radio('Disabled', 'radioWideBeam')],
|
||||
[
|
||||
ui.Text('Plasma Beam'),
|
||||
ui.Radio('Shuffled', 'radioPlasmaBeam', default=True),
|
||||
ui.Radio('Starting', 'radioPlasmaBeam'),
|
||||
ui.Radio('Disabled', 'radioPlasmaBeam')],
|
||||
sg.Text('Plasma Beam'),
|
||||
sg.Radio('Shuffled', 'radioPlasmaBeam', default=True),
|
||||
sg.Radio('Starting', 'radioPlasmaBeam'),
|
||||
sg.Radio('Disabled', 'radioPlasmaBeam')],
|
||||
[
|
||||
ui.Text('Wave Beam'),
|
||||
ui.Radio('Shuffled', 'radioWaveBeam', default=True),
|
||||
ui.Radio('Starting', 'radioWaveBeam'),
|
||||
ui.Radio('Disabled', 'radioWaveBeam')],
|
||||
sg.Text('Wave Beam'),
|
||||
sg.Radio('Shuffled', 'radioWaveBeam', default=True),
|
||||
sg.Radio('Starting', 'radioWaveBeam'),
|
||||
sg.Radio('Disabled', 'radioWaveBeam')],
|
||||
[
|
||||
ui.Text('Ice Beam'),
|
||||
ui.Radio('Shuffled', 'radioIceBeam', default=True),
|
||||
ui.Radio('Starting', 'radioIceBeam'),
|
||||
ui.Radio('Disabled', 'radioIceBeam')],
|
||||
sg.Text('Ice Beam'),
|
||||
sg.Radio('Shuffled', 'radioIceBeam', default=True),
|
||||
sg.Radio('Starting', 'radioIceBeam'),
|
||||
sg.Radio('Disabled', 'radioIceBeam')],
|
||||
[
|
||||
ui.Text('Missile Data'),
|
||||
ui.Radio('Shuffled', 'radioMissileData', default=True),
|
||||
ui.Radio('Starting', 'radioMissileData'),
|
||||
ui.Radio('Disabled', 'radioMissileData')],
|
||||
sg.Text('Missile Data'),
|
||||
sg.Radio('Shuffled', 'radioMissileData', default=True),
|
||||
sg.Radio('Starting', 'radioMissileData'),
|
||||
sg.Radio('Disabled', 'radioMissileData')],
|
||||
[
|
||||
ui.Text('Super Missile Data'),
|
||||
ui.Radio('Shuffled', 'radioSuperMissile', default=True),
|
||||
ui.Radio('Starting', 'radioSuperMissile'),
|
||||
ui.Radio('Disabled', 'radioSuperMissile')],
|
||||
sg.Text('Super Missile Data'),
|
||||
sg.Radio('Shuffled', 'radioSuperMissile', default=True),
|
||||
sg.Radio('Starting', 'radioSuperMissile'),
|
||||
sg.Radio('Disabled', 'radioSuperMissile')],
|
||||
[
|
||||
ui.Text('Ice Missile Data'),
|
||||
ui.Radio('Shuffled', 'radioIceMissile', default=True),
|
||||
ui.Radio('Starting', 'radioIceMissile'),
|
||||
ui.Radio('Disabled', 'radioIceMissile')],
|
||||
sg.Text('Ice Missile Data'),
|
||||
sg.Radio('Shuffled', 'radioIceMissile', default=True),
|
||||
sg.Radio('Starting', 'radioIceMissile'),
|
||||
sg.Radio('Disabled', 'radioIceMissile')],
|
||||
[
|
||||
ui.Text('Diffusion Data'),
|
||||
ui.Radio('Shuffled', 'radioDiffusion', default=True),
|
||||
ui.Radio('Starting', 'radioDiffusion'),
|
||||
ui.Radio('Disabled', 'radioDiffusion')],
|
||||
sg.Text('Diffusion Data'),
|
||||
sg.Radio('Shuffled', 'radioDiffusion', default=True),
|
||||
sg.Radio('Starting', 'radioDiffusion'),
|
||||
sg.Radio('Disabled', 'radioDiffusion')],
|
||||
[
|
||||
ui.Text('Bombs'),
|
||||
ui.Radio('Shuffled', 'radioBombs', default=True),
|
||||
ui.Radio('Starting', 'radioBombs'),
|
||||
ui.Radio('Disabled', 'radioBombs')],
|
||||
sg.Text('Bombs'),
|
||||
sg.Radio('Shuffled', 'radioBombs', default=True),
|
||||
sg.Radio('Starting', 'radioBombs'),
|
||||
sg.Radio('Disabled', 'radioBombs')],
|
||||
[
|
||||
ui.Text('Power Bomb Data'),
|
||||
ui.Radio('Shuffled', 'radioPowerBombData', default=True),
|
||||
ui.Radio('Starting', 'radioPowerBombData'),
|
||||
ui.Radio('Disabled', 'radioPowerBombData')],
|
||||
sg.Text('Power Bomb Data'),
|
||||
sg.Radio('Shuffled', 'radioPowerBombData', default=True),
|
||||
sg.Radio('Starting', 'radioPowerBombData'),
|
||||
sg.Radio('Disabled', 'radioPowerBombData')],
|
||||
[
|
||||
ui.Text('Hi-Jump Boots'),
|
||||
ui.Radio('Shuffled', 'radioHiJump', default=True),
|
||||
ui.Radio('Starting', 'radioHiJump'),
|
||||
ui.Radio('Disabled', 'radioHiJump')],
|
||||
sg.Text('Hi-Jump Boots'),
|
||||
sg.Radio('Shuffled', 'radioHiJump', default=True),
|
||||
sg.Radio('Starting', 'radioHiJump'),
|
||||
sg.Radio('Disabled', 'radioHiJump')],
|
||||
[
|
||||
ui.Text('Speed Booster'),
|
||||
ui.Radio('Shuffled', 'radioSpeedBooster', default=True),
|
||||
ui.Radio('Starting', 'radioSpeedBooster'),
|
||||
ui.Radio('Disabled', 'radioSpeedBooster')],
|
||||
sg.Text('Speed Booster'),
|
||||
sg.Radio('Shuffled', 'radioSpeedBooster', default=True),
|
||||
sg.Radio('Starting', 'radioSpeedBooster'),
|
||||
sg.Radio('Disabled', 'radioSpeedBooster')],
|
||||
[
|
||||
ui.Text('Space Jump'),
|
||||
ui.Radio('Shuffled', 'radioSpaceJump', default=True),
|
||||
ui.Radio('Starting', 'radioSpaceJump'),
|
||||
ui.Radio('Disabled', 'radioSpaceJump')],
|
||||
sg.Text('Space Jump'),
|
||||
sg.Radio('Shuffled', 'radioSpaceJump', default=True),
|
||||
sg.Radio('Starting', 'radioSpaceJump'),
|
||||
sg.Radio('Disabled', 'radioSpaceJump')],
|
||||
[
|
||||
ui.Text('Screw Attack'),
|
||||
ui.Radio('Shuffled', 'radioScrewAttack', default=True),
|
||||
ui.Radio('Starting', 'radioScrewAttack'),
|
||||
ui.Radio('Disabled', 'radioScrewAttack')],
|
||||
sg.Text('Screw Attack'),
|
||||
sg.Radio('Shuffled', 'radioScrewAttack', default=True),
|
||||
sg.Radio('Starting', 'radioScrewAttack'),
|
||||
sg.Radio('Disabled', 'radioScrewAttack')],
|
||||
[
|
||||
ui.Text('Varia Suit'),
|
||||
ui.Radio('Shuffled', 'radioVariaSuit', default=True),
|
||||
ui.Radio('Starting', 'radioVariaSuit'),
|
||||
ui.Radio('Disabled', 'radioVariaSuit')],
|
||||
sg.Text('Varia Suit'),
|
||||
sg.Radio('Shuffled', 'radioVariaSuit', default=True),
|
||||
sg.Radio('Starting', 'radioVariaSuit'),
|
||||
sg.Radio('Disabled', 'radioVariaSuit')],
|
||||
[
|
||||
ui.Text('Gravity Suit'),
|
||||
ui.Radio('Shuffled', 'radioGravitySuit', default=True),
|
||||
ui.Radio('Starting', 'radioGravitySuit'),
|
||||
ui.Radio('Disabled', 'radioGravitySuit')],
|
||||
sg.Text('Gravity Suit'),
|
||||
sg.Radio('Shuffled', 'radioGravitySuit', default=True),
|
||||
sg.Radio('Starting', 'radioGravitySuit'),
|
||||
sg.Radio('Disabled', 'radioGravitySuit')],
|
||||
[
|
||||
ui.Text('Morph Ball'),
|
||||
ui.Radio('Shuffled', 'radioMorphBall', default=True),
|
||||
ui.Radio('Starting', 'radioMorphBall'),
|
||||
ui.Radio('Disabled', 'radioMorphBall')],
|
||||
sg.Text('Morph Ball'),
|
||||
sg.Radio('Shuffled', 'radioMorphBall', default=True),
|
||||
sg.Radio('Starting', 'radioMorphBall'),
|
||||
sg.Radio('Disabled', 'radioMorphBall')],
|
||||
[
|
||||
ui.Text('Blue Doors (Level 1)'),
|
||||
ui.Radio('Standard', 'radioBlueDoors', default=True),
|
||||
ui.Radio('Starting', 'radioBlueDoors'),
|
||||
ui.Radio('Shuffled', 'radioBlueDoors')],
|
||||
sg.Text('Blue Doors (Level 1)'),
|
||||
sg.Radio('Standard', 'radioBlueDoors', default=True),
|
||||
sg.Radio('Starting', 'radioBlueDoors'),
|
||||
sg.Radio('Shuffled', 'radioBlueDoors')],
|
||||
[
|
||||
ui.Text('Green Doors (Level 2)'),
|
||||
ui.Radio('Standard', 'radioGreenDoors', default=True),
|
||||
ui.Radio('Starting', 'radioGreenDoors'),
|
||||
ui.Radio('Shuffled', 'radioGreenDoors')],
|
||||
sg.Text('Green Doors (Level 2)'),
|
||||
sg.Radio('Standard', 'radioGreenDoors', default=True),
|
||||
sg.Radio('Starting', 'radioGreenDoors'),
|
||||
sg.Radio('Shuffled', 'radioGreenDoors')],
|
||||
[
|
||||
ui.Text('Yellow Doors (Level 3)'),
|
||||
ui.Radio('Standard', 'radioYellowDoors', default=True),
|
||||
ui.Radio('Starting', 'radioYellowDoors'),
|
||||
ui.Radio('Shuffled', 'radioYellowDoors')],
|
||||
sg.Text('Yellow Doors (Level 3)'),
|
||||
sg.Radio('Standard', 'radioYellowDoors', default=True),
|
||||
sg.Radio('Starting', 'radioYellowDoors'),
|
||||
sg.Radio('Shuffled', 'radioYellowDoors')],
|
||||
[
|
||||
ui.Text('Red Doors (Level 4)'),
|
||||
ui.Radio('Standard', 'radioRedDoors', default=True),
|
||||
ui.Radio('Starting', 'radioRedDoors'),
|
||||
ui.Radio('Shuffled', 'radioRedDoors')]]
|
||||
sg.Text('Red Doors (Level 4)'),
|
||||
sg.Radio('Standard', 'radioRedDoors', default=True),
|
||||
sg.Radio('Starting', 'radioRedDoors'),
|
||||
sg.Radio('Shuffled', 'radioRedDoors')]]
|
||||
settings = [
|
||||
[
|
||||
ui.Text('Difficulty'),
|
||||
ui.Slider(range=(0, 5), orientation='h', tooltip=tt_difficulty, key='Difficulty')],
|
||||
sg.Text('Difficulty'),
|
||||
sg.Slider(range=(0, 5), orientation='h', tooltip=tt_difficulty, key='-DIFFICULTY-')],
|
||||
[
|
||||
ui.Checkbox(text='Major/minor item split', key='MajorMinor', tooltip=tt_itempool)],
|
||||
sg.Checkbox(text='Generate race seed', key='-RACE-', tooltip=tt_race)],
|
||||
[
|
||||
ui.Checkbox(text='Missile upgrades enable Missiles', key='MissilesWithoutMainData', tooltip=tt_missileswithupgrades)],
|
||||
sg.Checkbox(text='Hide item graphics', key='-HIDEITEMS-', tooltip=tt_hide_items)],
|
||||
[
|
||||
ui.Checkbox(text='Enable Power Bombs without Bombs', key='PowerBombsWithoutBombs', tooltip=tt_pbswithoutbombs)],
|
||||
sg.Checkbox(text='Major/minor item split', key='-MAJORMINOR-', tooltip=tt_major_minor)],
|
||||
[
|
||||
ui.Checkbox(text='Damage runs', key='DamageRuns', tooltip=tt_damageruns)],
|
||||
sg.Checkbox(text='Missile upgrades enable Missiles', key='-MISSILEDATA-', tooltip=tt_missile_data)],
|
||||
[
|
||||
ui.Checkbox(text='Split security levels', key='SplitSecurity', tooltip=tt_splitsecurity)],
|
||||
sg.Checkbox(text='Enable Power Bombs without Bombs', key='-PBDATA-', tooltip=tt_pb_data)],
|
||||
[
|
||||
ui.Checkbox(text='Sector Shuffle', key='SectorShuffle', tooltip=tt_SectorShuffle)],
|
||||
sg.Checkbox(text='Hazard runs', key='-HAZARDRUNS-', tooltip=tt_hazard_runs)],
|
||||
[
|
||||
ui.Checkbox(text='Hide item graphics', key='HideItems', tooltip=tt_HideItems)],
|
||||
sg.Checkbox(text='Split security levels', key='-SPLITSECURITY-', tooltip=tt_split_security)],
|
||||
[
|
||||
ui.Checkbox(text='Race seed', key='RaceSeed', tooltip=tt_race)]]
|
||||
tabLayout = [
|
||||
sg.Text(text='Sector Shuffle:')],
|
||||
[
|
||||
ui.TabGroup([
|
||||
sg.Checkbox(text='Shuffle Sectors', key='-SHUFFLESECTORS-', tooltip=tt_shuffle_sectors),
|
||||
sg.Checkbox(text='Shuffle Tubes', key='-SHUFFLETUBES-', tooltip=tt_shuffle_tubes)]]
|
||||
cosmetic = [
|
||||
[
|
||||
sg.Text('Palette Shuffle')],
|
||||
[
|
||||
sg.Checkbox(text='Tilesets', key='-PALTILESETS-')],
|
||||
[
|
||||
sg.Checkbox(text='Sprites', key='-PALSPRITES-')],
|
||||
[
|
||||
sg.Checkbox(text='Suits', key='-PALSUITS-')],
|
||||
[
|
||||
sg.Checkbox(text='Beams', key='-PALBEAMS-')]]
|
||||
tab_layout = [
|
||||
[
|
||||
sg.TabGroup([
|
||||
[
|
||||
ui.Tab('Logic', settings)]], tab_location='topleft')]]
|
||||
sg.Tab('Logic', settings)],
|
||||
[
|
||||
sg.Tab('Cosmetic', cosmetic)]], tab_location='topleft', expand_x=True)]]
|
||||
layout = [
|
||||
[
|
||||
ui.Text('Seed value'),
|
||||
ui.Input(key='Seed')],
|
||||
sg.Text('Seed value'),
|
||||
sg.Input(key='-SEED-')],
|
||||
[
|
||||
tabLayout],
|
||||
tab_layout],
|
||||
[
|
||||
ui.Text('Number of Seeds to generate:'),
|
||||
ui.Input(key='Num', size=5, justification='center', enable_events=True),
|
||||
ui.Push(),
|
||||
ui.Checkbox(text='Create patch', key='Patch', tooltip=tt_createpatch),
|
||||
ui.Button(button_text='Generate', bind_return_key=True)]]
|
||||
window = ui.Window('Open Metroid Fusion Open Randomizer', layout)
|
||||
fileName = str()
|
||||
finishGenerating = False
|
||||
oldNum = str()
|
||||
sg.Text('Number of Seeds to generate:'),
|
||||
sg.Input(key='-NUM-', size=5, justification='center', enable_events=True),
|
||||
sg.Push(),
|
||||
sg.Checkbox(text='Create patch', key='-PATCH-', tooltip=tt_patch),
|
||||
sg.Button(button_text='Generate', bind_return_key=True)]]
|
||||
window = sg.Window('Metroid Fusion Open Randomizer', layout, icon=str(Path(__file__).parent / 'data' / 'MFOR.ico'))
|
||||
file_name = str()
|
||||
finish_generating = False
|
||||
old_num = str()
|
||||
disable_exceptions = (0, 'Logic', 'Cosmetic')
|
||||
(event, values) = window.read()
|
||||
|
||||
while True:
|
||||
(event, values) = window.read()
|
||||
if event == ui.WINDOW_CLOSED:
|
||||
if event == sg.WINDOW_CLOSED:
|
||||
break
|
||||
|
||||
if event == 'Num':
|
||||
if len(values['Num']) > 3:
|
||||
window['Num'].update(oldNum)
|
||||
|
||||
elif event == '-NUM-':
|
||||
if len(values['-NUM-']) > 3:
|
||||
window['-NUM-'].update(old_num)
|
||||
for x in range(4):
|
||||
if x < len(values['Num']):
|
||||
if values['Num'][x] not in '0123456789':
|
||||
window['Num'].update(oldNum)
|
||||
if x < len(values['-NUM-']):
|
||||
if values['-NUM-'][x] not in '0123456789':
|
||||
values['-NUM-'].update(oldNum)
|
||||
break
|
||||
else:
|
||||
oldNum = values['Num']
|
||||
oldNum = values['-NUM-']
|
||||
|
||||
if event == 'Generate':
|
||||
basegame = ui.popup_get_file('Choose base game', no_titlebar=True, file_types=[('GBA File', '*.gba')], history=True, history_setting_filename=os.path.join('.', 'settings.json'))
|
||||
if basegame == '':
|
||||
ui.popup('Please select a Metroid Fusion (U) rom.', title='No source rom selected')
|
||||
if basegame != None and basegame != '':
|
||||
checksum = fileHash(basegame)
|
||||
base_game = sg.popup_get_file('Choose base game', default_path=str(Path.cwd()), no_titlebar=True, file_types=[('GBA File', '*.gba')], history=True, history_setting_filename=str(Path.cwd() / 'settings.json'))
|
||||
if base_game == '':
|
||||
sg.popup('Please select a Metroid Fusion (U) rom.', title='No source rom selected')
|
||||
if base_game != None and base_game != '':
|
||||
checksum = file_hash(base_game)
|
||||
if checksum != 1819625372:
|
||||
ui.popup('Only Metroid Fusion (U) is supported.\nCheck the CRC32 value: it should be 6C75479C', title='Bad Checksum')
|
||||
sg.popup('Only Metroid Fusion (U) is supported.\nCheck the CRC32 value: it should be 6C75479C', title='Bad Checksum')
|
||||
else:
|
||||
values.update({
|
||||
'Debug': debug })
|
||||
threading.Thread(target=rando_thread, args=[window, values], daemon=True).start()
|
||||
window['Difficulty'].update(disabled=True)
|
||||
window['MajorMinor'].update(disabled=True)
|
||||
window['MissilesWithoutMainData'].update(disabled=True)
|
||||
window['PowerBombsWithoutBombs'].update(disabled=True)
|
||||
window['DamageRuns'].update(disabled=True)
|
||||
window['SplitSecurity'].update(disabled=True)
|
||||
window['SectorShuffle'].update(disabled=True)
|
||||
window['HideItems'].update(disabled=True)
|
||||
window['Seed'].update(disabled=True)
|
||||
window['RaceSeed'].update(disabled=True)
|
||||
window['Num'].update(disabled=True)
|
||||
window['Patch'].update(disabled=True)
|
||||
window['Generate'].update(disabled=True)
|
||||
|
||||
|
||||
while generating:
|
||||
ui.popup_animated(ui.DEFAULT_BASE64_LOADING_GIF, 'Generating game, please wait...', time_between_frames=20)
|
||||
sg.popup_animated(sg.DEFAULT_BASE64_LOADING_GIF, 'Generating game, please wait...', time_between_frames=20)
|
||||
window.Refresh()
|
||||
|
||||
if finishGenerating:
|
||||
ui.popup_animated(None)
|
||||
if failedgen:
|
||||
ui.popup('Could not generate a game with the current settings. Try changing your settings.', title='Metroid Fusion Open Randomizer')
|
||||
elif randoerror:
|
||||
ui.popup('An error occurred, no game was generated.', title='Error')
|
||||
elif ui.Input.get(window['Num']) != '':
|
||||
if int(ui.Input.get(window['Num'])) > 1:
|
||||
ui.popup('Multiple games have been added to the seeds folder.', title='Success!')
|
||||
|
||||
if finish_generating:
|
||||
sg.popup_animated(None)
|
||||
if failed_gen:
|
||||
sg.popup('Could not generate a game with the current settings. Try changing your settings.', title='Metroid Fusion Open Randomizer')
|
||||
elif rando_error:
|
||||
sg.popup('An error occurred, no game was generated.', title='Error')
|
||||
elif sg.Input.get(window['-NUM-']) != '':
|
||||
if int(sg.Input.get(window['-NUM-'])) > 1:
|
||||
sg.popup('Multiple games have been added to the seeds folder.', title='Success!')
|
||||
else:
|
||||
ui.popup('{}\nhas been added to the seeds folder.'.format(fileName), title='Success!')
|
||||
sg.popup(f'''{file_name}\nhas been added to the seeds folder.''', title='Success!')
|
||||
else:
|
||||
ui.popup('{}\nhas been added to the seeds folder.'.format(fileName), title='Success!')
|
||||
window['Difficulty'].update(disabled=False)
|
||||
window['MajorMinor'].update(disabled=False)
|
||||
window['MissilesWithoutMainData'].update(disabled=False)
|
||||
window['PowerBombsWithoutBombs'].update(disabled=False)
|
||||
window['DamageRuns'].update(disabled=False)
|
||||
window['SplitSecurity'].update(disabled=False)
|
||||
window['SectorShuffle'].update(disabled=False)
|
||||
window['HideItems'].update(disabled=False)
|
||||
window['Seed'].update(disabled=False)
|
||||
window['RaceSeed'].update(disabled=False)
|
||||
window['Num'].update(disabled=False)
|
||||
window['Patch'].update(disabled=False)
|
||||
window['Generate'].update(disabled=False)
|
||||
finishGenerating = False
|
||||
window.close()
|
||||
sg.popup(f'''{file_name}\nhas been added to the seeds folder.''', title='Success!')
|
||||
finish_generating = False
|
||||
|
||||
window.close()
|
||||
|
|
|
|||
284
MFOR.py
284
MFOR.py
|
|
@ -7,79 +7,225 @@
|
|||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
|
||||
# Source Generated with Decompyle++
|
||||
# File: MFOR.pyc (Python 3.8)
|
||||
|
||||
import argparse
|
||||
import os
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('-seed', help='Seed value, optional')
|
||||
parser.add_argument('-race', default=False, action='store_true', help='Generate race rom (no spoiler log)')
|
||||
parser.add_argument('-patch', default=False, action='store_true', help='Generate BPS patch with seed (for easy sharing)')
|
||||
parser.add_argument('-diff', help='Trick difficulty level (0-5, default 0)')
|
||||
parser.add_argument('-limit', default=False, action='store_true', help='Major/minor item pool')
|
||||
parser.add_argument('-missiles', default=False, action='store_true', help='Missile upgrades enable the missile launcher (default off)')
|
||||
parser.add_argument('-pbs', default=False, action='store_true', help='Enable Power Bombs without normal Bombs (default off)')
|
||||
parser.add_argument('-damage-runs', default=False, action='store_true', help='Allow logical damage runs (default off)')
|
||||
parser.add_argument('-split-security', default=False, action='store_true', help='Separated Security levels (default off)')
|
||||
parser.add_argument('-sector-shuffle', default=False, action='store_true', help='Randomly shuffle the arrangement of the Sectors')
|
||||
parser.add_argument('-rom', help='Base rom (Metroid Fusion (U).gba)')
|
||||
parser.add_argument('-nogui', default=False, action='store_true', help='Termnial based seed generation (this)')
|
||||
parser.add_argument('-num', help='Number of seeds to generate (default 1)')
|
||||
parser.add_argument('-hideitems', default=False, action='store_true', help='All items use ? tank graphics')
|
||||
parser.add_argument('-debug', default=False, action='store_true', help='Debugging, for my own use')
|
||||
args = parser.parse_args()
|
||||
import random
|
||||
import sys
|
||||
import zlib
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
version = '2024.02.10'
|
||||
|
||||
if not os.path.exists(os.path.join('.', 'data')):
|
||||
os.mkdir('data')
|
||||
if not os.path.exists(os.path.join('.', 'seeds')):
|
||||
os.mkdir('seeds')
|
||||
if not os.path.exists(os.path.join('.', 'spoilers')):
|
||||
os.mkdir('spoilers')
|
||||
if not args.debug:
|
||||
args.debug = False
|
||||
if args.nogui:
|
||||
settings = dict()
|
||||
settings.update({
|
||||
'Seed': None })
|
||||
if args.seed:
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=f'''Metroid Fusion Open Randomizer v{version}''')
|
||||
parser.add_argument('-file', help='Path to unmodified game (Metroid Fusion (U).gba)')
|
||||
parser.add_argument('-seed', default=None, help='Optional seed value')
|
||||
parser.add_argument('-difficulty', choices=['0','1','2','3','4','5','r'], default='0', help='Trick difficulty level 0-5 (default 0)')
|
||||
parser.add_argument('-race', choices=['t','f','r'], default='f', help='Generate race seed (no spoiler log)')
|
||||
parser.add_argument('-hidden', choices=['t','f','r'], default='f', help='All items use ? tank graphics')
|
||||
parser.add_argument('-limit', choices=['t','f','r'], default='f', help='Major/minor item pool')
|
||||
parser.add_argument('-missiles', choices=['t','f','r'], default='f', help='Missile upgrades enable the Missile launcher (default f)')
|
||||
parser.add_argument('-bombs', choices=['t','f','r'], default='f', help='Enable Power Bombs without normal Bombs (default f)')
|
||||
parser.add_argument('-hazards', choices=['t','f','r'], default='f', help='Logic allows hazard runs (default f)')
|
||||
parser.add_argument('-security', choices=['t','f','r'], default='f', help='Split security: if split, security stations only unlock their specific security level. By default, higher level security stations will unlock all lesser security levels.')
|
||||
parser.add_argument('-sectors', choices=['t','f','r'], default='f', help='Choose whether to shuffle the arrangement of the Sectors')
|
||||
parser.add_argument('-tubes', choices=['t','f','r'], default='f', help='Choose whether to shuffle the tube connections between the Sectors')
|
||||
parser.add_argument('-palettes', help='Enable palette shuffle: [t]ilesets, [b]eams, [s]uits, s[p]rites')
|
||||
parser.add_argument('-num', default=1, help='Number of seeds to generate')
|
||||
parser.add_argument('-patch', default=False, action='store_true', help='Generate BPS patch for easy sharing')
|
||||
args = parser.parse_args()
|
||||
|
||||
if not hasattr(args, 'debug'):
|
||||
args.debug = False
|
||||
if args.file:
|
||||
start_randomizer = start_randomizer
|
||||
import Randomizer
|
||||
settings = dict()
|
||||
logic = list()
|
||||
settings.update({
|
||||
'Seed': args.seed })
|
||||
settings.update({
|
||||
'Debug': args.debug })
|
||||
settings.update({
|
||||
'Patch': args.patch })
|
||||
if not args.diff:
|
||||
args.diff = 0
|
||||
if int(args.diff) <= 0:
|
||||
args.diff = 0
|
||||
elif int(args.diff) >= 5:
|
||||
args.diff = 5
|
||||
settings.update({
|
||||
'Difficulty': args.diff })
|
||||
settings.update({
|
||||
'MajorMinor': args.limit })
|
||||
settings.update({
|
||||
'MissilesWithoutMainData': args.missiles })
|
||||
settings.update({
|
||||
'PowerBombsWithoutBombs': args.pbs })
|
||||
settings.update({
|
||||
'DamageRuns': args.damage_runs })
|
||||
settings.update({
|
||||
'SplitSecurity': args.split_security })
|
||||
settings.update({
|
||||
'SectorShuffle': args.sector_shuffle })
|
||||
settings.update({
|
||||
'HideItems': args.hideitems })
|
||||
settings.update({
|
||||
'RaceSeed': args.race })
|
||||
settings.update({
|
||||
'Num': None })
|
||||
if args.num:
|
||||
'-SEED-': args.seed })
|
||||
if args.difficulty == 'r':
|
||||
args.difficulty = random.randrange(6)
|
||||
logic.append(f'''Difficulty: {args.difficulty}''')
|
||||
else:
|
||||
args.difficulty = int(args.difficulty)
|
||||
if args.race == 'r':
|
||||
args.race = random.choice([
|
||||
True,
|
||||
False])
|
||||
logic.append(f'''Race: {args.race}''')
|
||||
elif args.race == 't':
|
||||
args.race = True
|
||||
else:
|
||||
args.race = False
|
||||
if args.hidden == 'r':
|
||||
args.hidden = random.choice([
|
||||
True,
|
||||
False])
|
||||
logic.append(f'''Hide items: {args.hidden}''')
|
||||
elif args.hidden == 't':
|
||||
args.hidden = True
|
||||
else:
|
||||
args.hidden = False
|
||||
if args.limit == 'r':
|
||||
args.limit = random.choice([
|
||||
True,
|
||||
False])
|
||||
logic.append(f'''Major/minor: {args.limit}''')
|
||||
elif args.limit == 't':
|
||||
args.limit = True
|
||||
else:
|
||||
args.limit = False
|
||||
if args.missiles == 'r':
|
||||
args.missiles = random.choice([
|
||||
True,
|
||||
False])
|
||||
if args.missiles:
|
||||
pass
|
||||
# FIXME: whatever this is
|
||||
# 'any'(f'''1{'main'}''')
|
||||
elif args.missiles == 't':
|
||||
args.missiles = True
|
||||
else:
|
||||
args.missiles = False
|
||||
if args.bombs == 'r':
|
||||
args.bombs = random.choice([
|
||||
True,
|
||||
False])
|
||||
if args.bombs:
|
||||
pass
|
||||
# FIXME: whatever this is
|
||||
# 'data'(f'''1{'bombs'}''')
|
||||
elif args.bombs == 't':
|
||||
args.bombs = True
|
||||
else:
|
||||
args.bombs = False
|
||||
if args.hazards == 'r':
|
||||
args.hazards = random.choice([
|
||||
True,
|
||||
False])
|
||||
logic.append(f'''Hazard runs: {args.hazards}''')
|
||||
elif args.hazards == 't':
|
||||
args.hazards = True
|
||||
else:
|
||||
args.hazards = False
|
||||
if args.security == 'r':
|
||||
args.security = random.choice([
|
||||
True,
|
||||
False])
|
||||
logic.append(f'''Split security: {args.security}''')
|
||||
elif args.security == 't':
|
||||
args.security = True
|
||||
else:
|
||||
args.security = False
|
||||
if args.sectors == 'r':
|
||||
args.sectors = random.choice([
|
||||
True,
|
||||
False])
|
||||
logic.append(f'''Shuffle Sectors: {args.sectors}''')
|
||||
elif args.sectors == 't':
|
||||
args.sectors = True
|
||||
else:
|
||||
args.sectors = False
|
||||
if args.tubes == 'r':
|
||||
args.tubes = random.choice([
|
||||
True,
|
||||
False])
|
||||
logic.append(f'''Shuffle tubes: {args.tubes}''')
|
||||
elif args.tubes == 't':
|
||||
args.tubes = True
|
||||
else:
|
||||
args.tubes = False
|
||||
|
||||
settings.update({
|
||||
'Num': int(args.num) })
|
||||
from Randomizer import start_randomizer
|
||||
start_randomizer(args.rom, settings)
|
||||
else:
|
||||
import GUI as gui
|
||||
gui.main_window(args.debug)
|
||||
'-DIFFICULTY-': args.difficulty })
|
||||
settings.update({
|
||||
'-RACE-': args.race })
|
||||
settings.update({
|
||||
'-HIDEITEMS-': args.hidden })
|
||||
settings.update({
|
||||
'-MAJORMINOR-': args.limit })
|
||||
settings.update({
|
||||
'-MISSILEDATA-': args.missiles })
|
||||
settings.update({
|
||||
'-PBDATA-': args.bombs })
|
||||
settings.update({
|
||||
'-HAZARDRUNS-': args.hazards })
|
||||
settings.update({
|
||||
'-SPLITSECURITY-': args.security })
|
||||
settings.update({
|
||||
'-SHUFFLESECTORS-': args.sectors })
|
||||
settings.update({
|
||||
'-SHUFFLETUBES-': args.tubes })
|
||||
if args.num:
|
||||
args.num = int(args.num)
|
||||
if args.num < 1:
|
||||
args.num = 1
|
||||
settings.update({
|
||||
'-NUM-': args.num })
|
||||
else:
|
||||
settings.update({
|
||||
'-NUM-': 1 })
|
||||
settings.update({
|
||||
'-PATCH-': args.patch })
|
||||
settings.update({
|
||||
'Debug': args.debug })
|
||||
settings.update({
|
||||
'-PALTILESETS-': False })
|
||||
settings.update({
|
||||
'-PALSPRITES-': False })
|
||||
settings.update({
|
||||
'-PALSUITS-': False })
|
||||
settings.update({
|
||||
'-PALBEAMS-': False })
|
||||
if args.palettes:
|
||||
if 't' in args.palettes:
|
||||
settings.update({
|
||||
'-PALTILESETS-': True })
|
||||
if 'b' in args.palettes:
|
||||
settings.update({
|
||||
'-PALBEAMS-': True })
|
||||
if 's' in args.palettes:
|
||||
settings.update({
|
||||
'-PALSUITS-': True })
|
||||
if 'p' in args.palettes:
|
||||
settings.update({
|
||||
'-PALSPRITES-': True })
|
||||
# FIXME: whatever this is
|
||||
# settings = (lambda .0 = None: pass# WARNING: Decompyle incomplete
|
||||
#)(sorted(settings.keys()))
|
||||
start_randomizer(args.file, settings)
|
||||
if len(logic) > 0:
|
||||
print('\nRandom settings:')
|
||||
else:
|
||||
import GUI
|
||||
GUI.main_window(args.debug)
|
||||
|
||||
|
||||
def _init():
|
||||
checksum = file_hash(Path(__file__).parent / 'data' / 'MFOR.bps')
|
||||
if checksum != 558161692:
|
||||
sys.exit('Error: Core files could not be read. Please go to https://metroidconstruction.com/ and re-download MFOR.')
|
||||
Path(Path.cwd() / 'seeds').mkdir(exist_ok=True)
|
||||
Path(Path.cwd() / 'spoilers').mkdir(exist_ok=True)
|
||||
|
||||
|
||||
def file_hash(file):
|
||||
checksum = 0
|
||||
try:
|
||||
with open(file, 'rb') as source:
|
||||
while True:
|
||||
s = source.read(65536)
|
||||
if not s:
|
||||
break
|
||||
checksum = zlib.crc32(s, checksum)
|
||||
except FileNotFoundError:
|
||||
sys.exit('Error:', file, 'could not be opened.')
|
||||
return checksum & 0xFFFFFFFF
|
||||
|
||||
if __name__ == '__main__':
|
||||
_init()
|
||||
main()
|
||||
|
|
|
|||
BIN
data/MFOR.bps
BIN
data/MFOR.bps
Binary file not shown.
BIN
data/MFOR.ico
Normal file
BIN
data/MFOR.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 728 KiB |
|
|
@ -1017,7 +1017,7 @@
|
|||
"Type": "Boss"
|
||||
},
|
||||
{
|
||||
"Name": "Box-2",
|
||||
"Name": "BOX-2",
|
||||
"Room": "0x10",
|
||||
"Type": "Boss"
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue