diff --git a/CHANGELOG.md b/CHANGELOG.md index dc84da1d..44e65526 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +### 0.1.6.4 +- Fixed Frogsmith and Stumpy and restored progression in these locations +- Added Blacksmith/Hammer Pegs to OW Tile Swap pool + ### 0.1.6.3 - Fixed borked credits (and missing Sprite Author) when collection rate isn't 216 or if GTBK count isn't /22 - Added OW Rando in credits diff --git a/OWEdges.py b/OWEdges.py index 67c2dd4d..dd77f8e7 100644 --- a/OWEdges.py +++ b/OWEdges.py @@ -958,19 +958,19 @@ OWTileGroups = { 'Palace of Darkness Area' ] ), - # ("Blacksmith", "Regular"): ( - # [ - # 0x22, 0x62 - # ], - # [ - # 'Blacksmith Area', - # 'Bat Cave Ledge' - # ], - # [ - # 'Hammer Pegs Area', - # 'Hammer Pegs Entry' - # ] - # ), + ("Blacksmith", "Regular"): ( + [ + 0x22, 0x62 + ], + [ + 'Blacksmith Area', + 'Bat Cave Ledge' + ], + [ + 'Hammer Pegs Area', + 'Hammer Pegs Entry' + ] + ), ("Dunes", "Regular"): ( [ 0x25, 0x65 diff --git a/OverworldGlitchRules.py b/OverworldGlitchRules.py index ea6b90ce..fcb9a18d 100644 --- a/OverworldGlitchRules.py +++ b/OverworldGlitchRules.py @@ -254,11 +254,11 @@ def get_boots_clip_exits_dw(inverted): yield ('VoO To Dig Game Clip', 'Village of Outcasts Area', 'Dig Game Area') yield ('VoO To Dig Game Hook Clip', 'Village of Outcasts Area', 'Dig Game Ledge') #requires hookshot yield ('Broken Bridge To Dunes Clip', 'Broken Bridge West', 'Dark Dunes Area') - yield ('Broken Bridge To Hammer Pegs Clip', 'Broken Bridge West', 'Hammer Peg Area') #fake flipper + yield ('Broken Bridge To Hammer Pegs Clip', 'Broken Bridge West', 'Hammer Pegs Area') #fake flipper yield ('Broken Bridge To Bomb Shop Clip', 'Broken Bridge West', 'Big Bomb Shop Area') #fake flipper yield ('PoD To Cliff Clip', 'Palace of Darkness Area', 'Darkness Cliff') yield ('Dark Dunes To Cliff Clip', 'Dark Dunes Area', 'Darkness Cliff') - yield ('Dark Dunes To Hammer Pegs Clip', 'Dark Dunes Area', 'Hammer Peg Area') + yield ('Dark Dunes To Hammer Pegs Clip', 'Dark Dunes Area', 'Hammer Pegs Area') yield ('Dark Dunes To Bomb Shop Clip', 'Dark Dunes Area', 'Big Bomb Shop Area') yield ('Dig Game To Mire Clip', 'Dig Game Area', 'Misery Mire Area') @@ -267,7 +267,7 @@ def get_boots_clip_exits_dw(inverted): yield ('Bomb Shop To Cliff Clip', 'Big Bomb Shop Area', 'Dark Central Cliffs') yield ('Bomb Shop To Hammer Bridge FAWT Clip', 'Big Bomb Shop Area', 'Hammer Bridge North Area') yield ('Hammer Bridge To Bomb Shop Clip', 'Hammer Bridge North Area', 'Big Bomb Shop Area') - yield ('Hammer Bridge To Hammer Pegs Clip', 'Hammer Bridge North Area', 'Hammer Peg Area') + yield ('Hammer Bridge To Hammer Pegs Clip', 'Hammer Bridge North Area', 'Hammer Pegs Area') yield ('Hammer Bridge To Cliff Clip', 'Hammer Bridge South Area', 'Dark Central Cliffs') yield ('Dark Tree Line Water Clip', 'Dark Tree Line Area', 'Dark Tree Line Water') #requires flippers yield ('PoD Nook To Shopping Mall FAWT Clip', 'Palace of Darkness Nook Area', 'Shopping Mall Area') diff --git a/OverworldShuffle.py b/OverworldShuffle.py index 3360772f..bea78c36 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -4,7 +4,7 @@ from sortedcontainers import SortedList from BaseClasses import OWEdge, WorldType, RegionType, Direction, Terrain, PolSlot from OWEdges import OWTileGroups, OWEdgeGroups, OpenStd, parallel_links, IsParallel -__version__ = '0.1.6.3-u' +__version__ = '0.1.6.4-u' def link_overworld(world, player): # setup mandatory connections @@ -641,8 +641,8 @@ mandatory_connections = [('Flute Away', 'Flute Sky'), ('Broken Bridge Water Drop', 'Broken Bridge Water'), #flippers ('Broken Bridge Northeast Water Drop', 'Broken Bridge Water'), #flippers ('Broken Bridge West Water Drop', 'Broken Bridge Water'), #flippers - ('Peg Area Rocks (West)', 'Hammer Peg Area'), #mitts - ('Peg Area Rocks (East)', 'Hammer Peg Entry'), #mitts + ('Peg Area Rocks (West)', 'Hammer Pegs Area'), #mitts + ('Peg Area Rocks (East)', 'Hammer Pegs Entry'), #mitts ('Dig Game To Ledge Drop', 'Dig Game Ledge'), #mitts ('Dig Game Ledge Drop', 'Dig Game Area'), ('Frog Ledge Drop', 'Archery Game Area'), @@ -924,8 +924,8 @@ ow_connections = { ('Blacksmith Entry Mirror Spot', 'Blacksmith Area'), ('Bat Cave Ledge Mirror Spot', 'Bat Cave Ledge') ], [ - ('Hammer Pegs Mirror Spot', 'Hammer Peg Area'), - ('Hammer Pegs Entry Mirror Spot', 'Hammer Peg Entry') + ('Hammer Pegs Mirror Spot', 'Hammer Pegs Area'), + ('Hammer Pegs Entry Mirror Spot', 'Hammer Pegs Entry') ]), 0x25: ([ ('Sand Dunes Mirror Spot', 'Sand Dunes Area') diff --git a/README.md b/README.md index be7c291c..df2a5d49 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ This is a very new mode of LTTPR so the tools and info is very limited. - There - In Crossed OW Tile Swap, there are some interesting bunny water-walk situations that can occur, these are mean to be out-of-logic but beware of logic bugs around this area. ### Known bugs: -- In Mixed OW Tile Swap, Smith and Stumpy have issues when their tiles are swapped. Progression cannot be found on them when these tiles are swapped +- ~~In Mixed OW Tile Swap, Smith and Stumpy have issues when their tiles are swapped. Progression cannot be found on them when these tiles are swapped~~ (Fixed in 0.1.6.4) - Screens that loop on itself and also have free-standing items, the sprites are duplicated and can cause item duplication - When OWG are performed to enter mega-tile screens (large OW screens), there is a small chance that an incorrect VRAM reference value causes the map graphics to offset in increments of 16 pixels @@ -36,7 +36,7 @@ Download the source code from the repository directly and put it in a folder of You must have Python installed (version 3.6 - 3.9 supported) -This program requires all python dependencies that are necessary to run Aerinon's Door Randomizer plus an additional 'sortedcontainers' package. Try running ```pip install sortedcontainers``` on the command line to install the dependency. +This program requires all python dependencies that are necessary to run Aerinon's Door Randomizer plus an additional 'sortedcontainers' package. Try running ```pip install sortedcontainers``` or ```python -m pip install sortedcontainers``` on the command line to install the dependency. Alternatively, run ```resources/ci/common/local_install.py``` to install all the missing dependencies as well. diff --git a/Regions.py b/Regions.py index 6fd64c33..1138c900 100644 --- a/Regions.py +++ b/Regions.py @@ -171,8 +171,8 @@ def create_regions(world, player): create_dw_region(player, 'Broken Bridge Water', None, ['Broken Bridge NC']), create_dw_region(player, 'Palace of Darkness Area', None, ['Palace of Darkness Hint', 'Palace of Darkness', 'Eastern Palace Mirror Spot', 'Palace of Darkness SW', 'Palace of Darkness SE']), create_dw_region(player, 'Darkness Cliff', None, ['Dark Dunes Ledge Drop', 'Hammer Bridge North Ledge Drop', 'Dark Tree Line Ledge Drop', 'Palace of Darkness Ledge Drop']), - create_dw_region(player, 'Hammer Peg Entry', None, ['Peg Area Rocks (West)', 'Blacksmith Entry Mirror Spot', 'Hammer Pegs WS']), - create_dw_region(player, 'Hammer Peg Area', ['Dark Blacksmith Ruins'], ['Peg Area Rocks (East)', 'Dark World Hammer Peg Cave', 'Blacksmith Mirror Spot', 'Bat Cave Ledge Mirror Spot']), + create_dw_region(player, 'Hammer Pegs Entry', None, ['Peg Area Rocks (West)', 'Blacksmith Entry Mirror Spot', 'Hammer Pegs WS']), + create_dw_region(player, 'Hammer Pegs Area', ['Dark Blacksmith Ruins'], ['Peg Area Rocks (East)', 'Dark World Hammer Peg Cave', 'Blacksmith Mirror Spot', 'Bat Cave Ledge Mirror Spot']), create_dw_region(player, 'Dark Dunes Area', None, ['Sand Dunes Mirror Spot', 'Dark Dunes NW', 'Dark Dunes WN', 'Dark Dunes SC']), create_dw_region(player, 'Dig Game Area', ['Digging Game'], ['Dig Game To Ledge Drop', 'Maze Race Mirror Spot', 'Dig Game ES']), create_dw_region(player, 'Dig Game Ledge', None, ['Dig Game Ledge Drop', 'Maze Race Ledge Mirror Spot', 'Dig Game EC']), diff --git a/Rom.py b/Rom.py index 2737eb3d..f708d49e 100644 --- a/Rom.py +++ b/Rom.py @@ -28,7 +28,7 @@ from OverworldShuffle import default_flute_connections, flute_data JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '5cf6e7c96f0b7775e2936ef1b7b3be66' +RANDOMIZERBASEHASH = '7fde2c814de47cf292b74c8be9db04c4' class JsonRom(object): @@ -593,19 +593,6 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False): # patch overworld edges inverted_buffer = [0] * 0x82 if world.owShuffle[player] != 'vanilla' or world.owSwap[player] != 'vanilla': - rom.write_byte(0x18004C, 0x01) #patch for allowing Frogsmith to enter multi-entrance caves - # patches map data specific for OW Shuffle - inverted_buffer[0x03] = inverted_buffer[0x03] | 0x2 # convenient portal on WDM - inverted_buffer[0x1A] = inverted_buffer[0x1A] | 0x2 # rocks added to prevent OWG hardlock - inverted_buffer[0x1B] = inverted_buffer[0x1B] | 0x2 # rocks added to prevent OWG hardlock - inverted_buffer[0x22] = inverted_buffer[0x22] | 0x2 # rocks added to prevent OWG hardlock - inverted_buffer[0x3F] = inverted_buffer[0x3F] | 0x2 # added C to terrain - inverted_buffer[0x43] = inverted_buffer[0x43] | 0x2 # convenient portal on WDDM - inverted_buffer[0x5A] = inverted_buffer[0x5A] | 0x2 # rocks added to prevent OWG hardlock - inverted_buffer[0x5B] = inverted_buffer[0x5B] | 0x2 # rocks added to prevent OWG hardlock - inverted_buffer[0x62] = inverted_buffer[0x62] | 0x2 # rocks added to prevent OWG hardlock - inverted_buffer[0x7F] = inverted_buffer[0x7F] | 0x2 # added C to terrain - owMode = 0 if world.owShuffle[player] == 'parallel': owMode = 1 @@ -629,6 +616,20 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False): write_int16(rom, 0x150004, owFlags) + rom.write_byte(0x18004C, 0x01) # patch for allowing Frogsmith to enter multi-entrance caves + + # patches map data specific for OW Shuffle + inverted_buffer[0x03] = inverted_buffer[0x03] | 0x2 # convenient portal on WDM + inverted_buffer[0x1A] = inverted_buffer[0x1A] | 0x2 # rocks added to prevent OWG hardlock + inverted_buffer[0x1B] = inverted_buffer[0x1B] | 0x2 # rocks added to prevent OWG hardlock + inverted_buffer[0x22] = inverted_buffer[0x22] | 0x2 # rocks added to prevent OWG hardlock + inverted_buffer[0x3F] = inverted_buffer[0x3F] | 0x2 # added C to terrain + inverted_buffer[0x43] = inverted_buffer[0x43] | 0x2 # convenient portal on WDDM + inverted_buffer[0x5A] = inverted_buffer[0x5A] | 0x2 # rocks added to prevent OWG hardlock + inverted_buffer[0x5B] = inverted_buffer[0x5B] | 0x2 # rocks added to prevent OWG hardlock + inverted_buffer[0x62] = inverted_buffer[0x62] | 0x2 # rocks added to prevent OWG hardlock + inverted_buffer[0x7F] = inverted_buffer[0x7F] | 0x2 # added C to terrain + if world.owSwap[player] == 'mixed': for b in world.owswaps[player][0]: # load inverted maps @@ -890,7 +891,7 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False): write_int16(rom, 0x187010, credits_total) # dynamic credits if credits_total != 216: # collection rate address: - cr_address = 0x239214 + cr_address = 0x239202 cr_pc = cr_address - 0x120000 # convert to pc mid_top, mid_bot = credits_digit((credits_total // 10) % 10) last_top, last_bot = credits_digit(credits_total % 10) @@ -909,7 +910,7 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False): total += count_locations_exclude_logic(region.locations, gt_logic) # rom.write_byte(0x187012, total) # dynamic credits # gt big key address: - gtbk_address = 0x23911C + gtbk_address = 0x2390EE gtbk_pc = gtbk_address - 0x120000 # convert to pc mid_top, mid_bot = credits_digit(total // 10) last_top, last_bot = credits_digit(total % 10) @@ -2796,7 +2797,7 @@ OtherEntrances = {'Blinds Hideout': 'Blind\'s old house', 'Kings Grave': 'The northeastmost grave', 'Bonk Fairy (Light)': 'The rock pile near your home', 'Hookshot Fairy': 'The left paired cave on east DM', - 'Bonk Fairy (Dark)': 'The rock pile near the old bomb shop', + 'Bonk Fairy (Dark)': 'The rock pile near the old bomb shop', 'Dark Lake Hylia Fairy': 'The cave NE dark Lake Hylia', 'C-Shaped House': 'The NE house in Village of Outcasts', 'Dark Death Mountain Fairy': 'The SW cave on dark DM', diff --git a/Rules.py b/Rules.py index 698f5dd9..69e129fb 100644 --- a/Rules.py +++ b/Rules.py @@ -72,13 +72,6 @@ def set_rules(world, player): set_bunny_rules(world, player, world.mode[player] == 'inverted') - # TODO: Remove these rules when these scenarios aren't a problem - if world.owSwap[player] == 'mixed': - if 'Frog Area' in world.owswaps[player][2]: - set_rule(world.get_location('Frog', player), lambda state: False) - if 'Stumpy Area' in world.owswaps[player][2]: - set_rule(world.get_location('Stumpy', player), lambda state: False) - def mirrorless_path_to_location(world, startName, targetName, player): # If Agahnim is defeated then the courtyard needs to be accessible without using the mirror for the mirror offset glitch. diff --git a/asm/owrando.asm b/asm/owrando.asm index 3bfb5b67..03a4443f 100644 --- a/asm/owrando.asm +++ b/asm/owrando.asm @@ -18,46 +18,59 @@ jml OWFluteCancel2 : nop org $0ab90d ;JSL $02E99D jsl OWFluteCancel +; allows Frog sprite to spawn in LW and also allows his friend to spawn in their house +org $068a76 ; < 30a76 - sprite_prep.asm:785 (LDA $7EF3CA : AND.w #$40) +lda $1b : eor.b #1 : nop #2 + +; allows Frog to be accepted at Blacksmith +org $06b3ee ; < 333ee - sprite_smithy_bros.asm:347 (LDA $7EF3CC : CMP.b #$08 : BEQ .no_returning_smithy_tagalong) +jsl OWSmithAccept : nop #2 +db #$b0 ; BCS to replace BEQ + +; load Stumpy per screen's original world, not current world flag +org $06907f ; < 3107f - sprite_prep.asm:2170 (LDA $7EF3CA) +lda $8a : and.b #$40 + ;(replacing -> LDA $8A : AND.b #$40) -org $00d8c4 ; < ? - Bank00.asm 4068 () +org $00d8c4 ; < ? - Bank00.asm:4068 () jsl.l OWWorldCheck -org $0283dc ; < ? - Bank02.asm 816 () +org $0283dc ; < ? - Bank02.asm:816 () jsl.l OWWorldCheck -org $02aa36 ; < ? - Bank02.asm 6559 () +org $02aa36 ; < ? - Bank02.asm:6559 () jsl.l OWWorldCheck -org $02aeca ; < ? - Bank02.asm 7257 () +org $02aeca ; < ? - Bank02.asm:7257 () jsl.l OWWorldCheck16 : nop -org $02b349 ; < ? - Bank02.asm 7902 () +org $02b349 ; < ? - Bank02.asm:7902 () jsl.l OWWorldCheck -org $02c40a ; < ? - Bank02.asm 10547 () +org $02c40a ; < ? - Bank02.asm:10547 () jsl.l OWWorldCheck -org $05afd9 ; < ? - sprite_warp_vortex.asm 60 () +org $05afd9 ; < ? - sprite_warp_vortex.asm:60 () jsl.l OWWorldCheck -org $07a3f0 ; < ? - Bank07.asm 5772 () ; flute activation/use +org $07a3f0 ; < ? - Bank07.asm:5772 () ; flute activation/use jsl.l OWWorldCheck -org $07a967 ; < ? - Bank07.asm 6578 () +org $07a967 ; < ? - Bank07.asm:6578 () jsl.l OWWorldCheck -org $07a9a1 ; < ? - Bank07.asm 6622 () +org $07a9a1 ; < ? - Bank07.asm:6622 () jsl.l OWWorldCheck -org $07a9ed ; < ? - Bank07.asm 6677 () +org $07a9ed ; < ? - Bank07.asm:6677 () jsl.l OWWorldCheck -org $07aa34 ; < ? - Bank07.asm 6718 () +org $07aa34 ; < ? - Bank07.asm:6718 () jsl.l OWWorldCheck -org $08d408 ; < ? - ancilla_morph_poof.asm 48 () +org $08d408 ; < ? - ancilla_morph_poof.asm:48 () jsl.l OWWorldCheck -org $0aba6c ; < ? - Bank0a.asm 474 () +org $0aba6c ; < ? - Bank0a.asm:474 () jsl.l OWWorldCheck16 : nop -org $0aba99 ; < ? - Bank0a.asm 515 () +org $0aba99 ; < ? - Bank0a.asm:515 () jsl.l OWWorldCheck -org $0bfeab ; < ? - Bank0b.asm 36 () +org $0bfeab ; < ? - Bank0b.asm:36 () jsl.l OWWorldCheck16 : nop org $0cffb6 ; < ? - ?.asm ? () jsl.l OWWorldCheck16 : nop org $0cffe8 ; < ? - ?.asm ? () jsl.l OWWorldCheck16 : nop -org $1beca2 ; < ? - palettes.asm 556 () +org $1beca2 ; < ? - palettes.asm:556 () jsl.l OWWorldCheck16 : nop -org $1bed95 ; < ? - palettes.asm 748 () +org $1bed95 ; < ? - palettes.asm:748 () jsl.l OWWorldCheck16 : nop org $02b16e ; AND #$3F : ORA 7EF3CA @@ -122,6 +135,13 @@ OWFluteCancel2: lda #$01 : sta $7f5006 + rtl } +OWSmithAccept: +{ + lda $7ef3cc : cmp #$07 : beq + + cmp #$08 : beq + + clc : rtl + + sec : rtl +} org $aa9000 OWEdgeTransition: diff --git a/data/base2current.bps b/data/base2current.bps index 18b1826a..197b7484 100644 Binary files a/data/base2current.bps and b/data/base2current.bps differ diff --git a/mystery_example.yml b/mystery_example.yml index e349063d..bf0987c6 100644 --- a/mystery_example.yml +++ b/mystery_example.yml @@ -1,4 +1,19 @@ description: Example door rando weights + ow_shuffle: + vanilla: 0 + parallel: 2 + full: 2 + ow_keepsimilar: + on: 1 + off: 1 + ow_swap: + vanilla: 0 + mixed: 2 + crossed: 2 + ow_fluteshuffle: + vanilla: 0 + balanced: 1 + random: 1 door_shuffle: vanilla: 0 basic: 2