Merge branch 'OriginOverworldShuffle' into OverworldShuffle
This commit is contained in:
86
Rom.py
86
Rom.py
@@ -32,13 +32,13 @@ from EntranceShuffle import door_addresses, exit_ids, ow_prize_table
|
||||
from OverworldShuffle import default_flute_connections, flute_data
|
||||
from InitialSram import InitialSram
|
||||
|
||||
from source.classes.SFX import randomize_sfx
|
||||
from source.classes.SFX import randomize_sfx, randomize_sfxinstruments, randomize_songinstruments
|
||||
from source.item.FillUtil import valid_pot_items
|
||||
from source.dungeon.RoomList import Room0127
|
||||
|
||||
|
||||
JAP10HASH = '03a63945398191337e896e5771f77173'
|
||||
RANDOMIZERBASEHASH = 'ee45fd99b433e6f3e46e4f98a35ec544'
|
||||
RANDOMIZERBASEHASH = '7365fcc38493f960db07a5478135f850'
|
||||
|
||||
|
||||
class JsonRom(object):
|
||||
@@ -109,6 +109,9 @@ class LocalRom(object):
|
||||
self.patch_base_rom()
|
||||
self.orig_buffer = self.buffer.copy()
|
||||
|
||||
def read_byte(self, address):
|
||||
return self.buffer[address]
|
||||
|
||||
def write_byte(self, address, value):
|
||||
self.buffer[address] = value
|
||||
|
||||
@@ -709,7 +712,7 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
||||
offset = 0
|
||||
data = flute_data[owid]
|
||||
|
||||
if world.is_tile_swapped(data[1], player):
|
||||
if world.is_tile_swapped(owid, player):
|
||||
offset = 0x40
|
||||
|
||||
write_int16(rom, snes_to_pc(0x02E849 + (o * 2)), owid + offset) # owid
|
||||
@@ -755,7 +758,7 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
||||
elif world.owShuffle[player] == 'full':
|
||||
owMode = 2
|
||||
|
||||
if world.owKeepSimilar[player] and (world.owShuffle[player] != 'vanilla' or world.owCrossed[player] in ['limited', 'chaos']):
|
||||
if world.owKeepSimilar[player] and (world.owShuffle[player] != 'vanilla' or world.owCrossed[player] == 'unrestricted'):
|
||||
owMode |= 0x0100
|
||||
if world.owCrossed[player] != 'none' and (world.owCrossed[player] != 'polar' or world.owMixed[player]):
|
||||
owMode |= 0x0200
|
||||
@@ -811,13 +814,13 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
||||
|
||||
owFlags |= 0x0200
|
||||
|
||||
# setting spriteID to D8, a placeholder sprite we use to inform ROM to spawn a dynamic item
|
||||
# setting spriteID to D9, a placeholder sprite we use to inform ROM to spawn a dynamic item
|
||||
#for address in bonk_addresses:
|
||||
for address in [b for b in bonk_addresses if b != 0x4D0AE]: # temp fix for screen 1A murahdahla sprite replacement
|
||||
rom.write_byte(address, 0xD8)
|
||||
rom.write_byte(address, 0xD9)
|
||||
# temporary fix for screen 1A
|
||||
rom.write_byte(snes_to_pc(0x09AE32), 0xD8)
|
||||
rom.write_byte(snes_to_pc(0x09AE35), 0xD8)
|
||||
rom.write_byte(snes_to_pc(0x09AE32), 0xD9)
|
||||
rom.write_byte(snes_to_pc(0x09AE35), 0xD9)
|
||||
|
||||
rom.write_byte(snes_to_pc(0x06918E), 0x80) # skip good bee bottle check
|
||||
|
||||
@@ -1547,9 +1550,9 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
||||
rom.write_byte(0x180211, gametype) # Game type
|
||||
|
||||
warningflags = 0x00 # none
|
||||
if world.logic[player] in ['owglitches', 'nologic']:
|
||||
if world.logic[player] in ['owglitches', 'hybridglitches', 'nologic']:
|
||||
warningflags |= 0x20
|
||||
if world.logic[player] in ['minorglitches', 'owglitches', 'nologic']:
|
||||
if world.logic[player] in ['minorglitches', 'owglitches', 'hybridglitches', 'nologic']:
|
||||
warningflags |= 0x40
|
||||
rom.write_byte(0x180212, warningflags) # Warning flags
|
||||
|
||||
@@ -1577,7 +1580,7 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
||||
rom.write_byte(0x18008F, 0x01 if world.is_atgt_swapped(player) else 0x00) # AT/GT swapped
|
||||
rom.write_byte(0xF5D73, 0xF0) # bees are catchable
|
||||
rom.write_byte(0xF5F10, 0xF0) # bees are catchable
|
||||
rom.write_byte(0x180086, 0x00 if world.aga_randomness else 0x01) # set blue ball and ganon warp randomness
|
||||
rom.write_byte(0x180086, 0x00 if world.aga_randomness[player] else 0x01) # set blue ball and ganon warp randomness
|
||||
rom.write_byte(0x1800A0, 0x01) # return to light world on s+q without mirror
|
||||
rom.write_byte(0x1800A1, 0x01) # enable overworld screen transition draining for water level inside swamp
|
||||
rom.write_byte(0x180174, 0x01 if world.fix_fake_world[player] else 0x00)
|
||||
@@ -1591,7 +1594,8 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
||||
rom.write_byte(0x180035, 30) # starting max arrows
|
||||
|
||||
rom.write_byte(0x18004A, 0x00 if world.mode[player] != 'inverted' else 0x01) # Inverted mode
|
||||
rom.write_byte(0x18005D, 0x00) # Hammer always breaks barrier
|
||||
#rom.write_byte(0x18005D, 0x00) # Hammer always breaks barrier
|
||||
rom.write_byte(0x02AF79, 0xD0 if world.mode[player] != 'inverted' else 0xF0) # vortexes: Normal (D0=light to dark, F0=dark to light, 42 = both)
|
||||
rom.write_byte(0x03A943, 0xD0 if world.mode[player] != 'inverted' else 0xF0) # Mirror: Normal (D0=Dark to Light, F0=light to dark, 42 = both)
|
||||
rom.write_byte(0x03A96D, 0xF0 if world.mode[player] != 'inverted' else 0xD0) # Residual Portal: Normal (F0= Light Side, D0=Dark Side, 42 = both (Darth Vader))
|
||||
rom.write_byte(0x03A9A7, 0xD0) # Residual Portal: Normal (D0= Light Side, F0=Dark Side, 42 = both (Darth Vader))
|
||||
@@ -1639,10 +1643,11 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
||||
rom.write_byte(0x18002E, ganon_item_byte[world.ganon_item[player]])
|
||||
|
||||
# block HC upstairs doors in rain state in standard mode
|
||||
prevent_rain = world.mode[player] == "standard" and world.shuffle[player] != 'vanilla'
|
||||
prevent_rain = world.mode[player] == 'standard' and world.shuffle[player] != 'vanilla' and world.logic[player] != 'nologic'
|
||||
rom.write_byte(0x18008A, 0x01 if prevent_rain else 0x00)
|
||||
# block sanc door in rain state and the dungeon is not vanilla
|
||||
rom.write_byte(0x13f0fa, 0x01 if world.mode[player] == "standard" and world.doorShuffle[player] != 'vanilla' else 0x00)
|
||||
block_sanc = world.mode[player] == 'standard' and world.doorShuffle[player] != 'vanilla' and world.logic[player] != 'nologic'
|
||||
rom.write_byte(0x13f0fa, 0x01 if block_sanc else 0x00)
|
||||
|
||||
if prevent_rain:
|
||||
portals = [world.get_portal('Hyrule Castle East', player), world.get_portal('Hyrule Castle West', player)]
|
||||
@@ -1758,7 +1763,7 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
||||
# b - Big Key
|
||||
# a - Small Key
|
||||
#
|
||||
enable_menu_map_check = world.overworld_map[player] != 'default' and world.shuffle[player] != 'none'
|
||||
enable_menu_map_check = world.overworld_map[player] != 'default' and world.shuffle[player] != 'vanilla'
|
||||
rom.write_byte(0x180045, ((0x01 if world.keyshuffle[player] == 'wild' else 0x00)
|
||||
| (0x02 if world.bigkeyshuffle[player] else 0x00)
|
||||
| (0x04 if world.mapshuffle[player] or enable_menu_map_check else 0x00)
|
||||
@@ -1808,7 +1813,7 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
||||
rom.write_byte(0x1800A3, 0x01) # enable correct world setting behaviour after agahnim kills
|
||||
rom.write_byte(0x1800A4, 0x01 if world.logic[player] != 'nologic' else 0x00) # enable POD EG fix
|
||||
rom.write_byte(0x180042, 0x01 if world.save_and_quit_from_boss else 0x00) # Allow Save and Quit after boss kill
|
||||
rom.write_byte(0x180358, 0x01 if (world.logic[player] in ['owglitches', 'nologic']) else 0x00)
|
||||
rom.write_byte(0x180358, 0x01 if (world.logic[player] in ['owglitches', 'hybridglitches', 'nologic']) else 0x00)
|
||||
|
||||
# remove shield from uncle
|
||||
rom.write_bytes(0x6D253, [0x00, 0x00, 0xf6, 0xff, 0x00, 0x0E])
|
||||
@@ -1876,7 +1881,7 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
||||
# rom.write_byte(snes_to_pc(0x0DB730), 0x08) # allows chickens to travel across water
|
||||
|
||||
# allow smith into multi-entrance caves in appropriate shuffles
|
||||
if world.shuffle[player] in ['restricted', 'full', 'lite', 'lean', 'swapped', 'crossed', 'insanity'] or (world.shuffle[player] == 'simple' and world.mode[player] == 'inverted'):
|
||||
if world.shuffle[player] in ['restricted', 'full', 'lite', 'lean', 'district', 'swapped', 'crossed', 'insanity'] or (world.shuffle[player] == 'simple' and world.mode[player] == 'inverted'):
|
||||
rom.write_byte(0x18004C, 0x01)
|
||||
|
||||
# set correct flag for hera basement item
|
||||
@@ -2039,7 +2044,8 @@ def hud_format_text(text):
|
||||
|
||||
|
||||
def apply_rom_settings(rom, beep, color, quickswap, fastmenu, disable_music, sprite,
|
||||
ow_palettes, uw_palettes, reduce_flashing, shuffle_sfx, msu_resume):
|
||||
ow_palettes, uw_palettes, reduce_flashing, shuffle_sfx,
|
||||
shuffle_sfxinstruments, shuffle_songinstruments, msu_resume):
|
||||
|
||||
if not os.path.exists("data/sprites/official/001.link.1.zspr") and rom.orig_buffer:
|
||||
dump_zspr(rom.orig_buffer[0x80000:0x87000], rom.orig_buffer[0xdd308:0xdd380],
|
||||
@@ -2134,6 +2140,10 @@ def apply_rom_settings(rom, beep, color, quickswap, fastmenu, disable_music, spr
|
||||
|
||||
if shuffle_sfx:
|
||||
randomize_sfx(rom)
|
||||
if shuffle_sfxinstruments:
|
||||
randomize_sfxinstruments(rom)
|
||||
if shuffle_songinstruments:
|
||||
randomize_songinstruments(rom)
|
||||
|
||||
if isinstance(rom, LocalRom):
|
||||
rom.write_crc()
|
||||
@@ -2338,7 +2348,7 @@ def write_strings(rom, world, player, team):
|
||||
tt.removeUnwantedText()
|
||||
|
||||
# Let's keep this guy's text accurate to the shuffle setting.
|
||||
if world.shuffle[player] in ['vanilla', 'dungeonsfull', 'dungeonssimple']:
|
||||
if world.shuffle[player] in ['vanilla', 'dungeonsfull', 'dungeonssimple', 'lite', 'lean']:
|
||||
tt['kakariko_flophouse_man_no_flippers'] = 'I really hate mowing my yard.\n{PAGEBREAK}\nI should move.'
|
||||
tt['kakariko_flophouse_man'] = 'I really hate mowing my yard.\n{PAGEBREAK}\nI should move.'
|
||||
|
||||
@@ -2389,9 +2399,9 @@ def write_strings(rom, world, player, team):
|
||||
# Now we write inconvenient locations for most shuffles and finish taking care of the less chaotic ones.
|
||||
if world.shuffle[player] not in ['lite', 'lean']:
|
||||
entrances_to_hint.update(InconvenientOtherEntrances)
|
||||
if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull', 'lite', 'lean', 'swapped']:
|
||||
if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull', 'district', 'swapped']:
|
||||
hint_count = 0
|
||||
elif world.shuffle[player] in ['simple', 'restricted']:
|
||||
elif world.shuffle[player] in ['simple', 'restricted', 'lite', 'lean']:
|
||||
hint_count = 2
|
||||
else:
|
||||
hint_count = 4
|
||||
@@ -2417,7 +2427,7 @@ def write_strings(rom, world, player, team):
|
||||
entrances_to_hint.update(OtherEntrances)
|
||||
if world.mode[player] != 'inverted':
|
||||
entrances_to_hint.update({'Dark Sanctuary Hint': 'The dark sanctuary cave'})
|
||||
if world.shuffle[player] not in ['vanilla', 'dungeonssimple', 'dungeonsfull', 'lite', 'lean']:
|
||||
if world.shuffle[player] not in ['vanilla', 'dungeonssimple', 'dungeonsfull', 'lite', 'lean', 'district']:
|
||||
if world.shufflelinks[player]:
|
||||
entrances_to_hint.update({'Big Bomb Shop': 'The old bomb shop'})
|
||||
entrances_to_hint.update({'Links House': 'The hero\'s old residence'})
|
||||
@@ -2434,17 +2444,17 @@ def write_strings(rom, world, player, team):
|
||||
entrances_to_hint.update({'Inverted Pyramid Entrance': 'The extra castle passage'})
|
||||
else:
|
||||
entrances_to_hint.update({'Pyramid Entrance': 'The pyramid ledge'})
|
||||
hint_count = 4 if world.shuffle[player] not in ['vanilla', 'dungeonssimple', 'dungeonsfull', 'swapped'] else 0
|
||||
hint_count = 4 if world.shuffle[player] not in ['vanilla', 'dungeonssimple', 'dungeonsfull', 'district', 'swapped'] else 0
|
||||
hint_count -= 2 if world.shuffle[player] not in ['simple', 'restricted'] else 0
|
||||
for entrance in all_entrances:
|
||||
if entrance.name in entrances_to_hint:
|
||||
if hint_count > 0:
|
||||
if hint_count > 0:
|
||||
if entrance.name in entrances_to_hint:
|
||||
this_hint = entrances_to_hint[entrance.name] + ' leads to ' + hint_text(entrance.connected_region) + '.'
|
||||
tt[hint_locations.pop(0)] = this_hint
|
||||
entrances_to_hint.pop(entrance.name)
|
||||
hint_count -= 1
|
||||
else:
|
||||
break
|
||||
else:
|
||||
break
|
||||
|
||||
# Next we write a few hints for specific inconvenient locations. We don't make many because in entrance this is highly unpredictable.
|
||||
locations_to_hint = InconvenientLocations.copy()
|
||||
@@ -2453,7 +2463,7 @@ def write_strings(rom, world, player, team):
|
||||
if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull']:
|
||||
locations_to_hint.extend(InconvenientVanillaLocations)
|
||||
random.shuffle(locations_to_hint)
|
||||
hint_count = 3 if world.shuffle[player] not in ['vanilla', 'dungeonssimple', 'dungeonsfull', 'swapped'] else 5
|
||||
hint_count = 3 if world.shuffle[player] not in ['vanilla', 'dungeonssimple', 'dungeonsfull', 'district', 'swapped'] else 5
|
||||
hint_count -= 2 if world.doorShuffle[player] not in ['vanilla', 'basic'] else 0
|
||||
del locations_to_hint[hint_count:]
|
||||
for location in locations_to_hint:
|
||||
@@ -2528,7 +2538,7 @@ def write_strings(rom, world, player, team):
|
||||
if world.bigkeyshuffle[player]:
|
||||
items_to_hint.extend(BigKeys)
|
||||
random.shuffle(items_to_hint)
|
||||
hint_count = 5 if world.shuffle[player] not in ['vanilla', 'dungeonssimple', 'dungeonsfull', 'swapped'] else 8
|
||||
hint_count = 5 if world.shuffle[player] not in ['vanilla', 'dungeonssimple', 'dungeonsfull', 'district', 'swapped'] else 8
|
||||
hint_count += 2 if world.doorShuffle[player] not in ['vanilla', 'basic'] else 0
|
||||
hint_count += 1 if world.owShuffle[player] != 'vanilla' or world.owCrossed[player] != 'none' or world.owMixed[player] else 0
|
||||
while hint_count > 0 and len(items_to_hint) > 0:
|
||||
@@ -2572,11 +2582,11 @@ def write_strings(rom, world, player, team):
|
||||
choices.clear()
|
||||
choices.append(location_item)
|
||||
if hint_type == 'foolish':
|
||||
if district.dungeons and world.shuffle[player] != 'vanilla':
|
||||
if district.dungeons and world.shuffle[player] not in ['vanilla', 'district']:
|
||||
choices.extend(district.dungeons)
|
||||
hint_type = 'dungeon_path'
|
||||
elif district.access_points and world.shuffle[player] not in ['vanilla', 'dungeonssimple',
|
||||
'dungeonsfull']:
|
||||
'dungeonsfull', 'district']:
|
||||
choices.extend([x.hint_text for x in district.access_points])
|
||||
hint_type = 'connector'
|
||||
if hint_type == 'foolish':
|
||||
@@ -2771,9 +2781,15 @@ def write_strings(rom, world, player, team):
|
||||
rom.write_byte(0x04a52e, 0x06) # follower set to blind maiden
|
||||
|
||||
# inverted spawn menu changes
|
||||
lh_text = "House"
|
||||
if world.is_tile_swapped(0x2c, player):
|
||||
lh_text = "Bomb Shop"
|
||||
sanc_text = "Sanctuary"
|
||||
if world.mode[player] == 'inverted':
|
||||
sanc_text = "Dark Chapel"
|
||||
tt['menu_start_2'] = "{MENU}\n{SPEED0}\n≥@'s " + lh_text + "\n " + sanc_text + "\n{CHOICE3}"
|
||||
tt['menu_start_3'] = "{MENU}\n{SPEED0}\n≥@'s " + lh_text + "\n " + sanc_text + "\n Mountain Cave\n{CHOICE2}"
|
||||
if world.mode[player] == 'inverted':
|
||||
tt['menu_start_2'] = "{MENU}\n{SPEED0}\n≥@'s House\n Dark Chapel\n{CHOICE3}"
|
||||
tt['menu_start_3'] = "{MENU}\n{SPEED0}\n≥@'s House\n Dark Chapel\n Mountain Cave\n{CHOICE2}"
|
||||
tt['intro_main'] = CompressedTextMapper.convert(
|
||||
"{INTRO}\n Episode III\n{PAUSE3}\n A Link to\n the Past\n"
|
||||
+ "{PAUSE3}\nInverted\n Randomizer\n{PAUSE3}\nAfter mostly disregarding what happened in the first two games.\n"
|
||||
@@ -2960,10 +2976,6 @@ def set_inverted_mode(world, player, rom, inverted_buffer):
|
||||
write_int16s(rom, snes_to_pc(0x1BB810), [0x00BE, 0x00C0, 0x013E]) # update pyramid hole entrance
|
||||
write_int16s(rom, snes_to_pc(0x1BB836), [0x001B, 0x001B, 0x001B])
|
||||
|
||||
write_int16(rom, snes_to_pc(0x308300), 0x0140) # add extra pyramid hole
|
||||
write_int16(rom, snes_to_pc(0x308320), 0x001B)
|
||||
if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull']:
|
||||
rom.write_byte(snes_to_pc(0x308340), 0x7B)
|
||||
|
||||
rom.write_byte(snes_to_pc(0x00DB9D), 0x1A) # make retreat bat gfx available in HC area
|
||||
rom.write_byte(snes_to_pc(0x00DC09), 0x1A)
|
||||
|
||||
Reference in New Issue
Block a user