2023-10-19 22:41:11 +00:00
# OpenMFOR
# credits manually reinstated due to the comments being lost from the object code decompilation
# Original release is Copyright (C) 2022 Kazuto88
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
2023-10-10 10:13:02 +00:00
# Source Generated with Decompyle++
# File: GUI.pyc (Python 3.8)
import PySimpleGUI as ui
import zlib
import time
import threading
import os
ui . 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. '
generating = False
2023-10-11 09:51:12 +00:00
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
2023-10-10 10:13:02 +00:00
def rando_thread ( window = None , values = None ) :
2024-02-06 03:28:00 +00:00
global fileName , basegame , failedgen , randoerror , generating , finishGenerating
2023-10-10 10:13:02 +00:00
values . update ( {
' Difficulty ' : int ( values . get ( ' Difficulty ' ) ) } )
if values [ ' Num ' ] :
values . update ( {
' Num ' : int ( values . get ( ' Num ' ) ) } )
else :
values . update ( {
' Num ' : 1 } )
if values [ ' Num ' ] < 1 :
values . update ( {
' Num ' : 1 } )
values . pop ( 0 )
failedgen = False
randoerror = False
generating = True
from Randomizer import start_randomizer
if values [ ' Debug ' ] :
fileName = start_randomizer ( basegame , 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
generating = False
finishGenerating = True
def main_window ( debug ) :
2024-02-06 03:28:00 +00:00
global fileName , basegame , generating , finishGenerating
2023-10-10 10:13:02 +00:00
itemPool = [
[
ui . Text ( ' Charge Beam ' ) ,
ui . Radio ( ' Shuffled ' , ' radioChargeBeam ' , default = True ) ,
ui . Radio ( ' Starting ' , ' radioChargeBeam ' ) ,
ui . Radio ( ' Disabled ' , ' radioChargeBeam ' ) ] ,
[
ui . Text ( ' Wide Beam ' ) ,
ui . Radio ( ' Shuffled ' , ' radioWideBeam ' , default = True ) ,
ui . Radio ( ' Starting ' , ' radioWideBeam ' ) ,
ui . Radio ( ' Disabled ' , ' radioWideBeam ' ) ] ,
[
ui . Text ( ' Plasma Beam ' ) ,
ui . Radio ( ' Shuffled ' , ' radioPlasmaBeam ' , default = True ) ,
ui . Radio ( ' Starting ' , ' radioPlasmaBeam ' ) ,
ui . Radio ( ' Disabled ' , ' radioPlasmaBeam ' ) ] ,
[
ui . Text ( ' Wave Beam ' ) ,
ui . Radio ( ' Shuffled ' , ' radioWaveBeam ' , default = True ) ,
ui . Radio ( ' Starting ' , ' radioWaveBeam ' ) ,
ui . Radio ( ' Disabled ' , ' radioWaveBeam ' ) ] ,
[
ui . Text ( ' Ice Beam ' ) ,
ui . Radio ( ' Shuffled ' , ' radioIceBeam ' , default = True ) ,
ui . Radio ( ' Starting ' , ' radioIceBeam ' ) ,
ui . Radio ( ' Disabled ' , ' radioIceBeam ' ) ] ,
[
ui . Text ( ' Missile Data ' ) ,
ui . Radio ( ' Shuffled ' , ' radioMissileData ' , default = True ) ,
ui . Radio ( ' Starting ' , ' radioMissileData ' ) ,
ui . Radio ( ' Disabled ' , ' radioMissileData ' ) ] ,
[
ui . Text ( ' Super Missile Data ' ) ,
ui . Radio ( ' Shuffled ' , ' radioSuperMissile ' , default = True ) ,
ui . Radio ( ' Starting ' , ' radioSuperMissile ' ) ,
ui . Radio ( ' Disabled ' , ' radioSuperMissile ' ) ] ,
[
ui . Text ( ' Ice Missile Data ' ) ,
ui . Radio ( ' Shuffled ' , ' radioIceMissile ' , default = True ) ,
ui . Radio ( ' Starting ' , ' radioIceMissile ' ) ,
ui . Radio ( ' Disabled ' , ' radioIceMissile ' ) ] ,
[
ui . Text ( ' Diffusion Data ' ) ,
ui . Radio ( ' Shuffled ' , ' radioDiffusion ' , default = True ) ,
ui . Radio ( ' Starting ' , ' radioDiffusion ' ) ,
ui . Radio ( ' Disabled ' , ' radioDiffusion ' ) ] ,
[
ui . Text ( ' Bombs ' ) ,
ui . Radio ( ' Shuffled ' , ' radioBombs ' , default = True ) ,
ui . Radio ( ' Starting ' , ' radioBombs ' ) ,
ui . Radio ( ' Disabled ' , ' radioBombs ' ) ] ,
[
ui . Text ( ' Power Bomb Data ' ) ,
ui . Radio ( ' Shuffled ' , ' radioPowerBombData ' , default = True ) ,
ui . Radio ( ' Starting ' , ' radioPowerBombData ' ) ,
ui . Radio ( ' Disabled ' , ' radioPowerBombData ' ) ] ,
[
ui . Text ( ' Hi-Jump Boots ' ) ,
ui . Radio ( ' Shuffled ' , ' radioHiJump ' , default = True ) ,
ui . Radio ( ' Starting ' , ' radioHiJump ' ) ,
ui . Radio ( ' Disabled ' , ' radioHiJump ' ) ] ,
[
ui . Text ( ' Speed Booster ' ) ,
ui . Radio ( ' Shuffled ' , ' radioSpeedBooster ' , default = True ) ,
ui . Radio ( ' Starting ' , ' radioSpeedBooster ' ) ,
ui . Radio ( ' Disabled ' , ' radioSpeedBooster ' ) ] ,
[
ui . Text ( ' Space Jump ' ) ,
ui . Radio ( ' Shuffled ' , ' radioSpaceJump ' , default = True ) ,
ui . Radio ( ' Starting ' , ' radioSpaceJump ' ) ,
ui . Radio ( ' Disabled ' , ' radioSpaceJump ' ) ] ,
[
ui . Text ( ' Screw Attack ' ) ,
ui . Radio ( ' Shuffled ' , ' radioScrewAttack ' , default = True ) ,
ui . Radio ( ' Starting ' , ' radioScrewAttack ' ) ,
ui . Radio ( ' Disabled ' , ' radioScrewAttack ' ) ] ,
[
ui . Text ( ' Varia Suit ' ) ,
ui . Radio ( ' Shuffled ' , ' radioVariaSuit ' , default = True ) ,
ui . Radio ( ' Starting ' , ' radioVariaSuit ' ) ,
ui . Radio ( ' Disabled ' , ' radioVariaSuit ' ) ] ,
[
ui . Text ( ' Gravity Suit ' ) ,
ui . Radio ( ' Shuffled ' , ' radioGravitySuit ' , default = True ) ,
ui . Radio ( ' Starting ' , ' radioGravitySuit ' ) ,
ui . Radio ( ' Disabled ' , ' radioGravitySuit ' ) ] ,
[
ui . Text ( ' Morph Ball ' ) ,
ui . Radio ( ' Shuffled ' , ' radioMorphBall ' , default = True ) ,
ui . Radio ( ' Starting ' , ' radioMorphBall ' ) ,
ui . Radio ( ' Disabled ' , ' radioMorphBall ' ) ] ,
[
ui . Text ( ' Blue Doors (Level 1) ' ) ,
ui . Radio ( ' Standard ' , ' radioBlueDoors ' , default = True ) ,
ui . Radio ( ' Starting ' , ' radioBlueDoors ' ) ,
ui . Radio ( ' Shuffled ' , ' radioBlueDoors ' ) ] ,
[
ui . Text ( ' Green Doors (Level 2) ' ) ,
ui . Radio ( ' Standard ' , ' radioGreenDoors ' , default = True ) ,
ui . Radio ( ' Starting ' , ' radioGreenDoors ' ) ,
ui . Radio ( ' Shuffled ' , ' radioGreenDoors ' ) ] ,
[
ui . Text ( ' Yellow Doors (Level 3) ' ) ,
ui . Radio ( ' Standard ' , ' radioYellowDoors ' , default = True ) ,
ui . Radio ( ' Starting ' , ' radioYellowDoors ' ) ,
ui . Radio ( ' Shuffled ' , ' radioYellowDoors ' ) ] ,
[
ui . Text ( ' Red Doors (Level 4) ' ) ,
ui . Radio ( ' Standard ' , ' radioRedDoors ' , default = True ) ,
ui . Radio ( ' Starting ' , ' radioRedDoors ' ) ,
ui . Radio ( ' Shuffled ' , ' radioRedDoors ' ) ] ]
settings = [
[
ui . Text ( ' Difficulty ' ) ,
ui . Slider ( range = ( 0 , 5 ) , orientation = ' h ' , tooltip = tt_difficulty , key = ' Difficulty ' ) ] ,
[
ui . Checkbox ( text = ' Major/minor item split ' , key = ' MajorMinor ' , tooltip = tt_itempool ) ] ,
[
ui . Checkbox ( text = ' Missile upgrades enable Missiles ' , key = ' MissilesWithoutMainData ' , tooltip = tt_missileswithupgrades ) ] ,
[
ui . Checkbox ( text = ' Enable Power Bombs without Bombs ' , key = ' PowerBombsWithoutBombs ' , tooltip = tt_pbswithoutbombs ) ] ,
[
ui . Checkbox ( text = ' Damage runs ' , key = ' DamageRuns ' , tooltip = tt_damageruns ) ] ,
[
ui . Checkbox ( text = ' Split security levels ' , key = ' SplitSecurity ' , tooltip = tt_splitsecurity ) ] ,
[
ui . Checkbox ( text = ' Sector Shuffle ' , key = ' SectorShuffle ' , tooltip = tt_SectorShuffle ) ] ,
[
ui . Checkbox ( text = ' Hide item graphics ' , key = ' HideItems ' , tooltip = tt_HideItems ) ] ,
[
ui . Checkbox ( text = ' Race seed ' , key = ' RaceSeed ' , tooltip = tt_race ) ] ]
tabLayout = [
[
ui . TabGroup ( [
[
ui . Tab ( ' Logic ' , settings ) ] ] , tab_location = ' topleft ' ) ] ]
layout = [
[
ui . Text ( ' Seed value ' ) ,
ui . Input ( key = ' Seed ' ) ] ,
[
tabLayout ] ,
[
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 ( )
2024-02-04 04:21:29 +00:00
while True :
( event , values ) = window . read ( )
if event == ui . WINDOW_CLOSED :
break
2024-02-06 03:28:00 +00:00
if event == ' Num ' :
2024-02-04 04:21:29 +00:00
if len ( values [ ' Num ' ] ) > 3 :
2023-10-10 10:13:02 +00:00
window [ ' Num ' ] . update ( oldNum )
2024-02-04 04:21:29 +00:00
for x in range ( 4 ) :
if x < len ( values [ ' Num ' ] ) :
if values [ ' Num ' ] [ x ] not in ' 0123456789 ' :
window [ ' Num ' ] . update ( oldNum )
break
else :
oldNum = values [ ' Num ' ]
2024-02-06 03:28:00 +00:00
if event == ' Generate ' :
2024-02-04 04:21:29 +00:00
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 )
if checksum != 1819625372 :
ui . popup ( ' Only Metroid Fusion (U) is supported. \n Check 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 )
2024-02-06 03:28:00 +00:00
while generating :
2024-02-04 04:21:29 +00:00
ui . popup_animated ( ui . DEFAULT_BASE64_LOADING_GIF , ' Generating game, please wait... ' , time_between_frames = 20 )
window . Refresh ( )
2024-02-06 03:28:00 +00:00
if finishGenerating :
2024-02-04 04:21:29 +00:00
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! ' )
else :
ui . popup ( ' {} \n has been added to the seeds folder. ' . format ( fileName ) , title = ' Success! ' )
2023-10-10 10:13:02 +00:00
else :
ui . popup ( ' {} \n has been added to the seeds folder. ' . format ( fileName ) , title = ' Success! ' )
2024-02-04 04:21:29 +00:00
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
2023-10-10 10:13:02 +00:00
window . close ( )