LttP/Core: more ripping and tearing (#3160)

This commit is contained in:
Fabian Dill
2024-04-18 18:33:16 +02:00
committed by GitHub
parent f19a84222e
commit 6e56f31398
19 changed files with 374 additions and 655 deletions

View File

@@ -945,22 +945,22 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool):
rom.write_bytes(0x118C64, [first_bot, mid_bot, last_bot])
# patch medallion requirements
if world.required_medallions[player][0] == 'Bombos':
if local_world.required_medallions[0] == 'Bombos':
rom.write_byte(0x180022, 0x00) # requirement
rom.write_byte(0x4FF2, 0x31) # sprite
rom.write_byte(0x50D1, 0x80)
rom.write_byte(0x51B0, 0x00)
elif world.required_medallions[player][0] == 'Quake':
elif local_world.required_medallions[0] == 'Quake':
rom.write_byte(0x180022, 0x02) # requirement
rom.write_byte(0x4FF2, 0x31) # sprite
rom.write_byte(0x50D1, 0x88)
rom.write_byte(0x51B0, 0x00)
if world.required_medallions[player][1] == 'Bombos':
if local_world.required_medallions[1] == 'Bombos':
rom.write_byte(0x180023, 0x00) # requirement
rom.write_byte(0x5020, 0x31) # sprite
rom.write_byte(0x50FF, 0x90)
rom.write_byte(0x51DE, 0x00)
elif world.required_medallions[player][1] == 'Ether':
elif local_world.required_medallions[1] == 'Ether':
rom.write_byte(0x180023, 0x01) # requirement
rom.write_byte(0x5020, 0x31) # sprite
rom.write_byte(0x50FF, 0x98)
@@ -1069,7 +1069,7 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool):
# Byrna residual magic cost
rom.write_bytes(0x45C42, [0x04, 0x02, 0x01])
difficulty = world.difficulty_requirements[player]
difficulty = local_world.difficulty_requirements
# Set overflow items for progressive equipment
rom.write_bytes(0x180090,
@@ -1240,17 +1240,17 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool):
rom.write_byte(0x180044, 0x01) # hammer activates tablets
# set up clocks for timed modes
if world.clock_mode[player] in ['ohko', 'countdown-ohko']:
if local_world.clock_mode in ['ohko', 'countdown-ohko']:
rom.write_bytes(0x180190, [0x01, 0x02, 0x01]) # ohko timer with resetable timer functionality
elif world.clock_mode[player] == 'stopwatch':
elif local_world.clock_mode == 'stopwatch':
rom.write_bytes(0x180190, [0x02, 0x01, 0x00]) # set stopwatch mode
elif world.clock_mode[player] == 'countdown':
elif local_world.clock_mode == 'countdown':
rom.write_bytes(0x180190, [0x01, 0x01, 0x00]) # set countdown, with no reset available
else:
rom.write_bytes(0x180190, [0x00, 0x00, 0x00]) # turn off clock mode
# Set up requested clock settings
if world.clock_mode[player] in ['countdown-ohko', 'stopwatch', 'countdown']:
if local_world.clock_mode in ['countdown-ohko', 'stopwatch', 'countdown']:
rom.write_int32(0x180200,
world.red_clock_time[player] * 60 * 60) # red clock adjustment time (in frames, sint32)
rom.write_int32(0x180204,
@@ -1263,14 +1263,14 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool):
rom.write_int32(0x180208, 0) # green clock adjustment time (in frames, sint32)
# Set up requested start time for countdown modes
if world.clock_mode[player] in ['countdown-ohko', 'countdown']:
if local_world.clock_mode in ['countdown-ohko', 'countdown']:
rom.write_int32(0x18020C, world.countdown_start_time[player] * 60 * 60) # starting time (in frames, sint32)
else:
rom.write_int32(0x18020C, 0) # starting time (in frames, sint32)
# set up goals for treasure hunt
rom.write_int16(0x180163, world.treasure_hunt_count[player])
rom.write_bytes(0x180165, [0x0E, 0x28] if world.treasure_hunt_icon[player] == 'Triforce Piece' else [0x0D, 0x28])
rom.write_int16(0x180163, local_world.treasure_hunt_count)
rom.write_bytes(0x180165, [0x0E, 0x28]) # Triforce Piece Sprite
rom.write_byte(0x180194, 1) # Must turn in triforced pieces (instant win not enabled)
rom.write_bytes(0x180213, [0x00, 0x01]) # Not a Tournament Seed
@@ -1283,14 +1283,14 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool):
rom.write_byte(0x180211, gametype) # Game type
# assorted fixes
rom.write_byte(0x1800A2, 0x01 if world.fix_fake_world[
player] else 0x00) # Toggle whether to be in real/fake dark world when dying in a DW dungeon before killing aga1
# Toggle whether to be in real/fake dark world when dying in a DW dungeon before killing aga1
rom.write_byte(0x1800A2, 0x01 if local_world.fix_fake_world else 0x00)
# Lock or unlock aga tower door during escape sequence.
rom.write_byte(0x180169, 0x00)
if world.mode[player] == 'inverted':
rom.write_byte(0x180169, 0x02) # lock aga/ganon tower door with crystals in inverted
rom.write_byte(0x180171,
0x01 if world.ganon_at_pyramid[player] else 0x00) # Enable respawning on pyramid after ganon death
0x01 if local_world.ganon_at_pyramid else 0x00) # Enable respawning on pyramid after ganon death
rom.write_byte(0x180173, 0x01) # Bob is enabled
rom.write_byte(0x180168, 0x08) # Spike Cave Damage
rom.write_bytes(0x18016B, [0x04, 0x02, 0x01]) # Set spike cave and MM spike room Cape usage
@@ -1306,7 +1306,7 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool):
rom.write_byte(0x180086, 0x00 if world.aga_randomness 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)
rom.write_byte(0x180174, 0x01 if local_world.fix_fake_world else 0x00)
rom.write_byte(0x18017E, 0x01) # Fairy fountains only trade in bottles
# Starting equipment
@@ -1448,7 +1448,7 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool):
for address in keys[item.name]:
equip[address] = min(equip[address] + 1, 99)
elif item.name in bottles:
if equip[0x34F] < world.difficulty_requirements[player].progressive_bottle_limit:
if equip[0x34F] < local_world.difficulty_requirements.progressive_bottle_limit:
equip[0x35C + equip[0x34F]] = bottles[item.name]
equip[0x34F] += 1
elif item.name in rupees:
@@ -1507,9 +1507,9 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool):
rom.write_bytes(0x180080,
[50, 50, 70, 70]) # values to fill for Capacity Upgrades (Bomb5, Bomb10, Arrow5, Arrow10)
rom.write_byte(0x18004D, ((0x01 if 'arrows' in world.escape_assist[player] else 0x00) |
(0x02 if 'bombs' in world.escape_assist[player] else 0x00) |
(0x04 if 'magic' in world.escape_assist[player] else 0x00))) # Escape assist
rom.write_byte(0x18004D, ((0x01 if 'arrows' in local_world.escape_assist else 0x00) |
(0x02 if 'bombs' in local_world.escape_assist else 0x00) |
(0x04 if 'magic' in local_world.escape_assist else 0x00))) # Escape assist
if world.goal[player] in ['pedestal', 'triforce_hunt', 'local_triforce_hunt']:
rom.write_byte(0x18003E, 0x01) # make ganon invincible
@@ -1546,7 +1546,7 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool):
rom.write_byte(0x18003B, 0x01 if world.map_shuffle[player] else 0x00) # maps showing crystals on overworld
# compasses showing dungeon count
if world.clock_mode[player] or not world.dungeon_counters[player]:
if local_world.clock_mode or not world.dungeon_counters[player]:
rom.write_byte(0x18003C, 0x00) # Currently must be off if timer is on, because they use same HUD location
elif world.dungeon_counters[player] is True:
rom.write_byte(0x18003C, 0x02) # always on
@@ -1653,13 +1653,13 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool):
rom.write_bytes(0x18018B, [0x20, 0, 0]) # Mantle respawn refills (magic, bombs, arrows)
# patch swamp: Need to enable permanent drain of water as dam or swamp were moved
rom.write_byte(0x18003D, 0x01 if world.swamp_patch_required[player] else 0x00)
rom.write_byte(0x18003D, 0x01 if local_world.swamp_patch_required else 0x00)
# powder patch: remove the need to leave the screen after powder, since it causes problems for potion shop at race game
# temporarally we are just nopping out this check we will conver this to a rom fix soon.
rom.write_bytes(0x02F539,
[0xEA, 0xEA, 0xEA, 0xEA, 0xEA] if world.powder_patch_required[player] else [0xAD, 0xBF, 0x0A, 0xF0,
0x4F])
[0xEA, 0xEA, 0xEA, 0xEA, 0xEA] if local_world.powder_patch_required else [
0xAD, 0xBF, 0x0A, 0xF0, 0x4F])
# allow smith into multi-entrance caves in appropriate shuffles
if world.entrance_shuffle[player] in ['restricted', 'full', 'crossed', 'insanity'] or (
@@ -2421,7 +2421,7 @@ def write_strings(rom, world, player):
' %s?' % hint_text(silverarrows[0]).replace('Ganon\'s', 'my')) if silverarrows else '?\nI think not!'
tt['ganon_phase_3_no_silvers'] = 'Did you find the silver arrows%s' % silverarrow_hint
tt['ganon_phase_3_no_silvers_alt'] = 'Did you find the silver arrows%s' % silverarrow_hint
if world.worlds[player].has_progressive_bows and (world.difficulty_requirements[player].progressive_bow_limit >= 2 or (
if world.worlds[player].has_progressive_bows and (w.difficulty_requirements.progressive_bow_limit >= 2 or (
world.swordless[player] or world.glitches_required[player] == 'no_glitches')):
prog_bow_locs = world.find_item_locations('Progressive Bow', player, True)
world.per_slot_randoms[player].shuffle(prog_bow_locs)
@@ -2482,16 +2482,16 @@ def write_strings(rom, world, player):
tt['sign_ganon'] = 'Go find the Triforce pieces with your friends... Ganon is invincible!'
else:
tt['sign_ganon'] = 'Go find the Triforce pieces... Ganon is invincible!'
if world.treasure_hunt_count[player] > 1:
if w.treasure_hunt_count > 1:
tt['murahdahla'] = "Hello @. I\nam Murahdahla, brother of\nSahasrahla and Aginah. Behold the power of\n" \
"invisibility.\n\n\n\n… … …\n\nWait! you can see me? I knew I should have\n" \
"hidden in a hollow tree. If you bring\n%d Triforce pieces out of %d, I can reassemble it." % \
(world.treasure_hunt_count[player], world.triforce_pieces_available[player])
(w.treasure_hunt_count, world.triforce_pieces_available[player])
else:
tt['murahdahla'] = "Hello @. I\nam Murahdahla, brother of\nSahasrahla and Aginah. Behold the power of\n" \
"invisibility.\n\n\n\n… … …\n\nWait! you can see me? I knew I should have\n" \
"hidden in a hollow tree. If you bring\n%d Triforce piece out of %d, I can reassemble it." % \
(world.treasure_hunt_count[player], world.triforce_pieces_available[player])
(w.treasure_hunt_count, world.triforce_pieces_available[player])
elif world.goal[player] in ['pedestal']:
tt['ganon_fall_in_alt'] = 'Why are you even here?\n You can\'t even hurt me! Your goal is at the pedestal.'
tt['ganon_phase_3_alt'] = 'Seriously? Go Away, I will not Die.'
@@ -2500,20 +2500,20 @@ def write_strings(rom, world, player):
tt['ganon_fall_in'] = Ganon1_texts[local_random.randint(0, len(Ganon1_texts) - 1)]
tt['ganon_fall_in_alt'] = 'You cannot defeat me until you finish your goal!'
tt['ganon_phase_3_alt'] = 'Got wax in\nyour ears?\nI can not die!'
if world.treasure_hunt_count[player] > 1:
if w.treasure_hunt_count > 1:
if world.goal[player] == 'ganon_triforce_hunt' and world.players > 1:
tt['sign_ganon'] = 'You need to find %d Triforce pieces out of %d with your friends to defeat Ganon.' % \
(world.treasure_hunt_count[player], world.triforce_pieces_available[player])
(w.treasure_hunt_count, world.triforce_pieces_available[player])
elif world.goal[player] in ['ganon_triforce_hunt', 'local_ganon_triforce_hunt']:
tt['sign_ganon'] = 'You need to find %d Triforce pieces out of %d to defeat Ganon.' % \
(world.treasure_hunt_count[player], world.triforce_pieces_available[player])
(w.treasure_hunt_count, world.triforce_pieces_available[player])
else:
if world.goal[player] == 'ganon_triforce_hunt' and world.players > 1:
tt['sign_ganon'] = 'You need to find %d Triforce piece out of %d with your friends to defeat Ganon.' % \
(world.treasure_hunt_count[player], world.triforce_pieces_available[player])
(w.treasure_hunt_count, world.triforce_pieces_available[player])
elif world.goal[player] in ['ganon_triforce_hunt', 'local_ganon_triforce_hunt']:
tt['sign_ganon'] = 'You need to find %d Triforce piece out of %d to defeat Ganon.' % \
(world.treasure_hunt_count[player], world.triforce_pieces_available[player])
(w.treasure_hunt_count, world.triforce_pieces_available[player])
tt['kakariko_tavern_fisherman'] = TavernMan_texts[local_random.randint(0, len(TavernMan_texts) - 1)]