Compare commits
8 commits
2024.02.10
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 2a73e487a5 | |||
| 1523860c9a | |||
| a36c9a95f0 | |||
| fe6fa75972 | |||
| 672cf3ca23 | |||
| 01dee434bd | |||
| 367fdd75ec | |||
| 0c17440bde |
5 changed files with 72 additions and 36 deletions
2
GUI.py
2
GUI.py
|
|
@ -227,7 +227,7 @@ def main_window(debug):
|
|||
sg.Push(),
|
||||
sg.Checkbox(text='Create patch', key='-PATCH-', tooltip=tt_patch),
|
||||
sg.Button(button_text='Generate', bind_return_key=True)]]
|
||||
window = sg.Window('Open Metroid Fusion Open Randomizer', layout, icon=str(Path(__file__).parent / 'data' / 'MFOR.ico'))
|
||||
window = sg.Window('Open Metroid Fusion Open Randomizer', layout, icon=str(Path.cwd() / 'data' / 'MFOR.ico'))
|
||||
file_name = str()
|
||||
finish_generating = False
|
||||
old_num = str()
|
||||
|
|
|
|||
13
MFOR.py
13
MFOR.py
|
|
@ -146,12 +146,13 @@ def main():
|
|||
settings.update({"-PALSUITS-": True})
|
||||
if "p" in args.palettes:
|
||||
settings.update({"-PALSPRITES-": True})
|
||||
settings = {key: settings[key] for key in sorted(settings.keys())}
|
||||
start_randomizer(args.file, settings)
|
||||
if len(logic) > 0:
|
||||
print("\nRandom settings:")
|
||||
for item in logic:
|
||||
print(item)
|
||||
|
||||
settings = {key: settings[key] for key in sorted(settings.keys())}
|
||||
start_randomizer(args.file, settings)
|
||||
if len(logic) > 0:
|
||||
print("\nRandom settings:")
|
||||
for item in logic:
|
||||
print(item)
|
||||
|
||||
else:
|
||||
import GUI
|
||||
|
|
|
|||
|
|
@ -25,7 +25,8 @@ Caveat emptor: the project is already diverging from the original decompilation
|
|||
- [x] Reconstructing missing parts of code
|
||||
- [x] Patching
|
||||
- [x] Generating BPS patches (python-bps-continued used to apply base patch as it's platform independent, but FLIPS to generate BPS files)
|
||||
- [ ] Potentially merging/reimplementing the new features from v2024.02.10
|
||||
- [x] Potentially merging/reimplementing the new features from v2024.02.10
|
||||
- [ ] Merging the logic edits from v2024.02.10
|
||||
- [ ] Solver refactoring
|
||||
- [x] CI/CD for Windows frozen builds
|
||||
|
||||
|
|
@ -39,6 +40,10 @@ Caveat emptor: the project is already diverging from the original decompilation
|
|||
- ????
|
||||
- PROFIT
|
||||
|
||||
Prebuilt release builds might be available on the [releases](https://git.inabaudonge.reisen/OpenMFOR/OpenMFOR/releases) tab.
|
||||
|
||||
If you feel more inclined testing the tip of the development branches or playing with the logic, part of the following guide can be used on Windows too to run the randomizer from sources rather than PyInstaller packed executables.
|
||||
|
||||
## Install (any OS)
|
||||
|
||||
On *NIX OSes, the only strict prerequisites are Python 3.x and pip. For the GUI, sourcing `python3-tk` from your package manager is highly recommended.
|
||||
|
|
@ -71,7 +76,6 @@ The randomizer currently works **only** with the USA (and, by proxy, the Austral
|
|||
## Help
|
||||
|
||||
* [OpenMFOR Discord guild](https://discord.gg/QV3p8MWKab) since we've been told to refrain to bring this up on the wider community server over ongoing diplomacy issues.
|
||||
|
||||
* soon™ we might have an IRC channel or a Matrix group bridged to the Discord guild.
|
||||
|
||||
## Special Thanks
|
||||
|
|
@ -81,6 +85,7 @@ The randomizer currently works **only** with the USA (and, by proxy, the Austral
|
|||
- [tcprescott's python-bps-continued](https://github.com/tcprescott/python-bps-continued) since this makes at least rolling the seeds completely platform independent.
|
||||
- [Alcaro's Floating IPS](https://github.com/Alcaro/Flips)
|
||||
- Fedor Batogonov's [docker-pyinstaller](https://gitlab.com/batonogov/docker-pyinstaller) used by the CI/CD to make Windows builds on AppVeyor
|
||||
- The testers in the various Discord guilds that are spotting the massive scams before I do! (SkullAdult, Mr. Fox, baria, Fpiz_, jakoliath)
|
||||
|
||||
[Kazuto88](https://github.com/Kazuto88) being the original randomizer developer. The following lines are his special thanks to the people that contributed to making this a reality:
|
||||
|
||||
|
|
|
|||
|
|
@ -2188,15 +2188,15 @@ def randomize_game(graph):
|
|||
|
||||
MajorList = list(WeightedMajors.keys())
|
||||
if SeedSettings['-MISSILEDATA-']:
|
||||
WeightedMajors.update({'MainMissiles': 8})
|
||||
WeightedMajors.update({'SuperMissileItem': 8})
|
||||
WeightedMajors.update({'IceMissileItem': 8})
|
||||
WeightedMajors.update({'DiffusionItem': 8})
|
||||
WeightedMajors.update({'MainMissiles': 4})
|
||||
WeightedMajors.update({'SuperMissileItem': 4})
|
||||
WeightedMajors.update({'IceMissileItem': 4})
|
||||
WeightedMajors.update({'DiffusionItem': 4})
|
||||
if SeedSettings['-PBDATA-']:
|
||||
WeightedMajors.update({'Bombs': 10})
|
||||
WeightedMajors.update({'MainPowerBombs': 10})
|
||||
WeightedMajors.update({'Bombs': 3})
|
||||
WeightedMajors.update({'MainPowerBombs': 3})
|
||||
if SeedSettings['-HAZARDRUNS-']:
|
||||
WeightedMajors.update({'VariaSuit': 4})
|
||||
WeightedMajors.update({'VariaSuit': 3})
|
||||
MajorWeights = list(WeightedMajors.values())
|
||||
MajorWeights.pop(MajorList.index('Bombs'))
|
||||
MajorList.remove('Bombs')
|
||||
|
|
@ -2746,15 +2746,24 @@ def patch_game():
|
|||
roomEventOffset = int(sym.get('t_bossanddownloadevents'), 16)
|
||||
itemEventOffset = int(sym.get('t_obtainitemevents'), 16)
|
||||
securityOffset = int(sym.get('b_unlocklowerlevels'), 16)
|
||||
print('roomEventOffset: 0x{:06X}'.format(roomEventOffset))
|
||||
print('itemEventOffset: 0x{:06X}'.format(itemEventOffset))
|
||||
print('securityOffset: 0x{:06X}'.format(securityOffset))
|
||||
saxAnyOffset = int(sym.get('@t_saxany'), 16)
|
||||
spawnBox = int(sym.get('@spawnbox'), 16)
|
||||
spawnMegaCoreX = int(sym.get('@spawnmegacorex'), 16)
|
||||
print('Debug values')
|
||||
print(f'''roomEventOffset={roomEventOffset:06X}''')
|
||||
print(f'''itemEventOffset={itemEventOffset:06X}''')
|
||||
print(f'''securityOffset={securityOffset:06X}''')
|
||||
print(f'''saxAnyOffset={saxAnyOffset:06X}''')
|
||||
print(f'''spawnBox={spawnBox:06X}''')
|
||||
print(f'''spawnMegaCoreX={spawnMegaCoreX:06X}''')
|
||||
else:
|
||||
roomEventOffset = 8326320
|
||||
roomEventOffset = 8326304
|
||||
itemEventOffset = 5726112
|
||||
securityOffset = 479192
|
||||
saxAnyOffset = 395796
|
||||
spawnBox = 8326096
|
||||
spawnMegaCoreX = 8326260
|
||||
for area in RoomNodes:
|
||||
areaIndex = list(RoomNodes.keys()).index(area)
|
||||
for node in RoomNodes[area]:
|
||||
name = node.get('Name')
|
||||
nodeType = node.get('Type')
|
||||
|
|
@ -2778,6 +2787,7 @@ def patch_game():
|
|||
blockValue = 3
|
||||
else:
|
||||
blockValue = ItemList.index(itemName)
|
||||
|
||||
if blockValue < 2:
|
||||
blockValue = blockValue ^ 1
|
||||
elif blockValue > 2:
|
||||
|
|
@ -2791,6 +2801,7 @@ def patch_game():
|
|||
blockValue = 7
|
||||
else:
|
||||
blockValue = 3
|
||||
|
||||
blockValue += 70
|
||||
if tileset == 9:
|
||||
blockValue += 1
|
||||
|
|
@ -2822,6 +2833,7 @@ def patch_game():
|
|||
blockValue += 1
|
||||
elif tileset == 72:
|
||||
blockValue += 1
|
||||
|
||||
clipValue = ItemList.index(itemName)
|
||||
if clipValue < 2:
|
||||
# Energy Tank or Missile Tank
|
||||
|
|
@ -2842,18 +2854,21 @@ def patch_game():
|
|||
clipValue += 1
|
||||
elif 'Underwater' in nodeType:
|
||||
clipValue += 2
|
||||
|
||||
if 'Hidden' not in nodeType:
|
||||
patchedGame.seek(bg1)
|
||||
patchedGame.write(blockValue.to_bytes(1, 'little'))
|
||||
|
||||
patchedGame.seek(clipdata)
|
||||
patchedGame.write(clipValue.to_bytes(1, 'little'))
|
||||
elif 'Boss' in nodeType or 'Data' in nodeType:
|
||||
|
||||
if 'Boss' in nodeType or 'Data' in nodeType:
|
||||
itemName = PlacedItems[UsedLocations.index(name)]
|
||||
itemValue = ItemList.index(itemName)
|
||||
slot = BossDataList.index(name)
|
||||
roomEvent = roomEventOffset
|
||||
if roomEvent != None:
|
||||
roomEvent = roomEvent + 3 + slot*4
|
||||
roomEvent = roomEvent + 3 + slot * 4
|
||||
if itemValue < 3:
|
||||
itemValue += 1
|
||||
else:
|
||||
|
|
@ -2877,21 +2892,25 @@ def patch_game():
|
|||
location = name
|
||||
elif name in CreditsNames:
|
||||
location = CreditsNames.get(name)
|
||||
elif 'S0' in name:
|
||||
location = 'Main Deck : '
|
||||
else:
|
||||
if 'S0' in name:
|
||||
location = 'Main Deck : '
|
||||
else:
|
||||
location = 'Sector {} : '.format(name[6:7])
|
||||
if 'Tank' in nodeType:
|
||||
location = location + name[8:]
|
||||
else:
|
||||
location = location + nodeType + ' Room'
|
||||
location = 'Sector {} : '.format(name[6:7])
|
||||
|
||||
spaces = ceiling(30 - len(location), 2)
|
||||
location = ' ' * spaces + location
|
||||
patchedGame.seek(offset)
|
||||
patchedGame.write(location.encode('ascii'))
|
||||
for x in range(len(location), 35):
|
||||
patchedGame.write((0).to_bytes(1, 'little'))
|
||||
|
||||
patchedGame.seek(5726109)
|
||||
patchedGame.write(PlacedETanks.to_bytes(1, 'little'))
|
||||
patchedGame.seek(5726110)
|
||||
patchedGame.write(PlacedMissiles.to_bytes(1, 'little'))
|
||||
patchedGame.seek(5726111)
|
||||
patchedGame.write(PlacedPowerBombs.to_bytes(1, 'little'))
|
||||
|
||||
if SeedSettings['-HIDEITEMS-']:
|
||||
patchedGame.seek(3926048)
|
||||
patchedGame.write((76).to_bytes(2, 'little'))
|
||||
|
|
@ -2907,22 +2926,33 @@ def patch_game():
|
|||
patchedGame.write((78).to_bytes(2, 'little'))
|
||||
patchedGame.write((79).to_bytes(2, 'little'))
|
||||
if SeedSettings['-SPLITSECURITY-'] == True:
|
||||
security = securityOffset
|
||||
patchedGame.seek(security)
|
||||
patchedGame.seek(securityOffset)
|
||||
patchedGame.write((0).to_bytes(2, 'little'))
|
||||
if SeedSettings['-MISSILEDATA-']:
|
||||
patchedGame.seek(24828)
|
||||
patchedGame.write((15).to_bytes(1, 'little'))
|
||||
patchedGame.seek(395742)
|
||||
patchedGame.seek(saxAnyOffset + 1)
|
||||
patchedGame.write((15).to_bytes(1, 'little'))
|
||||
patchedGame.seek(465582)
|
||||
patchedGame.write((15).to_bytes(1, 'little'))
|
||||
patchedGame.seek(spawnBox + 13)
|
||||
patchedGame.write((2).to_bytes(1, 'little'))
|
||||
patchedGame.seek(spawnBox + 21)
|
||||
patchedGame.write((4).to_bytes(1, 'little'))
|
||||
patchedGame.seek(spawnBox + 29)
|
||||
patchedGame.write((8).to_bytes(1, 'little'))
|
||||
patchedGame.seek(spawnMegaCoreX + 13)
|
||||
patchedGame.write((2).to_bytes(1, 'little'))
|
||||
patchedGame.seek(spawnMegaCoreX + 21)
|
||||
patchedGame.write((4).to_bytes(1, 'little'))
|
||||
patchedGame.seek(spawnMegaCoreX + 29)
|
||||
patchedGame.write((8).to_bytes(1, 'little'))
|
||||
if SeedSettings['-PBDATA-']:
|
||||
patchedGame.seek(24756)
|
||||
patchedGame.write((32).to_bytes(1, 'little'))
|
||||
patchedGame.seek(465672)
|
||||
patchedGame.write((32).to_bytes(1, 'little'))
|
||||
if SeedSettings['-SHUFFLESECTORS-'] == True:
|
||||
if SeedSettings['-SHUFFLESECTORS-'] == True or SeedSettings['-SHUFFLETUBES-'] == True:
|
||||
for currentArea in range(7):
|
||||
patchedGame.seek(7977108 + currentArea * 4, 0)
|
||||
data = patchedGame.read(4)
|
||||
|
|
|
|||
2
flips
2
flips
|
|
@ -1 +1 @@
|
|||
Subproject commit fdd5c6e34285beef5b9be759c9b91390df486c66
|
||||
Subproject commit e12ef189900b2c720c6dcd55036a8bb43925ea53
|
||||
Loading…
Add table
Add a link
Reference in a new issue