Initial Flute Shuffle implementation
This commit is contained in:
@@ -26,6 +26,7 @@ class World(object):
|
||||
self.owShuffle = owShuffle.copy()
|
||||
self.owSwap = owSwap.copy()
|
||||
self.owKeepSimilar = {}
|
||||
self.owFluteShuffle = {}
|
||||
self.shuffle = shuffle.copy()
|
||||
self.doorShuffle = doorShuffle.copy()
|
||||
self.intensity = {}
|
||||
@@ -76,6 +77,7 @@ class World(object):
|
||||
self.owswaps = {}
|
||||
self.owedges = []
|
||||
self._owedge_cache = {}
|
||||
self.owflutespots = {}
|
||||
self.doors = []
|
||||
self._door_cache = {}
|
||||
self.paired_doors = {}
|
||||
@@ -2157,6 +2159,7 @@ class Spoiler(object):
|
||||
'ow_shuffle': self.world.owShuffle,
|
||||
'ow_swap': self.world.owSwap,
|
||||
'ow_keepsimilar': self.world.owKeepSimilar,
|
||||
'ow_fluteshuffle': self.world.owFluteShuffle,
|
||||
'shuffle': self.world.shuffle,
|
||||
'door_shuffle': self.world.doorShuffle,
|
||||
'intensity': self.world.intensity,
|
||||
@@ -2239,6 +2242,7 @@ class Spoiler(object):
|
||||
outfile.write('Overworld Tile Swap:'.ljust(line_width) + '%s\n' % self.metadata['ow_swap'][player])
|
||||
if self.metadata['ow_shuffle'][player] != 'vanilla':
|
||||
outfile.write('Keep Similar OW Edges Together:'.ljust(line_width) + '%s\n' % ('Yes' if self.metadata['ow_keepsimilar'][player] else 'No'))
|
||||
outfile.write('Flute Shuffle:'.ljust(line_width) + '%s\n' % ('Yes' if self.metadata['ow_fluteshuffle'][player] != 'vanilla' else 'No'))
|
||||
outfile.write('Entrance Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['shuffle'][player])
|
||||
outfile.write('Door Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['door_shuffle'][player])
|
||||
outfile.write('Intensity:'.ljust(line_width) + '%s\n' % self.metadata['intensity'][player])
|
||||
|
||||
4
CLI.py
4
CLI.py
@@ -93,7 +93,8 @@ def parse_cli(argv, no_defaults=False):
|
||||
for player in range(1, multiargs.multi + 1):
|
||||
playerargs = parse_cli(shlex.split(getattr(ret, f"p{player}")), True)
|
||||
|
||||
for name in ['logic', 'mode', 'swords', 'goal', 'difficulty', 'item_functionality', 'ow_shuffle', 'ow_swap', 'ow_keepsimilar',
|
||||
for name in ['logic', 'mode', 'swords', 'goal', 'difficulty', 'item_functionality',
|
||||
'ow_shuffle', 'ow_swap', 'ow_keepsimilar', 'ow_fluteshuffle',
|
||||
'shuffle', 'door_shuffle', 'intensity', 'crystals_ganon', 'crystals_gt', 'openpyramid',
|
||||
'mapshuffle', 'compassshuffle', 'keyshuffle', 'bigkeyshuffle', 'startinventory',
|
||||
'triforce_pool_min', 'triforce_pool_max', 'triforce_goal_min', 'triforce_goal_max',
|
||||
@@ -144,6 +145,7 @@ def parse_settings():
|
||||
"ow_shuffle": "vanilla",
|
||||
"ow_swap": "vanilla",
|
||||
"ow_keepsimilar": False,
|
||||
"ow_fluteshuffle": "vanilla",
|
||||
"shuffle": "vanilla",
|
||||
"shufflelinks": False,
|
||||
|
||||
|
||||
3
Main.py
3
Main.py
@@ -74,6 +74,7 @@ def main(args, seed=None, fish=None):
|
||||
world.crystals_ganon_orig = args.crystals_ganon.copy()
|
||||
world.crystals_gt_orig = args.crystals_gt.copy()
|
||||
world.owKeepSimilar = args.ow_keepsimilar.copy()
|
||||
world.owFluteShuffle = args.ow_fluteshuffle.copy()
|
||||
world.open_pyramid = args.openpyramid.copy()
|
||||
world.boss_shuffle = args.shufflebosses.copy()
|
||||
world.enemy_shuffle = args.shuffleenemies.copy()
|
||||
@@ -383,6 +384,8 @@ def copy_world(world):
|
||||
ret.crystals_needed_for_gt = world.crystals_needed_for_gt.copy()
|
||||
ret.crystals_ganon_orig = world.crystals_ganon_orig.copy()
|
||||
ret.crystals_gt_orig = world.crystals_gt_orig.copy()
|
||||
ret.owKeepSimilar = world.owKeepSimilar.copy()
|
||||
ret.owFluteShuffle = world.owFluteShuffle.copy()
|
||||
ret.open_pyramid = world.open_pyramid.copy()
|
||||
ret.boss_shuffle = world.boss_shuffle.copy()
|
||||
ret.enemy_shuffle = world.enemy_shuffle.copy()
|
||||
|
||||
@@ -133,9 +133,11 @@ def roll_settings(weights):
|
||||
|
||||
overworld_shuffle = get_choice('overworld_shuffle')
|
||||
ret.ow_shuffle = overworld_shuffle if overworld_shuffle != 'none' else 'vanilla'
|
||||
overworld_shuffle = get_choice('overworld_swap')
|
||||
overworld_swap = get_choice('overworld_swap')
|
||||
ret.ow_swap = overworld_swap if overworld_swap != 'none' else 'vanilla'
|
||||
ret.ow_keepsimilar = get_choice('ow_keepsimilar')
|
||||
overworld_flute = get_choice('overworld_flute')
|
||||
ret.ow_swap = overworld_flute if overworld_flute != 'none' else 'vanilla'
|
||||
entrance_shuffle = get_choice('entrance_shuffle')
|
||||
ret.shuffle = entrance_shuffle if entrance_shuffle != 'none' else 'vanilla'
|
||||
door_shuffle = get_choice('door_shuffle')
|
||||
|
||||
@@ -722,8 +722,8 @@ OWTileGroups = {
|
||||
],
|
||||
[
|
||||
'East Dark Death Mountain (Top)',
|
||||
'East Dark Death Mountain (Bottom)',
|
||||
'East Dark Death Mountain (Bottom Left)'
|
||||
'East Dark Death Mountain (Bottom Left)',
|
||||
'East Dark Death Mountain (Bottom)'
|
||||
]
|
||||
),
|
||||
("East Mountain", "Entrance"): (
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import random, logging, copy
|
||||
from sortedcontainers import SortedList
|
||||
from BaseClasses import OWEdge, WorldType, RegionType, Direction, Terrain, PolSlot
|
||||
from OWEdges import OWTileGroups, OWEdgeGroups, OpenStd, parallel_links, IsParallel
|
||||
|
||||
@@ -141,14 +142,39 @@ def link_overworld(world, player):
|
||||
region = world.get_region(name, player)
|
||||
region.type = RegionType.LightWorld
|
||||
|
||||
#make new connections
|
||||
for owid in flute_connections.keys():
|
||||
(spot, dest) = flute_connections[owid]
|
||||
if (world.mode[player] == 'inverted') == (owid in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
connect_simple(world, spot, dest[0], player)
|
||||
else:
|
||||
connect_simple(world, spot, dest[1], player)
|
||||
# flute shuffle
|
||||
def connect_flutes(flute_destinations):
|
||||
for o in range(0, len(flute_destinations)):
|
||||
owid = flute_destinations[o]
|
||||
regions = flute_data[owid][0]
|
||||
if (world.mode[player] == 'inverted') == (owid in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
connect_simple(world, 'Flute Spot ' + str(o + 1), regions[0], player)
|
||||
else:
|
||||
connect_simple(world, 'Flute Spot ' + str(o + 1), regions[1], player)
|
||||
|
||||
if world.owFluteShuffle[player] == 'vanilla':
|
||||
connect_flutes(default_flute_connections)
|
||||
else:
|
||||
flute_pool = list(flute_data.keys())
|
||||
new_spots = SortedList()
|
||||
|
||||
# guarantee desert/mire access
|
||||
flute_pool.remove(0x30)
|
||||
new_spots.add(0x30)
|
||||
# guarantee mountain access
|
||||
owid = random.randint(0, 2) * 2 + 3
|
||||
flute_pool.remove(owid)
|
||||
new_spots.add(owid)
|
||||
|
||||
random.shuffle(flute_pool)
|
||||
f = 0
|
||||
while len(new_spots) < 8:
|
||||
new_spots.add(flute_pool[f])
|
||||
f += 1
|
||||
world.owflutespots[player] = new_spots
|
||||
connect_flutes(new_spots)
|
||||
|
||||
# make new connections
|
||||
for owid in ow_connections.keys():
|
||||
if (world.mode[player] == 'inverted') == (owid in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
for (exitname, regionname) in ow_connections[owid][0]:
|
||||
@@ -688,15 +714,9 @@ mandatory_connections = [('Flute Away', 'Flute Sky'),
|
||||
('Dark Tree Line WC Cliff Water Drop', 'Dark Tree Line Water') #fake flipper
|
||||
]
|
||||
|
||||
flute_connections = {0x03: ('Flute Spot 1', ['West Death Mountain (Bottom)', 'West Dark Death Mountain (Bottom)']),
|
||||
0x16: ('Flute Spot 2', ['Potion Shop Area', 'Dark Witch Area']),
|
||||
0x18: ('Flute Spot 3', ['Kakariko Area', 'Village of Outcasts Area']),
|
||||
0x2c: ('Flute Spot 4', ['Links House Area', 'Big Bomb Shop Area']),
|
||||
0x2f: ('Flute Spot 5', ['Eastern Nook Area', 'Palace of Darkness Nook Area']),
|
||||
0x30: ('Flute Spot 6', ['Desert Palace Teleporter Ledge', 'Misery Mire Teleporter Ledge']),
|
||||
0x3b: ('Flute Spot 7', ['Dam Area', 'Swamp Area']),
|
||||
0x3f: ('Flute Spot 8', ['Octoballoon Area', 'Bomber Corner Area'])
|
||||
}
|
||||
default_flute_connections = [
|
||||
0x03, 0x16, 0x18, 0x2c, 0x2f, 0x30, 0x3b, 0x3f
|
||||
]
|
||||
|
||||
ow_connections = {
|
||||
0x00: ([
|
||||
@@ -1193,3 +1213,47 @@ default_connections = [('Lost Woods SW', 'Lost Woods Pass NW'),
|
||||
('West Dark Death Mountain ES', 'East Dark Death Mountain WS'),
|
||||
('East Dark Death Mountain EN', 'Turtle Rock WN')
|
||||
]
|
||||
|
||||
flute_data = {
|
||||
#OWID LW Region DW Region VRAM BG Y BG X Link Y Link X Cam Y Cam X Unk1 Unk2 IconY IconX AltY AltX
|
||||
0x00: (['Lost Woods East Area', 'Skull Woods Forest'], 0x1042, 0x022e, 0x0202, 0x0290, 0x0288, 0x029b, 0x028f, 0xfff2, 0x000e, 0x0290, 0x0288, 0x0290, 0x0290),
|
||||
0x02: (['Lumberjack Area', 'Dark Lumberjack Area'], 0x059c, 0x00d6, 0x04e6, 0x0138, 0x0558, 0x0143, 0x0563, 0xfffa, 0xfffa, 0x0138, 0x0550),
|
||||
0x03: (['West Death Mountain (Bottom)', 'West Dark Death Mountain (Bottom)'], 0x1600, 0x02ca, 0x060e, 0x0328, 0x0678, 0x0337, 0x0683, 0xfff6, 0xfff2, 0x035b, 0x0680),
|
||||
0x05: (['East Death Mountain (Bottom)', 'East Dark Death Mountain (Bottom)'], 0x1860, 0x031e, 0x0d00, 0x0388, 0x0da8, 0x038d, 0x0d7d, 0x0000, 0x0000, 0x0388, 0x0da8),
|
||||
0x07: (['Death Mountain TR Pegs', 'Turtle Rock Area'], 0x0804, 0x0102, 0x0e1a, 0x0160, 0x0e90, 0x016f, 0x0e97, 0xfffe, 0x0006, 0x0160, 0x0f20),
|
||||
0x0a: (['Mountain Entry Area', 'Bumper Cave Area'], 0x0180, 0x0220, 0x0206, 0x0280, 0x0488, 0x028f, 0x0493, 0x0000, 0xfffa, 0x0280, 0x0488),
|
||||
0x0f: (['Zora Waterfall Area', 'Catfish Area'], 0x0316, 0x025c, 0x0eb2, 0x02c0, 0x0f28, 0x02cb, 0x0f2f, 0x0002, 0xfffe, 0x02d0, 0x0f38),
|
||||
0x10: (['Lost Woods Pass West Area', 'Skull Woods Pass West Area'], 0x0080, 0x0400, 0x0000, 0x0448, 0x0058, 0x046f, 0x0085, 0x0000, 0x0000, 0x0448, 0x0058),
|
||||
0x11: (['Kakariko Fortune Area', 'Dark Fortune Area'], 0x0912, 0x051e, 0x0292, 0x0588, 0x0318, 0x058d, 0x031f, 0x0000, 0xfffe, 0x0588, 0x0318),
|
||||
0x12: (['Kakariko Pond Area', 'Outcast Pond Area'], 0x0890, 0x051a, 0x0476, 0x0578, 0x04f8, 0x0587, 0x0503, 0xfff6, 0x000a, 0x0578, 0x04f8),
|
||||
0x13: (['Sanctuary Area', 'Dark Chapel Area'], 0x051c, 0x04aa, 0x06de, 0x0508, 0x0758, 0x0517, 0x0763, 0xfff6, 0x0002, 0x0508, 0x0758),
|
||||
0x14: (['Graveyard Area', 'Dark Graveyard Area'], 0x089c, 0x051e, 0x08e6, 0x0580, 0x0958, 0x058b, 0x0963, 0x0000, 0xfffa, 0x0580, 0x0928, 0x0580, 0x0948),
|
||||
0x15: (['River Bend East Bank', 'Qirn Jump East Bank'], 0x041a, 0x0486, 0x0ad2, 0x04e8, 0x0b48, 0x04f3, 0x0b4f, 0x0008, 0xfffe, 0x04f8, 0x0b60),
|
||||
0x16: (['Potion Shop Area', 'Dark Witch Area'], 0x0888, 0x0516, 0x0c4e, 0x0578, 0x0cc8, 0x0583, 0x0cd3, 0xfffa, 0xfff2, 0x0598, 0x0ccf),
|
||||
0x17: (['Zora Approach Ledge', 'Catfish Approach Ledge'], 0x039e, 0x047e, 0x0ef2, 0x04e0, 0x0f68, 0x04eb, 0x0f6f, 0x0000, 0xfffe, 0x04e0, 0x0f68),
|
||||
0x18: (['Kakariko Area', 'Village of Outcasts Area'], 0x0b30, 0x0759, 0x017e, 0x07c8, 0x01f8, 0x07c6, 0x020b, 0x0007, 0x0002, 0x07c0, 0x0210, 0x01f8, 0x07c6),
|
||||
0x1a: (['Forgotten Forest Area', 'Shield Shop Fence'], 0x081a, 0x070f, 0x04d2, 0x0770, 0x0548, 0x077c, 0x054f, 0xffff, 0xfffe, 0x0770, 0x0548),
|
||||
0x1b: (['Hyrule Castle Courtyard', 'Pyramid Area'], 0x0c30, 0x077a, 0x0786, 0x07d8, 0x07f8, 0x07e7, 0x0803, 0x0006, 0xfffa, 0x07d8, 0x07f8),
|
||||
0x1d: (['Wooden Bridge Area', 'Broken Bridge Northeast'], 0x0602, 0x06c2, 0x0a0e, 0x0720, 0x0a80, 0x072f, 0x0a8b, 0xfffe, 0x0002, 0x0720, 0x0a80),
|
||||
0x1e: (['Eastern Palace Area', 'Palace of Darkness Area'], 0x1802, 0x091e, 0x0c0e, 0x09c0, 0x0c80, 0x098b, 0x0c8b, 0x0000, 0x0002, 0x09c0, 0x0c80),
|
||||
0x22: (['Blacksmith Area', 'Hammer Pegs Area'], 0x058c, 0x08aa, 0x0462, 0x0908, 0x04d8, 0x0917, 0x04df, 0x0006, 0xfffe, 0x0908, 0x04d8),
|
||||
0x25: (['Sand Dunes Area', 'Dark Dunes Area'], 0x030e, 0x085a, 0x0a76, 0x08b8, 0x0ae8, 0x08c7, 0x0af3, 0x0006, 0xfffa, 0x08b8, 0x0b08),
|
||||
0x28: (['Maze Race Area', 'Dig Game Area'], 0x0908, 0x0b1e, 0x003a, 0x0b88, 0x00b8, 0x0b8d, 0x00bf, 0x0000, 0x0006, 0x0b88, 0x00b8),
|
||||
0x29: (['Kakariko Suburb Area', 'Frog Area'], 0x0408, 0x0a7c, 0x0242, 0x0ae0, 0x02c0, 0x0aeb, 0x02c7, 0x0002, 0xfffe, 0x0ae0, 0x02c0),
|
||||
0x2a: (['Flute Boy Area', 'Stumpy Area'], 0x058e, 0x0aac, 0x046e, 0x0b10, 0x04e8, 0x0b1b, 0x04f3, 0x0002, 0x0002, 0x0b10, 0x04e8),
|
||||
0x2b: (['Central Bonk Rocks Area', 'Dark Bonk Rocks Area'], 0x0620, 0x0acc, 0x0700, 0x0b30, 0x0790, 0x0b3b, 0x0785, 0xfff2, 0x0000, 0x0b30, 0x0770),
|
||||
0x2c: (['Links House Area', 'Big Bomb Shop Area'], 0x0588, 0x0ab9, 0x0840, 0x0b17, 0x08b8, 0x0b26, 0x08bf, 0xfff7, 0x0000, 0x0b20, 0x08b8),
|
||||
0x2d: (['Stone Bridge Area', 'Hammer Bridge South Area'], 0x0886, 0x0b1e, 0x0a2a, 0x0ba0, 0x0aa8, 0x0b8b, 0x0aaf, 0x0000, 0x0006, 0x0bc4, 0x0ad0),
|
||||
0x2e: (['Tree Line Area', 'Dark Tree Line Area'], 0x0100, 0x0a1a, 0x0c00, 0x0a78, 0x0c30, 0x0a87, 0x0c7d, 0x0006, 0x0000, 0x0a78, 0x0c58),
|
||||
0x2f: (['Eastern Nook Area', 'Palace of Darkness Nook Area'], 0x0798, 0x0afa, 0x0eb2, 0x0b58, 0x0f30, 0x0b67, 0x0f37, 0xfff6, 0x000e, 0x0b50, 0x0f30),
|
||||
0x30: (['Desert Palace Teleporter Ledge', 'Misery Mire Teleporter Ledge'], 0x1880, 0x0f1e, 0x0000, 0x0fa8, 0x0078, 0x0f8d, 0x008d, 0x0000, 0x0000, 0x0fb0, 0x0070),
|
||||
0x32: (['Flute Boy Approach Area', 'Stumpy Approach Area'], 0x03a0, 0x0c6c, 0x0500, 0x0cd0, 0x05a8, 0x0cdb, 0x0585, 0x0002, 0x0000, 0x0cd6, 0x05a8),
|
||||
0x33: (['C Whirlpool Outer Area', 'Dark C Whirlpool Outer Area'], 0x0180, 0x0c20, 0x0600, 0x0c80, 0x0628, 0x0c8f, 0x067d, 0x0000, 0x0000, 0x0c80, 0x0628),
|
||||
0x34: (['Statues Area', 'Hype Cave Area'], 0x088e, 0x0d00, 0x0866, 0x0d60, 0x08d8, 0x0d6f, 0x08e3, 0x0000, 0x000a, 0x0d60, 0x08d8),
|
||||
0x35: (['Lake Hylia Area', 'Ice Lake Area'], 0x0d00, 0x0da6, 0x0a06, 0x0e08, 0x0a80, 0x0e13, 0x0a8b, 0xfffa, 0xfffa, 0x0d88, 0x0a88),
|
||||
0x37: (['Ice Cave Area', 'Shopping Mall Area'], 0x0786, 0x0cf6, 0x0e2e, 0x0d58, 0x0ea0, 0x0d63, 0x0eab, 0x000a, 0x0002, 0x0d48, 0x0ed0),
|
||||
0x3a: (['Desert Pass Area', 'Swamp Nook Area'], 0x001a, 0x0e08, 0x04c6, 0x0e70, 0x0540, 0x0e7d, 0x054b, 0x0006, 0x000a, 0x0e70, 0x0540),
|
||||
0x3b: (['Dam Area', 'Swamp Area'], 0x069e, 0x0edf, 0x06f2, 0x0f3d, 0x0778, 0x0f4c, 0x077f, 0xfff1, 0xfffe, 0x0f30, 0x0770),
|
||||
0x3c: (['South Pass Area', 'Dark South Pass Area'], 0x0584, 0x0ed0, 0x081e, 0x0f38, 0x0898, 0x0f45, 0x08a3, 0xfffe, 0x0002, 0x0f38, 0x0898),
|
||||
0x3f: (['Octoballoon Area', 'Bomber Corner Area'], 0x0810, 0x0f05, 0x0e75, 0x0f67, 0x0ef3, 0x0f72, 0x0efa, 0xfffb, 0x000b, 0x0f80, 0x0ef0)
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ def main(args):
|
||||
start_time = time.process_time()
|
||||
|
||||
# initialize the world
|
||||
world = World(1, 'vanilla', 'noglitches', 'standard', 'normal', 'none', 'on', 'ganon', 'freshness', False, False, False, False, False, False, None, False)
|
||||
world = World(1, 'vanilla', 'vanilla', 'vanilla', 'vanilla', 'noglitches', 'standard', 'normal', 'none', 'on', 'ganon', 'freshness', False, False, False, False, False, False, None, False)
|
||||
world.player_names[1].append("Player 1")
|
||||
logger = logging.getLogger('')
|
||||
|
||||
|
||||
16
README.md
16
README.md
@@ -85,6 +85,16 @@ OW tiles remain in their original world, but transitions can now be travel cross
|
||||
|
||||
This keeps similar edge transitions together. ie. The 2 west edges of Potion Shop will be paired to another set of two similar edges
|
||||
|
||||
## Flute Shuffle (--ow_fluteshuffle)
|
||||
|
||||
### Vanilla
|
||||
|
||||
Flute spots remain unchanged.
|
||||
|
||||
### Random
|
||||
|
||||
New flute spots are chosen at random. You can also cancel out of the flute menu by pressing X.
|
||||
|
||||
|
||||
# Command Line Options
|
||||
|
||||
@@ -111,3 +121,9 @@ For specifying the overworld tile swap you want as above. (default: vanilla)
|
||||
```
|
||||
|
||||
This keeps similar edge transitions paired together with other pairs of transitions
|
||||
|
||||
```
|
||||
--ow_fluteshuffle <mode>
|
||||
```
|
||||
|
||||
For randomizing the flute spots around the overworld
|
||||
|
||||
64
Rom.py
64
Rom.py
@@ -24,10 +24,11 @@ from Text import KingsReturn_texts, Sanctuary_texts, Kakariko_texts, Blacksmiths
|
||||
from Utils import output_path, local_path, int16_as_bytes, int32_as_bytes, snes_to_pc
|
||||
from Items import ItemFactory
|
||||
from EntranceShuffle import door_addresses, exit_ids
|
||||
from OverworldShuffle import default_flute_connections, flute_data
|
||||
|
||||
|
||||
JAP10HASH = '03a63945398191337e896e5771f77173'
|
||||
RANDOMIZERBASEHASH = '5fecbc1016544cfdcc596abffaed6736'
|
||||
RANDOMIZERBASEHASH = '6e44346357f8a9471a8499ab787635c1'
|
||||
|
||||
|
||||
class JsonRom(object):
|
||||
@@ -625,6 +626,8 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
||||
owFlags = 0
|
||||
if world.owKeepSimilar[player]:
|
||||
owFlags |= 0x1
|
||||
if world.owFluteShuffle[player] != 'vanilla':
|
||||
owFlags |= 0x100
|
||||
|
||||
write_int16(rom, 0x150004, owFlags)
|
||||
|
||||
@@ -645,6 +648,37 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
||||
write_int16(rom, edge.getAddress() + 0x0a, edge.vramLoc)
|
||||
write_int16(rom, edge.getAddress() + 0x0e, edge.getTarget())
|
||||
|
||||
# patch flute spots
|
||||
if world.owFluteShuffle[player] == 'vanilla':
|
||||
flute_spots = default_flute_connections
|
||||
else:
|
||||
flute_spots = world.owflutespots[player]
|
||||
|
||||
for o in range(0, len(flute_spots)):
|
||||
owid = flute_spots[o]
|
||||
offset = 0
|
||||
if (world.mode[player] == 'inverted') != (owid in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
offset = 0x40
|
||||
|
||||
data = flute_data[owid]
|
||||
write_int16(rom, snes_to_pc(0x02E849 + (o * 2)), owid + offset) # owid
|
||||
write_int16(rom, snes_to_pc(0x02E86B + (o * 2)), data[1]) #vram
|
||||
write_int16(rom, snes_to_pc(0x02E88D + (o * 2)), data[2]) # BG scroll Y
|
||||
write_int16(rom, snes_to_pc(0x02E8AF + (o * 2)), data[3]) # BG scroll X
|
||||
write_int16(rom, snes_to_pc(0x02E8D1 + (o * 2)), data[12] if offset > 0 and len(data) > 12 else data[4]) # link Y
|
||||
write_int16(rom, snes_to_pc(0x02E8F3 + (o * 2)), data[13] if offset > 0 and len(data) > 12 else data[5]) # link X
|
||||
write_int16(rom, snes_to_pc(0x02E915 + (o * 2)), data[6]) # cam Y
|
||||
write_int16(rom, snes_to_pc(0x02E937 + (o * 2)), data[7]) # cam X
|
||||
write_int16(rom, snes_to_pc(0x02E959 + (o * 2)), data[8]) # unknown 1
|
||||
write_int16(rom, snes_to_pc(0x02E97B + (o * 2)), data[9]) # unknown 2
|
||||
|
||||
# flute menu blips
|
||||
rom.buffer[snes_to_pc(0x0AB783 + o)] = data[11] & 0xff # X low byte
|
||||
rom.buffer[snes_to_pc(0x0AB78B + o)] = data[11] // 0x100 # X high byte
|
||||
rom.buffer[snes_to_pc(0x0AB793 + o)] = data[10] & 0xff # Y low byte
|
||||
rom.buffer[snes_to_pc(0x0AB79B + o)] = data[10] // 0x100 # Y high byte
|
||||
|
||||
|
||||
# patch entrance/exits/holes
|
||||
for region in world.regions:
|
||||
for exit in region.exits:
|
||||
@@ -2285,7 +2319,7 @@ def set_inverted_mode(world, player, rom):
|
||||
write_int16(rom, 0x15AEE + 2*0x25, 0x000C)
|
||||
|
||||
if (world.mode[player] == 'inverted') != (0x03 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
write_int16(rom, snes_to_pc(0x02E849), 0x0043) #flute spot
|
||||
#write_int16(rom, snes_to_pc(0x02E849), 0x0043) #flute spot
|
||||
if world.shuffle[player] in ['vanilla', 'dungeonsfull', 'dungeonssimple']:
|
||||
rom.write_bytes(snes_to_pc(0x308350), [0x00, 0x00, 0x01]) # mountain cave starts on OW
|
||||
|
||||
@@ -2352,12 +2386,12 @@ def set_inverted_mode(world, player, rom):
|
||||
write_int16(rom, 0x15AEE + 2*0x18, 0x00E6) # DMD west UW to bumper cave top entrance
|
||||
if (world.mode[player] == 'inverted') != (0x10 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
rom.write_bytes(snes_to_pc(0x1BC67A), [0x2E, 0x0B, 0x82]) # add warp under rock
|
||||
if (world.mode[player] == 'inverted') != (0x16 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
write_int16(rom, snes_to_pc(0x02E84B), 0x0056) #flute spot
|
||||
if (world.mode[player] == 'inverted') != (0x18 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
write_int16(rom, snes_to_pc(0x02E84D), 0x0058) #flute spot
|
||||
write_int16(rom, snes_to_pc(0x02E8D5), 0x07C8) #flute spot
|
||||
write_int16(rom, snes_to_pc(0x02E8F7), 0x01F8) #flute spot
|
||||
#if (world.mode[player] == 'inverted') != (0x16 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
#write_int16(rom, snes_to_pc(0x02E84B), 0x0056) #flute spot
|
||||
#if (world.mode[player] == 'inverted') != (0x18 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
#write_int16(rom, snes_to_pc(0x02E84D), 0x0058) #flute spot
|
||||
#write_int16(rom, snes_to_pc(0x02E8D5), 0x07C8) #flute spot
|
||||
#write_int16(rom, snes_to_pc(0x02E8F7), 0x01F8) #flute spot
|
||||
if (world.mode[player] == 'inverted') != (0x1B in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
write_int16(rom, 0x15AEE + 2 * 0x06, 0x0020) # post aga hyrule castle spawn
|
||||
rom.write_byte(0x15B8C + 0x06, 0x1B)
|
||||
@@ -2466,26 +2500,26 @@ def set_inverted_mode(world, player, rom):
|
||||
if (world.mode[player] == 'inverted') != (0x29 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
rom.write_bytes(snes_to_pc(0x06B2AB), [0xF0, 0xE1, 0x05]) #frog pickup on contact
|
||||
if (world.mode[player] == 'inverted') != (0x2C in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
write_int16(rom, snes_to_pc(0x02E84F), 0x006C) #flute spot
|
||||
#write_int16(rom, snes_to_pc(0x02E84F), 0x006C) #flute spot
|
||||
if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull']:
|
||||
rom.write_byte(0x15B8C, 0x6C) #exit links at bomb shop area
|
||||
rom.write_byte(0xDBB73 + 0x00, 0x53) # switch bomb shop and links house
|
||||
rom.write_byte(0xDBB73 + 0x52, 0x01)
|
||||
if (world.mode[player] == 'inverted') != (0x2F in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
write_int16(rom, snes_to_pc(0x02E851), 0x006F) #flute spot
|
||||
#write_int16(rom, snes_to_pc(0x02E851), 0x006F) #flute spot
|
||||
rom.write_bytes(snes_to_pc(0x1BC80D), [0xB2, 0x0B, 0x82]) # add warp under rock
|
||||
if (world.mode[player] == 'inverted') != (0x30 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
write_int16(rom, snes_to_pc(0x02E853), 0x0070) #flute spot
|
||||
#write_int16(rom, snes_to_pc(0x02E853), 0x0070) #flute spot
|
||||
rom.write_bytes(snes_to_pc(0x1BC81E), [0x94, 0x1D, 0x82]) # add warp under rock
|
||||
if (world.mode[player] == 'inverted') != (0x33 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
rom.write_bytes(snes_to_pc(0x1BC3DF), [0xD8, 0xD1]) # add warp under rock
|
||||
rom.write_bytes(snes_to_pc(0x1BD1D8), [0xA8, 0x02, 0x82, 0xFF, 0xFF]) # add warp under rock
|
||||
if (world.mode[player] == 'inverted') != (0x35 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
rom.write_bytes(snes_to_pc(0x1BC85A), [0x50, 0x0F, 0x82]) # add warp under rock
|
||||
if (world.mode[player] == 'inverted') != (0x3B in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
write_int16(rom, snes_to_pc(0x02E855), 0x007B) #flute spot
|
||||
if (world.mode[player] == 'inverted') != (0x3F in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
write_int16(rom, snes_to_pc(0x02E857), 0x007F) #flute spot
|
||||
#if (world.mode[player] == 'inverted') != (0x3B in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
#write_int16(rom, snes_to_pc(0x02E855), 0x007B) #flute spot
|
||||
#if (world.mode[player] == 'inverted') != (0x3F in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
#write_int16(rom, snes_to_pc(0x02E857), 0x007F) #flute spot
|
||||
|
||||
if world.mode[player] == 'inverted':
|
||||
rom.write_byte(0x15B8C + 0x3D, rom.buffer[0x15B8C]) # houlihan exit
|
||||
|
||||
@@ -106,7 +106,7 @@ OWWorldCheck16:
|
||||
|
||||
OWFluteCancel:
|
||||
{
|
||||
lda.l OWFlags+1 : and #$10 : bne +
|
||||
lda.l OWFlags+1 : and #$01 : bne +
|
||||
jsl $02e99d : rtl
|
||||
+ lda $7f5006 : cmp #$01 : beq +
|
||||
jsl $02e99d
|
||||
@@ -117,7 +117,7 @@ OWFluteCancel2:
|
||||
lda $f2 : ora $f0 : and #$c0 : bne +
|
||||
jml $0ab7bd
|
||||
+ inc $0200
|
||||
lda.l OWFlags+1 : and #$10 : beq +
|
||||
lda.l OWFlags+1 : and #$01 : beq +
|
||||
lda $f2 : cmp #$40 : bne +
|
||||
lda #$01 : sta $7f5006
|
||||
+ rtl
|
||||
|
||||
Binary file not shown.
@@ -127,6 +127,12 @@
|
||||
"action": "store_true",
|
||||
"type": "bool"
|
||||
},
|
||||
"ow_fluteshuffle": {
|
||||
"choices": [
|
||||
"vanilla",
|
||||
"random"
|
||||
]
|
||||
},
|
||||
"shuffle": {
|
||||
"choices": [
|
||||
"vanilla",
|
||||
|
||||
@@ -214,6 +214,11 @@
|
||||
"ow_keepsimilar": [
|
||||
"This keeps similar edge transitions together. ie. the two west edges on",
|
||||
"Potion Shop will be paired with another similar pair." ],
|
||||
"ow_fluteshuffle": [
|
||||
"This randomizes the flute spot destinations.",
|
||||
"Vanilla: All flute spots remain unchanged.",
|
||||
"Random: New flute spots will be generated."
|
||||
],
|
||||
"door_shuffle": [
|
||||
"Select Door Shuffling Algorithm. (default: %(default)s)",
|
||||
"Basic: Doors are mixed within a single dungeon.",
|
||||
|
||||
@@ -121,6 +121,10 @@
|
||||
|
||||
"randomizer.overworld.keepsimilar": "Keep Similar Edges Together",
|
||||
|
||||
"randomizer.overworld.overworldflute": "Flute Shuffle",
|
||||
"randomizer.overworld.overworldflute.vanilla": "Vanilla",
|
||||
"randomizer.overworld.overworldflute.random": "Random",
|
||||
|
||||
"randomizer.entrance.openpyramid": "Pre-open Pyramid Hole",
|
||||
"randomizer.entrance.shuffleganon": "Include Ganon's Tower and Pyramid Hole in shuffle pool",
|
||||
"randomizer.entrance.shufflelinks": "Include Link's House in the shuffle pool",
|
||||
|
||||
@@ -17,6 +17,14 @@
|
||||
"mixed",
|
||||
"crossed"
|
||||
]
|
||||
},
|
||||
"overworldflute": {
|
||||
"type": "selectbox",
|
||||
"default": "vanilla",
|
||||
"options": [
|
||||
"vanilla",
|
||||
"random"
|
||||
]
|
||||
}
|
||||
},
|
||||
"rightOverworldFrame": {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
aenum
|
||||
fast-enum
|
||||
python-bps-continued
|
||||
sortedcontainers
|
||||
colorama
|
||||
aioconsole
|
||||
websockets
|
||||
|
||||
@@ -75,7 +75,8 @@ SETTINGSTOPROCESS = {
|
||||
"overworld": {
|
||||
"overworldshuffle": "ow_shuffle",
|
||||
"overworldswap": "ow_swap",
|
||||
"keepsimilar": "ow_keepsimilar"
|
||||
"keepsimilar": "ow_keepsimilar",
|
||||
"overworldflute": "ow_fluteshuffle"
|
||||
},
|
||||
"entrance": {
|
||||
"openpyramid": "openpyramid",
|
||||
|
||||
Reference in New Issue
Block a user