Random sprite on hit now part of basepatch. Other events possible too.
This commit is contained in:
parent
104f780873
commit
38ac943a9c
43
Gui.py
43
Gui.py
|
@ -138,7 +138,10 @@ def guiMain(args=None):
|
|||
sprite = None
|
||||
def set_sprite(sprite_param):
|
||||
nonlocal sprite
|
||||
if sprite_param is None or not sprite_param.valid:
|
||||
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:
|
||||
|
@ -1409,7 +1412,31 @@ class SpriteSelector(object):
|
|||
button = Button(frame, text="Default Link sprite", command=self.use_default_link_sprite)
|
||||
button.pack(side=LEFT, padx=(0, 5))
|
||||
|
||||
button = Button(frame, text="Random sprite", command=self.use_random_sprite)
|
||||
self.randomButtonText = StringVar()
|
||||
button = Button(frame, textvariable=self.randomButtonText, command=self.use_random_sprite)
|
||||
button.pack(side=LEFT, padx=(0, 5))
|
||||
self.randomButtonText.set("Random")
|
||||
|
||||
self.randomOnEventText = StringVar()
|
||||
self.randomOnHitVar = IntVar()
|
||||
self.randomOnEnterVar = IntVar()
|
||||
self.randomOnExitVar = IntVar()
|
||||
self.randomOnSlashVar = IntVar()
|
||||
self.randomOnItemVar = IntVar()
|
||||
|
||||
button = Checkbutton(frame, text="Hit", command=self.update_random_button, variable=self.randomOnHitVar)
|
||||
button.pack(side=LEFT, padx=(0, 5))
|
||||
|
||||
button = Checkbutton(frame, text="Enter", command=self.update_random_button, variable=self.randomOnEnterVar)
|
||||
button.pack(side=LEFT, padx=(0, 5))
|
||||
|
||||
button = Checkbutton(frame, text="Exit", command=self.update_random_button, variable=self.randomOnExitVar)
|
||||
button.pack(side=LEFT, padx=(0, 5))
|
||||
|
||||
button = Checkbutton(frame, text="Slash", command=self.update_random_button, variable=self.randomOnSlashVar)
|
||||
button.pack(side=LEFT, padx=(0, 5))
|
||||
|
||||
button = Checkbutton(frame, text="Item", command=self.update_random_button, variable=self.randomOnItemVar)
|
||||
button.pack(side=LEFT, padx=(0, 5))
|
||||
|
||||
if adjuster:
|
||||
|
@ -1574,8 +1601,18 @@ class SpriteSelector(object):
|
|||
self.callback(Sprite.default_link_sprite())
|
||||
self.window.destroy()
|
||||
|
||||
def update_random_button(self):
|
||||
randomon = "-hit" if self.randomOnHitVar.get() else ""
|
||||
randomon += "-enter" if self.randomOnEnterVar.get() else ""
|
||||
randomon += "-exit" if self.randomOnExitVar.get() else ""
|
||||
randomon += "-slash" if self.randomOnSlashVar.get() else ""
|
||||
randomon += "-item" if self.randomOnItemVar.get() else ""
|
||||
self.randomOnEventText.set(f"randomon{randomon}" if randomon else None)
|
||||
self.randomButtonText.set("Random On Event" if randomon else "Random")
|
||||
|
||||
def use_random_sprite(self):
|
||||
self.callback(random.choice(self.all_sprites) if self.all_sprites else None)
|
||||
randomon = self.randomOnEventText.get()
|
||||
self.callback(randomon if randomon else (random.choice(self.all_sprites) if self.all_sprites else None))
|
||||
self.window.destroy()
|
||||
|
||||
def select_sprite(self, spritename):
|
||||
|
|
8
Main.py
8
Main.py
|
@ -177,10 +177,9 @@ def main(args, seed=None):
|
|||
rom_names = []
|
||||
|
||||
def _gen_rom(team: int, player: int):
|
||||
sprite_random_on_hit = type(args.sprite[player]) is str and args.sprite[player].lower() == 'randomonhit'
|
||||
use_enemizer = (world.boss_shuffle[player] != 'none' or world.enemy_shuffle[player]
|
||||
or world.enemy_health[player] != 'default' or world.enemy_damage[player] != 'default'
|
||||
or world.shufflepots[player] or sprite_random_on_hit or world.bush_shuffle[player]
|
||||
or world.shufflepots[player] or world.bush_shuffle[player]
|
||||
or world.killable_thieves[player] or world.tile_shuffle[player])
|
||||
|
||||
rom = LocalRom(args.rom)
|
||||
|
@ -188,8 +187,7 @@ def main(args, seed=None):
|
|||
patch_rom(world, rom, player, team, use_enemizer)
|
||||
|
||||
if use_enemizer:
|
||||
patch_enemizer(world, player, rom, args.enemizercli,
|
||||
sprite_random_on_hit)
|
||||
patch_enemizer(world, player, rom, args.enemizercli)
|
||||
|
||||
if args.race:
|
||||
patch_race_rom(rom)
|
||||
|
@ -198,7 +196,7 @@ def main(args, seed=None):
|
|||
|
||||
apply_rom_settings(rom, args.heartbeep[player], args.heartcolor[player], args.quickswap[player],
|
||||
args.fastmenu[player], args.disablemusic[player], args.sprite[player],
|
||||
args.ow_palettes[player], args.uw_palettes[player], world, player)
|
||||
args.ow_palettes[player], args.uw_palettes[player], world, player, True)
|
||||
|
||||
mcsb_name = ''
|
||||
if all([world.mapshuffle[player], world.compassshuffle[player], world.keyshuffle[player],
|
||||
|
|
89
Rom.py
89
Rom.py
|
@ -1,5 +1,5 @@
|
|||
JAP10HASH = '03a63945398191337e896e5771f77173'
|
||||
RANDOMIZERBASEHASH = '45a7732cfb056a251285fcb14e9bb8a7'
|
||||
RANDOMIZERBASEHASH = 'f71376f57dfd3d69eaac96f2f391ff64'
|
||||
|
||||
import io
|
||||
import json
|
||||
|
@ -59,15 +59,6 @@ class LocalRom(object):
|
|||
self.buffer[startaddress:startaddress + len(values)] = values
|
||||
|
||||
def write_to_file(self, file, hide_enemizer=False):
|
||||
|
||||
if hide_enemizer:
|
||||
extra_zeroes = 0x400000 - len(self.buffer)
|
||||
if extra_zeroes > 0:
|
||||
buffer = self.buffer + bytes([0x00] * extra_zeroes)
|
||||
with open(file, 'wb') as outfile:
|
||||
outfile.write(buffer)
|
||||
return
|
||||
|
||||
with open(file, 'wb') as outfile:
|
||||
outfile.write(self.buffer)
|
||||
|
||||
|
@ -106,7 +97,7 @@ class LocalRom(object):
|
|||
'Supplied Base Rom does not match known MD5 for JAP(1.0) release. Will try to patch anyway.')
|
||||
|
||||
# extend to 2MB
|
||||
self.buffer.extend(bytearray([0x00]) * (0x200000 - len(self.buffer)))
|
||||
self.buffer.extend(bytearray([0x00]) * (0x400000 - len(self.buffer)))
|
||||
|
||||
# load randomizer patches
|
||||
with open(local_path('data', 'base2current.json')) as stream:
|
||||
|
@ -196,7 +187,50 @@ def check_enemizer(enemizercli):
|
|||
check_enemizer.done = True
|
||||
|
||||
|
||||
def patch_enemizer(world, player: int, rom: LocalRom, enemizercli, random_sprite_on_hit: bool):
|
||||
def apply_random_sprite_on_event(rom: LocalRom, sprite, local_random, allow_random_on_event):
|
||||
onevent = onhit = 0
|
||||
sprites = list()
|
||||
if not allow_random_on_event:
|
||||
allow_random_on_event = not rom.read_byte(0x186381) # Check if explicitly disabled in rom. If so, it stays that way.
|
||||
if sprite and not isinstance(sprite, Sprite):
|
||||
sprite = sprite.lower()
|
||||
if sprite.startswith('randomon'):
|
||||
onevent = onhit = 0x01 if 'hit' in sprite else 0x00
|
||||
onevent += 0x02 if 'enter' in sprite else 0x00
|
||||
onevent += 0x04 if 'exit' in sprite else 0x00
|
||||
onevent += 0x08 if 'slash' in sprite else 0x00
|
||||
onevent += 0x10 if 'item' in sprite else 0x00
|
||||
sprite = Sprite(sprite) if os.path.isfile(sprite) else get_sprite_from_name(sprite, local_random)
|
||||
|
||||
# write link sprite if required
|
||||
if sprite:
|
||||
sprite.write_to_rom(rom)
|
||||
|
||||
if allow_random_on_event:
|
||||
rom.write_int16(0x18637F, onevent)
|
||||
rom.write_byte(0x186381, 0x00) # Enable usage of Random On Event.
|
||||
if rom.read_byte(0x200000):
|
||||
rom.write_byte(0x200103, onhit)
|
||||
|
||||
_populate_sprite_table()
|
||||
if onevent:
|
||||
sprites = list(set(_sprite_table.values())) # convert to list and remove dupes
|
||||
else:
|
||||
sprites.append(sprite)
|
||||
if sprites:
|
||||
while len(sprites) < 32:
|
||||
sprites.extend(sprites)
|
||||
local_random.shuffle(sprites)
|
||||
|
||||
for i, sprite in enumerate(sprites[:32]):
|
||||
if not i and not onevent:
|
||||
continue
|
||||
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)
|
||||
|
||||
|
||||
def patch_enemizer(world, player: int, rom: LocalRom, enemizercli):
|
||||
check_enemizer(enemizercli)
|
||||
randopatch_path = os.path.abspath(output_path(f'enemizer_randopatch_{player}.sfc'))
|
||||
options_path = os.path.abspath(output_path(f'enemizer_options_{player}.json'))
|
||||
|
@ -258,7 +292,7 @@ def patch_enemizer(world, player: int, rom: LocalRom, enemizercli, random_sprite
|
|||
'RandomizeTileTrapPattern': world.tile_shuffle[player],
|
||||
'RandomizeTileTrapFloorTile': False,
|
||||
'AllowKillableThief': world.killable_thieves[player],
|
||||
'RandomizeSpriteOnHit': random_sprite_on_hit,
|
||||
'RandomizeSpriteOnHit': False,
|
||||
'DebugMode': False,
|
||||
'DebugForceEnemy': False,
|
||||
'DebugForceEnemyId': 0,
|
||||
|
@ -334,19 +368,6 @@ def patch_enemizer(world, player: int, rom: LocalRom, enemizercli, random_sprite
|
|||
rom.write_byte(0x04DE81, 6)
|
||||
rom.write_byte(0x200101, 0) # Do not close boss room door on entry.
|
||||
|
||||
if random_sprite_on_hit:
|
||||
_populate_sprite_table()
|
||||
sprites = list(set(_sprite_table.values())) # convert to list and remove dupes
|
||||
if sprites:
|
||||
while len(sprites) < 32:
|
||||
sprites.extend(sprites)
|
||||
world.rom_seeds[player].shuffle(sprites)
|
||||
|
||||
for i, sprite in enumerate(sprites[:32]):
|
||||
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)
|
||||
|
||||
for used in (randopatch_path, options_path):
|
||||
try:
|
||||
os.remove(used)
|
||||
|
@ -376,7 +397,7 @@ def _populate_sprite_table():
|
|||
def get_sprite_from_name(name, local_random=random):
|
||||
_populate_sprite_table()
|
||||
name = name.lower()
|
||||
if name in ['random', 'randomonhit']:
|
||||
if name.startswith('random'):
|
||||
return local_random.choice(list(_sprite_table.values()))
|
||||
return _sprite_table.get(name, None)
|
||||
|
||||
|
@ -411,7 +432,7 @@ class Sprite(object):
|
|||
self.sprite = filedata[:0x7000]
|
||||
self.palette = filedata[0x7000:0x7078]
|
||||
self.glove_palette = filedata[0x7078:]
|
||||
elif len(filedata) in [0x100000, 0x200000]:
|
||||
elif len(filedata) in [0x100000, 0x200000, 0x400000]:
|
||||
# full rom with patched sprite, extract it
|
||||
self.sprite = filedata[0x80000:0x87000]
|
||||
self.palette = filedata[0xDD308:0xDD380]
|
||||
|
@ -546,6 +567,9 @@ class Sprite(object):
|
|||
rom.write_bytes(0x80000, self.sprite)
|
||||
rom.write_bytes(0xDD308, self.palette)
|
||||
rom.write_bytes(0xDEDF5, self.glove_palette)
|
||||
rom.write_bytes(0x300000, self.sprite)
|
||||
rom.write_bytes(0x307000, self.palette)
|
||||
rom.write_bytes(0x307078, self.glove_palette)
|
||||
|
||||
def patch_rom(world, rom, player, team, enemized):
|
||||
local_random = world.rom_seeds[player]
|
||||
|
@ -1460,10 +1484,9 @@ def hud_format_text(text):
|
|||
return output[:32]
|
||||
|
||||
|
||||
def apply_rom_settings(rom, beep, color, quickswap, fastmenu, disable_music, sprite, ow_palettes, uw_palettes, world=None, player=1):
|
||||
def apply_rom_settings(rom, beep, color, quickswap, fastmenu, disable_music, sprite, ow_palettes, uw_palettes, world=None, player=1, allow_random_on_event=False):
|
||||
local_random = random if not world else world.rom_seeds[player]
|
||||
if sprite and not isinstance(sprite, Sprite):
|
||||
sprite = Sprite(sprite) if os.path.isfile(sprite) else get_sprite_from_name(sprite, local_random)
|
||||
apply_random_sprite_on_event(rom, sprite, local_random, allow_random_on_event)
|
||||
|
||||
# enable instant item menu
|
||||
if fastmenu == 'instant':
|
||||
|
@ -1514,10 +1537,6 @@ def apply_rom_settings(rom, beep, color, quickswap, fastmenu, disable_music, spr
|
|||
rom.write_byte(0x6FA30, {'red': 0x24, 'blue': 0x2C, 'green': 0x3C, 'yellow': 0x28}[color])
|
||||
rom.write_byte(0x65561, {'red': 0x05, 'blue': 0x0D, 'green': 0x19, 'yellow': 0x09}[color])
|
||||
|
||||
# write link sprite if required
|
||||
if sprite:
|
||||
sprite.write_to_rom(rom)
|
||||
|
||||
# reset palette if it was adjusted already
|
||||
default_ow_palettes(rom)
|
||||
default_uw_palettes(rom)
|
||||
|
|
Binary file not shown.
|
@ -288,7 +288,12 @@ debug: # Only available if the host uses the doors branch, it is ignored otherwi
|
|||
rom:
|
||||
sprite: # Enter the name of your preferred sprite and weight it appropriately
|
||||
random: 0
|
||||
randomonhit: 0
|
||||
randomonhit: 0 # Random sprite on hit
|
||||
randomonenter: 0 # Random sprite on entering the underworld.
|
||||
randomonexit: 0 # Random sprite on exiting the underworld.
|
||||
randomonslash: 0 # Random sprite on sword slashes
|
||||
randomonitem: 0 # Random sprite on getting items.
|
||||
# You can combine these events like this. randomonhit-enter-exit if you want it on hit, enter, exit.
|
||||
Link: 50 # To add other sprites: open the gui/Creator, go to adjust, select a sprite and write down the name the gui calls it
|
||||
disablemusic: # If "on", all in-game music will be disabled
|
||||
on: 0
|
||||
|
|
Loading…
Reference in New Issue