Merge branch 'OverworldShuffleDev' into OverworldShuffle
This commit is contained in:
@@ -139,7 +139,7 @@ class World(object):
|
||||
set_player_attr('treasure_hunt_total', 0)
|
||||
set_player_attr('potshuffle', False)
|
||||
set_player_attr('pot_contents', None)
|
||||
set_player_attr('fakeboots', False)
|
||||
set_player_attr('pseudoboots', False)
|
||||
|
||||
set_player_attr('shopsanity', False)
|
||||
set_player_attr('keydropshuffle', False)
|
||||
@@ -2244,7 +2244,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('Flute Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['ow_fluteshuffle'][player])
|
||||
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])
|
||||
|
||||
@@ -1,11 +1,18 @@
|
||||
# Changelog
|
||||
|
||||
### 0.1.6.7
|
||||
- Fixed issue with Pyramid Exit exiting to wrong location in ER
|
||||
- Mountain Entry and West Death Mountain are now Swapped independently (Old Man rescue is always in your starting world)
|
||||
- Fixed issue with AT/GT access logic
|
||||
- Improved spoiler log playthru accuracy
|
||||
- ~~Merged DR v0.4.0.11 - Various DR changes~~
|
||||
|
||||
### 0.1.6.6
|
||||
- ~~Merged DR v0.4.0.9 - P/C Indicator / Credits fix / CLI Hints Fix~~
|
||||
|
||||
### 0.1.6.5
|
||||
- Reduced chance of diagonal flute spot in Balanced
|
||||
- ~~Merged DR v0.4.0.8 - Boss Indicator / Fake Boots / Quickswap Update / Credits Updates~~
|
||||
- ~~Merged DR v0.4.0.8 - Boss Indicator / Psuedo Boots / Quickswap Update / Credits Updates~~
|
||||
|
||||
### 0.1.6.4
|
||||
- Fixed Frogsmith and Stumpy and restored progression in these locations
|
||||
|
||||
4
CLI.py
4
CLI.py
@@ -98,7 +98,7 @@ def parse_cli(argv, no_defaults=False):
|
||||
'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',
|
||||
'triforce_min_difference', 'triforce_goal', 'triforce_pool', 'shufflelinks', 'fakeboots',
|
||||
'triforce_min_difference', 'triforce_goal', 'triforce_pool', 'shufflelinks', 'pseudoboots',
|
||||
'retro', 'accessibility', 'hints', 'beemizer', 'experimental', 'dungeon_counters',
|
||||
'shufflebosses', 'shuffleenemies', 'enemy_health', 'enemy_damage', 'shufflepots',
|
||||
'ow_palettes', 'uw_palettes', 'sprite', 'disablemusic', 'quickswap', 'fastmenu', 'heartcolor', 'heartbeep',
|
||||
@@ -149,7 +149,7 @@ def parse_settings():
|
||||
"ow_fluteshuffle": "vanilla",
|
||||
"shuffle": "vanilla",
|
||||
"shufflelinks": False,
|
||||
"fakeboots": False,
|
||||
"pseudoboots": False,
|
||||
|
||||
"shufflepots": False,
|
||||
"shuffleenemies": "none",
|
||||
|
||||
@@ -100,8 +100,8 @@ def link_doors_main(world, player):
|
||||
analyze_portals(world, player)
|
||||
for portal in world.dungeon_portals[player]:
|
||||
connect_portal(portal, world, player)
|
||||
|
||||
fix_big_key_doors_with_ugly_smalls(world, player)
|
||||
if not world.doorShuffle[player] == 'vanilla':
|
||||
fix_big_key_doors_with_ugly_smalls(world, player)
|
||||
if world.doorShuffle[player] == 'vanilla':
|
||||
for entrance, ext in open_edges:
|
||||
connect_two_way(world, entrance, ext, player)
|
||||
@@ -1678,7 +1678,7 @@ def change_door_to_small_key(d, world, player):
|
||||
def smooth_door_pairs(world, player):
|
||||
all_doors = [x for x in world.doors if x.player == player]
|
||||
skip = set()
|
||||
bd_candidates, dashable_counts, bombable_counts = defaultdict(list), defaultdict(int), defaultdict(int)
|
||||
bd_candidates = defaultdict(list)
|
||||
for door in all_doors:
|
||||
if door.type in [DoorType.Normal, DoorType.Interior] and door not in skip and not door.entranceFlag:
|
||||
partner = door.dest
|
||||
@@ -1704,30 +1704,19 @@ def smooth_door_pairs(world, player):
|
||||
remove_pair(door, world, player)
|
||||
if type_b == DoorKind.SmallKey:
|
||||
remove_pair(door, world, player)
|
||||
elif type_a in [DoorKind.Bombable, DoorKind.Dashable] or type_b in [DoorKind.Bombable, DoorKind.Dashable]:
|
||||
else:
|
||||
if valid_pair:
|
||||
new_type = type_a
|
||||
if type_a != type_b:
|
||||
new_type = DoorKind.Dashable if type_a == DoorKind.Dashable or type_b == DoorKind.Dashable else DoorKind.Bombable
|
||||
if type_a != new_type:
|
||||
room_a.change(door.doorListPos, new_type)
|
||||
if type_b != new_type:
|
||||
room_b.change(partner.doorListPos, new_type)
|
||||
add_pair(door, partner, world, player)
|
||||
spoiler_type = 'Bomb Door' if new_type == DoorKind.Bombable else 'Dash Door'
|
||||
world.spoiler.set_door_type(door.name + ' <-> ' + partner.name, spoiler_type, player)
|
||||
counter = bombable_counts if new_type == DoorKind.Bombable else dashable_counts
|
||||
counter[door.entrance.parent_region.dungeon] += 1
|
||||
else:
|
||||
bd_candidates[door.entrance.parent_region.dungeon].append(door)
|
||||
elif type_a in [DoorKind.Bombable, DoorKind.Dashable] or type_b in [DoorKind.Bombable, DoorKind.Dashable]:
|
||||
if type_a in [DoorKind.Bombable, DoorKind.Dashable]:
|
||||
room_a.change(door.doorListPos, DoorKind.Normal)
|
||||
remove_pair(door, world, player)
|
||||
elif type_b in [DoorKind.Bombable, DoorKind.Dashable]:
|
||||
else:
|
||||
room_b.change(partner.doorListPos, DoorKind.Normal)
|
||||
remove_pair(partner, world, player)
|
||||
elif valid_pair and type_a != DoorKind.SmallKey and type_b != DoorKind.SmallKey:
|
||||
bd_candidates[door.entrance.parent_region.dungeon].append(door)
|
||||
shuffle_bombable_dashable(bd_candidates, bombable_counts, dashable_counts, world, player)
|
||||
shuffle_bombable_dashable(bd_candidates, world, player)
|
||||
world.paired_doors[player] = [x for x in world.paired_doors[player] if x.pair or x.original]
|
||||
|
||||
|
||||
@@ -1764,15 +1753,15 @@ def stateful_door(door, kind):
|
||||
return False
|
||||
|
||||
|
||||
def shuffle_bombable_dashable(bd_candidates, bombable_counts, dashable_counts, world, player):
|
||||
def shuffle_bombable_dashable(bd_candidates, world, player):
|
||||
if world.doorShuffle[player] == 'basic':
|
||||
for dungeon, candidates in bd_candidates.items():
|
||||
diff = bomb_dash_counts[dungeon.name][1] - dashable_counts[dungeon]
|
||||
diff = bomb_dash_counts[dungeon.name][1]
|
||||
if diff > 0:
|
||||
for chosen in random.sample(candidates, min(diff, len(candidates))):
|
||||
change_pair_type(chosen, DoorKind.Dashable, world, player)
|
||||
candidates.remove(chosen)
|
||||
diff = bomb_dash_counts[dungeon.name][0] - bombable_counts[dungeon]
|
||||
diff = bomb_dash_counts[dungeon.name][0]
|
||||
if diff > 0:
|
||||
for chosen in random.sample(candidates, min(diff, len(candidates))):
|
||||
change_pair_type(chosen, DoorKind.Bombable, world, player)
|
||||
@@ -1781,16 +1770,12 @@ def shuffle_bombable_dashable(bd_candidates, bombable_counts, dashable_counts, w
|
||||
remove_pair_type_if_present(excluded, world, player)
|
||||
elif world.doorShuffle[player] == 'crossed':
|
||||
all_candidates = sum(bd_candidates.values(), [])
|
||||
all_bomb_counts = sum(bombable_counts.values())
|
||||
all_dash_counts = sum(dashable_counts.values())
|
||||
if all_dash_counts < 8:
|
||||
for chosen in random.sample(all_candidates, min(8 - all_dash_counts, len(all_candidates))):
|
||||
change_pair_type(chosen, DoorKind.Dashable, world, player)
|
||||
all_candidates.remove(chosen)
|
||||
if all_bomb_counts < 12:
|
||||
for chosen in random.sample(all_candidates, min(12 - all_bomb_counts, len(all_candidates))):
|
||||
change_pair_type(chosen, DoorKind.Bombable, world, player)
|
||||
all_candidates.remove(chosen)
|
||||
for chosen in random.sample(all_candidates, min(8, len(all_candidates))):
|
||||
change_pair_type(chosen, DoorKind.Dashable, world, player)
|
||||
all_candidates.remove(chosen)
|
||||
for chosen in random.sample(all_candidates, min(12, len(all_candidates))):
|
||||
change_pair_type(chosen, DoorKind.Bombable, world, player)
|
||||
all_candidates.remove(chosen)
|
||||
for excluded in all_candidates:
|
||||
remove_pair_type_if_present(excluded, world, player)
|
||||
|
||||
|
||||
@@ -28,123 +28,124 @@ def link_entrances(world, player):
|
||||
connect_custom(world, player)
|
||||
|
||||
# if we do not shuffle, set default connections
|
||||
if world.shuffle[player] == 'vanilla':
|
||||
if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull']:
|
||||
for exitname, regionname in default_connections:
|
||||
connect_simple(world, exitname, regionname, player)
|
||||
for exitname, regionname in default_dungeon_connections:
|
||||
connect_simple(world, exitname, regionname, player)
|
||||
if world.shuffle[player] == 'vanilla':
|
||||
for exitname, regionname in default_dungeon_connections:
|
||||
connect_simple(world, exitname, regionname, player)
|
||||
|
||||
if not invFlag:
|
||||
for exitname, regionname in open_default_connections:
|
||||
connect_simple(world, exitname, regionname, player)
|
||||
for exitname, regionname in open_default_dungeon_connections:
|
||||
connect_simple(world, exitname, regionname, player)
|
||||
if world.shuffle[player] == 'vanilla':
|
||||
for exitname, regionname in open_default_dungeon_connections:
|
||||
connect_simple(world, exitname, regionname, player)
|
||||
else:
|
||||
for exitname, regionname in inverted_default_connections:
|
||||
connect_simple(world, exitname, regionname, player)
|
||||
for exitname, regionname in inverted_default_dungeon_connections:
|
||||
connect_simple(world, exitname, regionname, player)
|
||||
elif world.shuffle[player] == 'dungeonssimple':
|
||||
for exitname, regionname in default_connections:
|
||||
connect_simple(world, exitname, regionname, player)
|
||||
if world.shuffle[player] == 'vanilla':
|
||||
for exitname, regionname in inverted_default_dungeon_connections:
|
||||
connect_simple(world, exitname, regionname, player)
|
||||
|
||||
# inverted entrance mods
|
||||
for owid in swapped_connections.keys():
|
||||
if (world.mode[player] == 'inverted') != (owid in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
for (entrancename, exitname) in swapped_connections[owid]:
|
||||
try:
|
||||
connect_two_way(world, entrancename, exitname, player)
|
||||
except RuntimeError:
|
||||
connect_entrance(world, entrancename, exitname, player)
|
||||
|
||||
if not invFlag:
|
||||
for exitname, regionname in open_default_connections:
|
||||
connect_simple(world, exitname, regionname, player)
|
||||
else:
|
||||
for exitname, regionname in inverted_default_connections:
|
||||
connect_simple(world, exitname, regionname, player)
|
||||
|
||||
simple_shuffle_dungeons(world, player)
|
||||
elif world.shuffle[player] == 'dungeonsfull':
|
||||
for exitname, regionname in default_connections:
|
||||
connect_simple(world, exitname, regionname, player)
|
||||
|
||||
if not invFlag:
|
||||
for exitname, regionname in open_default_connections:
|
||||
connect_simple(world, exitname, regionname, player)
|
||||
else:
|
||||
for exitname, regionname in inverted_default_connections:
|
||||
connect_simple(world, exitname, regionname, player)
|
||||
if (world.mode[player] == 'inverted') != (0x03 in world.owswaps[player][0] and world.owSwap[player] == 'mixed') and \
|
||||
(world.mode[player] == 'inverted') == (0x0a in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
connect_entrance(world, 'Death Mountain Return Cave (West)', 'Dark Death Mountain Healer Fairy', player)
|
||||
elif (world.mode[player] == 'inverted') != (0x0a in world.owswaps[player][0] and world.owSwap[player] == 'mixed') and \
|
||||
(world.mode[player] == 'inverted') == (0x03 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
connect_two_way(world, 'Bumper Cave (Top)', 'Death Mountain Return Cave Exit (West)', player)
|
||||
|
||||
skull_woods_shuffle(world, player)
|
||||
# dungeon entrance shuffle
|
||||
if world.shuffle[player] == 'dungeonssimple':
|
||||
simple_shuffle_dungeons(world, player)
|
||||
elif world.shuffle[player] == 'dungeonsfull':
|
||||
skull_woods_shuffle(world, player)
|
||||
|
||||
dungeon_exits = list(Dungeon_Exits)
|
||||
lw_entrances = list(LW_Dungeon_Entrances) if not invFlag else list(Inverted_LW_Dungeon_Entrances_Must_Exit)
|
||||
dw_entrances = list(DW_Dungeon_Entrances) if not invFlag else list(Inverted_DW_Dungeon_Entrances)
|
||||
dungeon_exits = list(Dungeon_Exits)
|
||||
lw_entrances = list(LW_Dungeon_Entrances) if not invFlag else list(Inverted_LW_Dungeon_Entrances_Must_Exit)
|
||||
dw_entrances = list(DW_Dungeon_Entrances) if not invFlag else list(Inverted_DW_Dungeon_Entrances)
|
||||
|
||||
if world.mode[player] != 'standard':
|
||||
lw_entrances.append('Hyrule Castle Entrance (South)')
|
||||
|
||||
if not invFlag:
|
||||
if world.mode[player] == 'standard':
|
||||
# must connect front of hyrule castle to do escape
|
||||
connect_two_way(world, 'Hyrule Castle Entrance (South)', 'Hyrule Castle Exit (South)', player)
|
||||
elif world.doorShuffle[player] == 'vanilla':
|
||||
dungeon_exits.append(('Hyrule Castle Exit (South)', 'Hyrule Castle Exit (West)', 'Hyrule Castle Exit (East)'))
|
||||
else:
|
||||
lw_dungeon_entrances_must_exit = list(Inverted_LW_Dungeon_Entrances_Must_Exit)
|
||||
# randomize which desert ledge door is a must-exit
|
||||
if random.randint(0, 1) == 0:
|
||||
lw_dungeon_entrances_must_exit.append('Desert Palace Entrance (North)')
|
||||
lw_entrances.append('Desert Palace Entrance (West)')
|
||||
else:
|
||||
lw_dungeon_entrances_must_exit.append('Desert Palace Entrance (West)')
|
||||
lw_entrances.append('Desert Palace Entrance (North)')
|
||||
dungeon_exits.append(('Hyrule Castle Exit (South)', 'Hyrule Castle Exit (West)', 'Hyrule Castle Exit (East)'))
|
||||
|
||||
if not world.shuffle_ganon:
|
||||
connect_two_way(world, 'Ganons Tower' if not invFlag else 'Agahnims Tower', 'Ganons Tower Exit', player)
|
||||
hc_ledge_entrances = ['Hyrule Castle Entrance (West)', 'Hyrule Castle Entrance (East)']
|
||||
else:
|
||||
if not invFlag:
|
||||
dw_entrances.append('Ganons Tower')
|
||||
else:
|
||||
lw_entrances.append('Agahnims Tower')
|
||||
dungeon_exits.append('Ganons Tower Exit')
|
||||
hc_ledge_entrances = ['Hyrule Castle Entrance (West)', 'Hyrule Castle Entrance (East)', 'Agahnims Tower']
|
||||
|
||||
if not invFlag:
|
||||
if world.mode[player] == 'standard':
|
||||
# rest of hyrule castle must be in light world, so it has to be the one connected to east exit of desert
|
||||
hyrule_castle_exits = [('Hyrule Castle Exit (West)', 'Hyrule Castle Exit (East)')]
|
||||
connect_mandatory_exits(world, lw_entrances, hyrule_castle_exits, list(LW_Dungeon_Entrances_Must_Exit), player)
|
||||
connect_caves(world, lw_entrances, [], hyrule_castle_exits, player)
|
||||
elif world.doorShuffle[player] != 'vanilla':
|
||||
# sanc is in light world, so must all of HC if door shuffle is on
|
||||
connect_mandatory_exits(world, lw_entrances,
|
||||
[('Hyrule Castle Exit (West)', 'Hyrule Castle Exit (East)', 'Hyrule Castle Exit (South)')],
|
||||
list(LW_Dungeon_Entrances_Must_Exit), player)
|
||||
else:
|
||||
connect_mandatory_exits(world, lw_entrances, dungeon_exits, list(LW_Dungeon_Entrances_Must_Exit), player)
|
||||
connect_mandatory_exits(world, dw_entrances, dungeon_exits, list(DW_Dungeon_Entrances_Must_Exit), player)
|
||||
else:
|
||||
# shuffle aga door first. If it's on HC ledge, remaining HC ledge door must be must-exit
|
||||
all_entrances_aga = lw_entrances + dw_entrances
|
||||
aga_doors = [i for i in all_entrances_aga]
|
||||
random.shuffle(aga_doors)
|
||||
aga_door = aga_doors.pop()
|
||||
if world.mode[player] != 'standard':
|
||||
lw_entrances.append('Hyrule Castle Entrance (South)')
|
||||
|
||||
if aga_door in hc_ledge_entrances:
|
||||
lw_entrances.remove(aga_door)
|
||||
hc_ledge_entrances.remove(aga_door)
|
||||
if not invFlag:
|
||||
if world.mode[player] == 'standard':
|
||||
# must connect front of hyrule castle to do escape
|
||||
connect_two_way(world, 'Hyrule Castle Entrance (South)', 'Hyrule Castle Exit (South)', player)
|
||||
elif world.doorShuffle[player] == 'vanilla':
|
||||
dungeon_exits.append(('Hyrule Castle Exit (South)', 'Hyrule Castle Exit (West)', 'Hyrule Castle Exit (East)'))
|
||||
else:
|
||||
lw_dungeon_entrances_must_exit = list(Inverted_LW_Dungeon_Entrances_Must_Exit)
|
||||
# randomize which desert ledge door is a must-exit
|
||||
if random.randint(0, 1) == 0:
|
||||
lw_dungeon_entrances_must_exit.append('Desert Palace Entrance (North)')
|
||||
lw_entrances.append('Desert Palace Entrance (West)')
|
||||
else:
|
||||
lw_dungeon_entrances_must_exit.append('Desert Palace Entrance (West)')
|
||||
lw_entrances.append('Desert Palace Entrance (North)')
|
||||
dungeon_exits.append(('Hyrule Castle Exit (South)', 'Hyrule Castle Exit (West)', 'Hyrule Castle Exit (East)'))
|
||||
|
||||
if not world.shuffle_ganon:
|
||||
connect_two_way(world, 'Ganons Tower' if not invFlag else 'Agahnims Tower', 'Ganons Tower Exit', player)
|
||||
hc_ledge_entrances = ['Hyrule Castle Entrance (West)', 'Hyrule Castle Entrance (East)']
|
||||
else:
|
||||
if not invFlag:
|
||||
dw_entrances.append('Ganons Tower')
|
||||
else:
|
||||
lw_entrances.append('Agahnims Tower')
|
||||
dungeon_exits.append('Ganons Tower Exit')
|
||||
hc_ledge_entrances = ['Hyrule Castle Entrance (West)', 'Hyrule Castle Entrance (East)', 'Agahnims Tower']
|
||||
|
||||
if not invFlag:
|
||||
if world.mode[player] == 'standard':
|
||||
# rest of hyrule castle must be in light world, so it has to be the one connected to east exit of desert
|
||||
hyrule_castle_exits = [('Hyrule Castle Exit (West)', 'Hyrule Castle Exit (East)')]
|
||||
connect_mandatory_exits(world, lw_entrances, hyrule_castle_exits, list(LW_Dungeon_Entrances_Must_Exit), player)
|
||||
connect_caves(world, lw_entrances, [], hyrule_castle_exits, player)
|
||||
elif world.doorShuffle[player] != 'vanilla':
|
||||
# sanc is in light world, so must all of HC if door shuffle is on
|
||||
connect_mandatory_exits(world, lw_entrances,
|
||||
[('Hyrule Castle Exit (West)', 'Hyrule Castle Exit (East)', 'Hyrule Castle Exit (South)')],
|
||||
list(LW_Dungeon_Entrances_Must_Exit), player)
|
||||
else:
|
||||
connect_mandatory_exits(world, lw_entrances, dungeon_exits, list(LW_Dungeon_Entrances_Must_Exit), player)
|
||||
connect_mandatory_exits(world, dw_entrances, dungeon_exits, list(DW_Dungeon_Entrances_Must_Exit), player)
|
||||
else:
|
||||
# shuffle aga door first. If it's on HC ledge, remaining HC ledge door must be must-exit
|
||||
all_entrances_aga = lw_entrances + dw_entrances
|
||||
aga_doors = [i for i in all_entrances_aga]
|
||||
random.shuffle(aga_doors)
|
||||
aga_door = aga_doors.pop()
|
||||
|
||||
random.shuffle(hc_ledge_entrances)
|
||||
hc_ledge_must_exit = hc_ledge_entrances.pop()
|
||||
lw_entrances.remove(hc_ledge_must_exit)
|
||||
lw_dungeon_entrances_must_exit.append(hc_ledge_must_exit)
|
||||
if aga_door in hc_ledge_entrances:
|
||||
lw_entrances.remove(aga_door)
|
||||
hc_ledge_entrances.remove(aga_door)
|
||||
|
||||
random.shuffle(hc_ledge_entrances)
|
||||
hc_ledge_must_exit = hc_ledge_entrances.pop()
|
||||
lw_entrances.remove(hc_ledge_must_exit)
|
||||
lw_dungeon_entrances_must_exit.append(hc_ledge_must_exit)
|
||||
|
||||
if aga_door in lw_entrances:
|
||||
lw_entrances.remove(aga_door)
|
||||
elif aga_door in dw_entrances:
|
||||
dw_entrances.remove(aga_door)
|
||||
if aga_door in lw_entrances:
|
||||
lw_entrances.remove(aga_door)
|
||||
elif aga_door in dw_entrances:
|
||||
dw_entrances.remove(aga_door)
|
||||
|
||||
connect_two_way(world, aga_door, 'Agahnims Tower Exit', player)
|
||||
dungeon_exits.remove('Agahnims Tower Exit')
|
||||
connect_two_way(world, aga_door, 'Agahnims Tower Exit', player)
|
||||
dungeon_exits.remove('Agahnims Tower Exit')
|
||||
|
||||
connect_mandatory_exits(world, lw_entrances, dungeon_exits, lw_dungeon_entrances_must_exit, player)
|
||||
|
||||
connect_caves(world, lw_entrances, dw_entrances, dungeon_exits, player)
|
||||
connect_mandatory_exits(world, lw_entrances, dungeon_exits, lw_dungeon_entrances_must_exit, player)
|
||||
|
||||
connect_caves(world, lw_entrances, dw_entrances, dungeon_exits, player)
|
||||
elif world.shuffle[player] == 'simple':
|
||||
simple_shuffle_dungeons(world, player)
|
||||
|
||||
@@ -1549,7 +1550,9 @@ def connect_entrance(world, entrancename, exitname, player):
|
||||
addresses = door_addresses[entrance.name][0]
|
||||
|
||||
entrance.connect(region, addresses, target)
|
||||
world.spoiler.set_entrance(entrance.name, exit.name if exit is not None else region.name, 'entrance', player)
|
||||
|
||||
if world.shuffle[player] not in ['vanilla', 'dungeonssimple', 'dungeonsfull']:
|
||||
world.spoiler.set_entrance(entrance.name, exit.name if exit is not None else region.name, 'entrance', player)
|
||||
|
||||
def connect_exit(world, exitname, entrancename, player):
|
||||
entrance = world.get_entrance(entrancename, player)
|
||||
@@ -1560,7 +1563,9 @@ def connect_exit(world, exitname, entrancename, player):
|
||||
exit.connected_region.entrances.remove(exit)
|
||||
|
||||
exit.connect(entrance.parent_region, door_addresses[entrance.name][1], exit_ids[exit.name][1])
|
||||
world.spoiler.set_entrance(entrance.name, exit.name, 'exit', player)
|
||||
|
||||
if world.shuffle[player] not in ['vanilla', 'dungeonssimple', 'dungeonsfull']:
|
||||
world.spoiler.set_entrance(entrance.name, exit.name, 'exit', player)
|
||||
|
||||
|
||||
def connect_two_way(world, entrancename, exitname, player):
|
||||
@@ -1575,7 +1580,9 @@ def connect_two_way(world, entrancename, exitname, player):
|
||||
|
||||
entrance.connect(exit.parent_region, door_addresses[entrance.name][0], exit_ids[exit.name][0])
|
||||
exit.connect(entrance.parent_region, door_addresses[entrance.name][1], exit_ids[exit.name][1])
|
||||
world.spoiler.set_entrance(entrance.name, exit.name, 'both', player)
|
||||
|
||||
if world.shuffle[player] not in ['vanilla', 'dungeonssimple', 'dungeonsfull']:
|
||||
world.spoiler.set_entrance(entrance.name, exit.name, 'both', player)
|
||||
|
||||
|
||||
def scramble_holes(world, player):
|
||||
@@ -2866,49 +2873,39 @@ default_connections = [('Waterfall of Wishing', 'Waterfall of Wishing'),
|
||||
('Hookshot Cave Back Entrance', 'Hookshot Cave'),
|
||||
('Mimic Cave', 'Mimic Cave'),
|
||||
|
||||
('Pyramid Hole', 'Pyramid'),
|
||||
('Pyramid Entrance', 'Bottom of Pyramid'),
|
||||
('Inverted Pyramid Hole', 'Pyramid'),
|
||||
('Inverted Pyramid Entrance', 'Bottom of Pyramid')
|
||||
('Pyramid Exit', 'Pyramid Exit Ledge')
|
||||
]
|
||||
|
||||
open_default_connections = [('Old Man Cave (West)', 'Old Man Cave Ledge'),
|
||||
('Old Man Cave (East)', 'Old Man Cave'),
|
||||
('Old Man Cave Exit (West)', 'Mountain Entry Entrance'),
|
||||
('Old Man Cave Exit (East)', 'West Death Mountain (Bottom)'),
|
||||
('Death Mountain Return Cave (East)', 'Death Mountain Return Cave'),
|
||||
('Death Mountain Return Cave (West)', 'Death Mountain Return Cave'),
|
||||
('Death Mountain Return Cave Exit (West)', 'Mountain Entry Ledge'),
|
||||
('Death Mountain Return Cave Exit (East)', 'West Death Mountain (Bottom)'),
|
||||
('Bumper Cave (Bottom)', 'Bumper Cave'),
|
||||
('Bumper Cave (Top)', 'Bumper Cave'),
|
||||
('Bumper Cave Exit (Top)', 'Bumper Cave Ledge'),
|
||||
('Bumper Cave Exit (Bottom)', 'Bumper Cave Entrance'),
|
||||
('Dark Death Mountain Fairy', 'Dark Death Mountain Healer Fairy'),
|
||||
swapped_connections = {
|
||||
0x03: [
|
||||
('Old Man Cave (East)', 'Death Mountain Return Cave Exit (West)'),
|
||||
#('Death Mountain Return Cave (East)', 'Death Mountain Return Cave Exit (East)'),
|
||||
('Dark Death Mountain Fairy', 'Old Man Cave Exit (East)')
|
||||
],
|
||||
0x0a: [
|
||||
('Old Man Cave (West)', 'Bumper Cave Exit (Bottom)'),
|
||||
('Death Mountain Return Cave (West)', 'Bumper Cave Exit (Top)'),
|
||||
('Bumper Cave (Bottom)', 'Old Man Cave Exit (West)'),
|
||||
('Bumper Cave (Top)', 'Dark Death Mountain Healer Fairy')
|
||||
],
|
||||
0x1b: [
|
||||
('Inverted Pyramid Entrance', 'Pyramid Exit')
|
||||
]
|
||||
}
|
||||
|
||||
('Links House', 'Links House'),
|
||||
open_default_connections = [('Links House', 'Links House'),
|
||||
('Links House Exit', 'Links House Area'),
|
||||
('Big Bomb Shop', 'Big Bomb Shop'),
|
||||
('Pyramid Exit', 'Pyramid Exit Ledge')]
|
||||
('Pyramid Hole', 'Pyramid'),
|
||||
('Pyramid Entrance', 'Bottom of Pyramid')
|
||||
]
|
||||
|
||||
inverted_default_connections = [('Old Man Cave (West)', 'Bumper Cave'),
|
||||
('Old Man Cave (East)', 'Death Mountain Return Cave'),
|
||||
('Old Man Cave Exit (West)', 'Bumper Cave Entrance'),
|
||||
('Old Man Cave Exit (East)', 'West Dark Death Mountain (Bottom)'),
|
||||
('Death Mountain Return Cave (West)', 'Bumper Cave'),
|
||||
('Death Mountain Return Cave (East)', 'Death Mountain Return Cave'),
|
||||
('Death Mountain Return Cave Exit (West)', 'West Death Mountain (Bottom)'),
|
||||
('Death Mountain Return Cave Exit (East)', 'West Death Mountain (Bottom)'),
|
||||
('Bumper Cave (Bottom)', 'Old Man Cave Ledge'),
|
||||
('Bumper Cave (Top)', 'Dark Death Mountain Healer Fairy'),
|
||||
('Bumper Cave Exit (Top)', 'Mountain Entry Ledge'),
|
||||
('Bumper Cave Exit (Bottom)', 'Mountain Entry Entrance'),
|
||||
('Dark Death Mountain Fairy', 'Old Man Cave'),
|
||||
|
||||
('Links House', 'Big Bomb Shop'),
|
||||
inverted_default_connections = [('Links House', 'Big Bomb Shop'),
|
||||
('Links House Exit', 'Big Bomb Shop Area'),
|
||||
('Big Bomb Shop', 'Links House'),
|
||||
('Pyramid Exit', 'Hyrule Castle Ledge')]
|
||||
('Inverted Pyramid Hole', 'Pyramid'),
|
||||
('Inverted Pyramid Entrance', 'Bottom of Pyramid')
|
||||
]
|
||||
|
||||
# non shuffled dungeons
|
||||
default_dungeon_connections = [('Desert Palace Entrance (South)', 'Desert South Portal'),
|
||||
|
||||
6
Main.py
6
Main.py
@@ -28,7 +28,7 @@ from Fill import sell_potions, sell_keys, balance_multiworld_progression, balanc
|
||||
from ItemList import generate_itempool, difficulties, fill_prizes, customize_shops
|
||||
from Utils import output_path, parse_player_names
|
||||
|
||||
__version__ = '0.4.0.9-u'
|
||||
__version__ = '0.4.0.11u'
|
||||
|
||||
|
||||
class EnemizerError(RuntimeError):
|
||||
@@ -93,7 +93,7 @@ def main(args, seed=None, fish=None):
|
||||
world.treasure_hunt_count = args.triforce_goal.copy()
|
||||
world.treasure_hunt_total = args.triforce_pool.copy()
|
||||
world.shufflelinks = args.shufflelinks.copy()
|
||||
world.fakeboots = args.fakeboots.copy()
|
||||
world.pseudoboots = args.pseudoboots.copy()
|
||||
|
||||
world.rom_seeds = {player: random.randint(0, 999999999) for player in range(1, world.players + 1)}
|
||||
|
||||
@@ -399,6 +399,8 @@ def copy_world(world):
|
||||
ret.keydropshuffle = world.keydropshuffle.copy()
|
||||
ret.mixed_travel = world.mixed_travel.copy()
|
||||
ret.standardize_palettes = world.standardize_palettes.copy()
|
||||
ret.owswaps = world.owswaps.copy()
|
||||
ret.owflutespots = world.owflutespots.copy()
|
||||
|
||||
for player in range(1, world.players + 1):
|
||||
create_regions(ret, player)
|
||||
|
||||
@@ -150,7 +150,7 @@ def roll_settings(weights):
|
||||
ret.dungeon_counters = 'pickup' if ret.door_shuffle != 'vanilla' or ret.compassshuffle == 'on' else 'off'
|
||||
|
||||
ret.shufflelinks = get_choice('shufflelinks') == 'on'
|
||||
ret.fakeboots = get_choice('fakeboots') == 'on'
|
||||
ret.pseudoboots = get_choice('pseudoboots') == 'on'
|
||||
ret.shopsanity = get_choice('shopsanity') == 'on'
|
||||
ret.keydropshuffle = get_choice('keydropshuffle') == 'on'
|
||||
ret.mixed_travel = get_choice('mixed_travel') if 'mixed_travel' in weights else 'prevent'
|
||||
|
||||
728
OWEdges.py
728
OWEdges.py
@@ -437,6 +437,16 @@ OWEdgeGroups = {
|
||||
['Octoballoon NE']
|
||||
]
|
||||
),
|
||||
# (Op, LW, Vt, Ld, NP, 1): (
|
||||
# [
|
||||
# ['Master Sword Meadow SC'],
|
||||
# ['Zoras Domain SW']
|
||||
# ],
|
||||
# [
|
||||
# ['Lost Woods NW'],
|
||||
# ['Zora Waterfall NE']
|
||||
# ]
|
||||
# ),
|
||||
(Op, LW, Hz, Ld, PL, 2): (
|
||||
[
|
||||
['Kakariko Fortune EN', 'Kakariko Fortune ES'],
|
||||
@@ -493,6 +503,14 @@ OWEdgeGroups = {
|
||||
['Statues WC']
|
||||
]
|
||||
),
|
||||
# (Op, LW, Hz, Wr, NP, 1): (
|
||||
# [
|
||||
# ['Hobo EC']
|
||||
# ],
|
||||
# [
|
||||
# ['Stone Bridge WC']
|
||||
# ]
|
||||
# ),
|
||||
(Op, LW, Vt, Wr, PL, 1): (
|
||||
[
|
||||
['Tree Line SC'],
|
||||
@@ -669,477 +687,613 @@ OWEdgeGroups = {
|
||||
)
|
||||
}
|
||||
|
||||
OWTileRegions = {
|
||||
0x00: [
|
||||
'Lost Woods West Area',
|
||||
'Lost Woods East Area'
|
||||
],
|
||||
0x02: [
|
||||
'Lumberjack Area'
|
||||
],
|
||||
0x03: [
|
||||
'West Death Mountain (Top)',
|
||||
'Spectacle Rock Ledge',
|
||||
'West Death Mountain (Bottom)'
|
||||
],
|
||||
0x05: [
|
||||
'Death Mountain Floating Island',
|
||||
'East Death Mountain (Top West)',
|
||||
'East Death Mountain (Top East)',
|
||||
'Spiral Cave Ledge',
|
||||
'Mimic Cave Ledge',
|
||||
'Fairy Ascension Ledge',
|
||||
'Fairy Ascension Plateau',
|
||||
'East Death Mountain (Bottom Left)',
|
||||
'East Death Mountain (Bottom)'
|
||||
],
|
||||
0x07: [
|
||||
'Death Mountain TR Pegs',
|
||||
'Death Mountain TR Pegs Ledge'
|
||||
],
|
||||
0x0a: [
|
||||
'Mountain Entry Area',
|
||||
'Mountain Entry Entrance',
|
||||
'Mountain Entry Ledge'
|
||||
],
|
||||
0x0f: [
|
||||
'Zora Waterfall Area',
|
||||
'Zora Waterfall Water',
|
||||
'Waterfall of Wishing Cave'
|
||||
],
|
||||
0x10: [
|
||||
'Lost Woods Pass West Area',
|
||||
'Lost Woods Pass East Top Area',
|
||||
'Lost Woods Pass East Bottom Area'
|
||||
],
|
||||
0x11: [
|
||||
'Kakariko Fortune Area'
|
||||
],
|
||||
0x12: [
|
||||
'Kakariko Pond Area'
|
||||
],
|
||||
0x13: [
|
||||
'Sanctuary Area',
|
||||
'Bonk Rock Ledge'
|
||||
],
|
||||
0x14: [
|
||||
'Graveyard Area',
|
||||
'Graveyard Ledge',
|
||||
'Kings Grave Area'
|
||||
],
|
||||
0x15: [
|
||||
'River Bend Area',
|
||||
'River Bend East Bank',
|
||||
'River Bend Water'
|
||||
],
|
||||
0x16: [
|
||||
'Potion Shop Area',
|
||||
'Potion Shop Northeast',
|
||||
'Potion Shop Water'
|
||||
],
|
||||
0x17: [
|
||||
'Zora Approach Area',
|
||||
'Zora Approach Ledge',
|
||||
'Zora Approach Water'
|
||||
],
|
||||
0x18: [
|
||||
'Kakariko Area',
|
||||
'Kakariko Southwest',
|
||||
'Kakariko Grass Yard'
|
||||
],
|
||||
0x1a: [
|
||||
'Forgotten Forest Area'
|
||||
],
|
||||
0x1b: [
|
||||
'Hyrule Castle Area',
|
||||
'Hyrule Castle Southwest',
|
||||
'Hyrule Castle Courtyard',
|
||||
'Hyrule Castle Courtyard Northeast',
|
||||
'Hyrule Castle Ledge',
|
||||
'Hyrule Castle East Entry'
|
||||
],
|
||||
0x1d: [
|
||||
'Wooden Bridge Area',
|
||||
'Wooden Bridge Northeast',
|
||||
'Wooden Bridge Water'
|
||||
],
|
||||
0x1e: [
|
||||
'Eastern Palace Area'
|
||||
],
|
||||
0x22: [
|
||||
'Blacksmith Area',
|
||||
'Bat Cave Ledge'
|
||||
],
|
||||
0x25: [
|
||||
'Sand Dunes Area'
|
||||
],
|
||||
0x28: [
|
||||
'Maze Race Area',
|
||||
'Maze Race Ledge',
|
||||
'Maze Race Prize'
|
||||
],
|
||||
0x29: [
|
||||
'Kakariko Suburb Area'
|
||||
],
|
||||
0x2a: [
|
||||
'Flute Boy Area',
|
||||
'Flute Boy Pass'
|
||||
],
|
||||
0x2b: [
|
||||
'Central Bonk Rocks Area'
|
||||
],
|
||||
0x2c: [
|
||||
'Links House Area'
|
||||
],
|
||||
0x2d: [
|
||||
'Stone Bridge Area',
|
||||
'Stone Bridge Water'
|
||||
],
|
||||
0x2e: [
|
||||
'Tree Line Area',
|
||||
'Tree Line Water'
|
||||
],
|
||||
0x2f: [
|
||||
'Eastern Nook Area'
|
||||
],
|
||||
0x30: [
|
||||
'Desert Area',
|
||||
'Desert Ledge',
|
||||
'Desert Palace Entrance (North) Spot',
|
||||
'Desert Checkerboard Ledge',
|
||||
'Desert Palace Stairs',
|
||||
'Desert Palace Mouth',
|
||||
'Desert Palace Teleporter Ledge',
|
||||
'Bombos Tablet Ledge'
|
||||
],
|
||||
0x32: [
|
||||
'Flute Boy Approach Area',
|
||||
'Flute Boy Bush Entry',
|
||||
'Cave 45 Ledge'
|
||||
],
|
||||
0x33: [
|
||||
'C Whirlpool Area',
|
||||
'C Whirlpool Water',
|
||||
'C Whirlpool Outer Area'
|
||||
],
|
||||
0x34: [
|
||||
'Statues Area',
|
||||
'Statues Water'
|
||||
],
|
||||
0x35: [
|
||||
'Lake Hylia Area',
|
||||
'Lake Hylia South Shore',
|
||||
'Lake Hylia Northeast Bank',
|
||||
'Lake Hylia Central Island',
|
||||
'Lake Hylia Island',
|
||||
'Lake Hylia Water'
|
||||
],
|
||||
0x37: [
|
||||
'Ice Cave Area'
|
||||
],
|
||||
0x3a: [
|
||||
'Desert Pass Area',
|
||||
'Desert Pass Southeast',
|
||||
'Desert Pass Ledge'
|
||||
],
|
||||
0x3b: [
|
||||
'Dam Area'
|
||||
],
|
||||
0x3c: [
|
||||
'South Pass Area'
|
||||
],
|
||||
0x3f: [
|
||||
'Octoballoon Area',
|
||||
'Octoballoon Water',
|
||||
'Octoballoon Water Ledge'
|
||||
],
|
||||
0x40: [
|
||||
'Skull Woods Forest',
|
||||
'Skull Woods Portal Entry',
|
||||
'Skull Woods Forest (West)',
|
||||
'Skull Woods Forgotten Path (Southwest)',
|
||||
'Skull Woods Forgotten Path (Northeast)'
|
||||
],
|
||||
0x42: [
|
||||
'Dark Lumberjack Area'
|
||||
],
|
||||
0x43: [
|
||||
'West Dark Death Mountain (Top)',
|
||||
'GT Approach',
|
||||
'West Dark Death Mountain (Bottom)'
|
||||
],
|
||||
0x45: [
|
||||
'East Dark Death Mountain (Top)',
|
||||
'East Dark Death Mountain (Bottom Left)',
|
||||
'East Dark Death Mountain (Bottom)'
|
||||
],
|
||||
0x47: [
|
||||
'Turtle Rock Area',
|
||||
'Turtle Rock Ledge'
|
||||
],
|
||||
0x4a: [
|
||||
'Bumper Cave Area',
|
||||
'Bumper Cave Entrance',
|
||||
'Bumper Cave Ledge'
|
||||
],
|
||||
0x4f: [
|
||||
'Catfish Area'
|
||||
],
|
||||
0x50: [
|
||||
'Skull Woods Pass West Area',
|
||||
'Skull Woods Pass East Top Area',
|
||||
'Skull Woods Pass East Bottom Area'
|
||||
],
|
||||
0x51: [
|
||||
'Dark Fortune Area'
|
||||
],
|
||||
0x52: [
|
||||
'Outcast Pond Area'
|
||||
],
|
||||
0x53: [
|
||||
'Dark Chapel Area'
|
||||
],
|
||||
0x54: [
|
||||
'Dark Graveyard Area'
|
||||
],
|
||||
0x55: [
|
||||
'Qirn Jump Area',
|
||||
'Qirn Jump East Bank',
|
||||
'Qirn Jump Water'
|
||||
],
|
||||
0x56: [
|
||||
'Dark Witch Area',
|
||||
'Dark Witch Northeast',
|
||||
'Dark Witch Water'
|
||||
],
|
||||
0x57: [
|
||||
'Catfish Approach Area',
|
||||
'Catfish Approach Ledge',
|
||||
'Catfish Approach Water'
|
||||
],
|
||||
0x58: [
|
||||
'Village of Outcasts Area',
|
||||
'Dark Grassy Lawn'
|
||||
],
|
||||
0x5a: [
|
||||
'Shield Shop Area',
|
||||
'Shield Shop Fence'
|
||||
],
|
||||
0x5b: [
|
||||
'Pyramid Area',
|
||||
'Pyramid Exit Ledge',
|
||||
'Pyramid Pass'
|
||||
],
|
||||
0x5d: [
|
||||
'Broken Bridge Area',
|
||||
'Broken Bridge Northeast',
|
||||
'Broken Bridge West',
|
||||
'Broken Bridge Water'
|
||||
],
|
||||
0x5e: [
|
||||
'Palace of Darkness Area'
|
||||
],
|
||||
0x62: [
|
||||
'Hammer Pegs Area',
|
||||
'Hammer Pegs Entry'
|
||||
],
|
||||
0x65: [
|
||||
'Dark Dunes Area'
|
||||
],
|
||||
0x68: [
|
||||
'Dig Game Area',
|
||||
'Dig Game Ledge'
|
||||
],
|
||||
0x69: [
|
||||
'Frog Area',
|
||||
'Frog Prison',
|
||||
'Archery Game Area'
|
||||
],
|
||||
0x6a: [
|
||||
'Stumpy Area',
|
||||
'Stumpy Pass'
|
||||
],
|
||||
0x6b: [
|
||||
'Dark Bonk Rocks Area'
|
||||
],
|
||||
0x6c: [
|
||||
'Big Bomb Shop Area'
|
||||
],
|
||||
0x6d: [
|
||||
'Hammer Bridge North Area',
|
||||
'Hammer Bridge South Area',
|
||||
'Hammer Bridge Water'
|
||||
],
|
||||
0x6e: [
|
||||
'Dark Tree Line Area',
|
||||
'Dark Tree Line Water'
|
||||
],
|
||||
0x6f: [
|
||||
'Palace of Darkness Nook Area'
|
||||
],
|
||||
0x70: [
|
||||
'Misery Mire Area',
|
||||
'Misery Mire Teleporter Ledge'
|
||||
],
|
||||
0x72: [
|
||||
'Stumpy Approach Area',
|
||||
'Stumpy Approach Bush Entry'
|
||||
],
|
||||
0x73: [
|
||||
'Dark C Whirlpool Area',
|
||||
'Dark C Whirlpool Water',
|
||||
'Dark C Whirlpool Outer Area'
|
||||
],
|
||||
0x74: [
|
||||
'Hype Cave Area',
|
||||
'Hype Cave Water'
|
||||
],
|
||||
0x75: [
|
||||
'Ice Lake Area',
|
||||
'Ice Lake Northeast Bank',
|
||||
'Ice Lake Ledge (West)',
|
||||
'Ice Lake Ledge (East)',
|
||||
'Ice Lake Water',
|
||||
'Ice Lake Moat',
|
||||
'Ice Palace Area'
|
||||
],
|
||||
0x77: [
|
||||
'Shopping Mall Area'
|
||||
],
|
||||
0x7a: [
|
||||
'Swamp Nook Area'
|
||||
],
|
||||
0x7b: [
|
||||
'Swamp Area'
|
||||
],
|
||||
0x7c: [
|
||||
'Dark South Pass Area'
|
||||
],
|
||||
0x7f: [
|
||||
'Bomber Corner Area',
|
||||
'Bomber Corner Water',
|
||||
'Bomber Corner Water Ledge'
|
||||
],
|
||||
0x80: [
|
||||
'Master Sword Meadow',
|
||||
'Hobo Bridge'
|
||||
],
|
||||
0x81: [
|
||||
'Zoras Domain'
|
||||
]
|
||||
}
|
||||
|
||||
OWTileGroups = {
|
||||
("Woods", "Regular"): (
|
||||
[
|
||||
0x00, 0x2d, 0x40, 0x6d, 0x80
|
||||
0x00, 0x2d, 0x80
|
||||
],
|
||||
[
|
||||
'Master Sword Meadow',
|
||||
'Lost Woods West Area',
|
||||
'Lost Woods East Area',
|
||||
'Stone Bridge Area',
|
||||
'Stone Bridge Water',
|
||||
'Hobo Bridge'
|
||||
],
|
||||
[
|
||||
'Skull Woods Forest',
|
||||
'Skull Woods Portal Entry',
|
||||
'Skull Woods Forest (West)',
|
||||
'Skull Woods Forgotten Path (Southwest)',
|
||||
'Skull Woods Forgotten Path (Northeast)',
|
||||
'Hammer Bridge North Area',
|
||||
'Hammer Bridge South Area',
|
||||
'Hammer Bridge Water'
|
||||
0x40, 0x6d
|
||||
]
|
||||
),
|
||||
("Lumberjack", "Regular"): (
|
||||
[
|
||||
0x02, 0x42
|
||||
0x02
|
||||
],
|
||||
[
|
||||
'Lumberjack Area'
|
||||
],
|
||||
[
|
||||
'Dark Lumberjack Area'
|
||||
0x42
|
||||
]
|
||||
),
|
||||
("West Mountain", "Regular"): (
|
||||
[
|
||||
0x03, 0x43
|
||||
0x03
|
||||
],
|
||||
[
|
||||
'West Death Mountain (Top)',
|
||||
'Spectacle Rock Ledge',
|
||||
'West Death Mountain (Bottom)'
|
||||
],
|
||||
[
|
||||
'West Dark Death Mountain (Top)',
|
||||
'GT Approach',
|
||||
'West Dark Death Mountain (Bottom)'
|
||||
0x43
|
||||
]
|
||||
),
|
||||
("East Mountain", "Regular"): (
|
||||
[
|
||||
0x05, 0x45
|
||||
0x05
|
||||
],
|
||||
[
|
||||
'Death Mountain Floating Island',
|
||||
'East Death Mountain (Top West)',
|
||||
'East Death Mountain (Top East)',
|
||||
'Spiral Cave Ledge',
|
||||
'Mimic Cave Ledge',
|
||||
'Fairy Ascension Ledge',
|
||||
'Fairy Ascension Plateau',
|
||||
'East Death Mountain (Bottom Left)',
|
||||
'East Death Mountain (Bottom)'
|
||||
],
|
||||
[
|
||||
'East Dark Death Mountain (Top)',
|
||||
'East Dark Death Mountain (Bottom Left)',
|
||||
'East Dark Death Mountain (Bottom)'
|
||||
0x45
|
||||
]
|
||||
),
|
||||
("East Mountain", "Entrance"): (
|
||||
[
|
||||
0x07, 0x47
|
||||
0x07,
|
||||
],
|
||||
[
|
||||
'Death Mountain TR Pegs',
|
||||
'Death Mountain TR Pegs Ledge'
|
||||
],
|
||||
[
|
||||
'Turtle Rock Area',
|
||||
'Turtle Rock Ledge'
|
||||
0x47
|
||||
]
|
||||
),
|
||||
("Lake", "Regular"): (
|
||||
[
|
||||
0x0f, 0x35, 0x4f, 0x75, 0x81
|
||||
0x0f, 0x35, 0x81
|
||||
],
|
||||
[
|
||||
'Zora Waterfall Area',
|
||||
'Zora Waterfall Water',
|
||||
'Waterfall of Wishing Cave',
|
||||
'Zoras Domain',
|
||||
'Lake Hylia Area',
|
||||
'Lake Hylia South Shore',
|
||||
'Lake Hylia Northeast Bank',
|
||||
'Lake Hylia Central Island',
|
||||
'Lake Hylia Island',
|
||||
'Lake Hylia Water'
|
||||
],
|
||||
[
|
||||
'Catfish Area',
|
||||
'Ice Lake Area',
|
||||
'Ice Lake Northeast Bank',
|
||||
'Ice Lake Ledge (West)',
|
||||
'Ice Lake Ledge (East)',
|
||||
'Ice Lake Water',
|
||||
'Ice Lake Moat',
|
||||
'Ice Palace Area'
|
||||
0x4f, 0x75
|
||||
]
|
||||
),
|
||||
("West Mountain", "Entrance"): (
|
||||
("Mountain Entry", "Regular"): (
|
||||
[
|
||||
0x0a, 0x4a
|
||||
0x0a
|
||||
],
|
||||
[
|
||||
'Mountain Entry Area',
|
||||
'Mountain Entry Entrance',
|
||||
'Mountain Entry Ledge'
|
||||
],
|
||||
[
|
||||
'Bumper Cave Area',
|
||||
'Bumper Cave Entrance',
|
||||
'Bumper Cave Ledge'
|
||||
0x4a
|
||||
]
|
||||
),
|
||||
("Woods Pass", "Regular"): (
|
||||
[
|
||||
0x10, 0x50
|
||||
0x10
|
||||
],
|
||||
[
|
||||
'Lost Woods Pass West Area',
|
||||
'Lost Woods Pass East Top Area',
|
||||
'Lost Woods Pass East Bottom Area'
|
||||
],
|
||||
[
|
||||
'Skull Woods Pass West Area',
|
||||
'Skull Woods Pass East Top Area',
|
||||
'Skull Woods Pass East Bottom Area'
|
||||
0x50
|
||||
]
|
||||
),
|
||||
("Fortune", "Regular"): (
|
||||
[
|
||||
0x11, 0x51
|
||||
0x11
|
||||
],
|
||||
[
|
||||
'Kakariko Fortune Area'
|
||||
],
|
||||
[
|
||||
'Dark Fortune Area'
|
||||
0x51
|
||||
]
|
||||
),
|
||||
("Whirlpools", "Regular"): (
|
||||
[
|
||||
0x12, 0x15, 0x33, 0x3f, 0x52, 0x55, 0x73, 0x7f
|
||||
0x12, 0x15, 0x33, 0x3f
|
||||
],
|
||||
[
|
||||
'Kakariko Pond Area',
|
||||
'River Bend Area',
|
||||
'River Bend East Bank',
|
||||
'River Bend Water',
|
||||
'C Whirlpool Area',
|
||||
'C Whirlpool Water',
|
||||
'C Whirlpool Outer Area',
|
||||
'Octoballoon Area',
|
||||
'Octoballoon Water',
|
||||
'Octoballoon Water Ledge'
|
||||
],
|
||||
[
|
||||
'Outcast Pond Area',
|
||||
'Qirn Jump Area',
|
||||
'Qirn Jump East Bank',
|
||||
'Qirn Jump Water',
|
||||
'Dark C Whirlpool Area',
|
||||
'Dark C Whirlpool Water',
|
||||
'Dark C Whirlpool Outer Area',
|
||||
'Bomber Corner Area',
|
||||
'Bomber Corner Water',
|
||||
'Bomber Corner Water Ledge'
|
||||
0x52, 0x55, 0x73, 0x7f
|
||||
]
|
||||
),
|
||||
("Castle", "Entrance"): (
|
||||
[
|
||||
0x13, 0x14, 0x53, 0x54
|
||||
0x13, 0x14
|
||||
],
|
||||
[
|
||||
'Sanctuary Area',
|
||||
'Bonk Rock Ledge',
|
||||
'Graveyard Area',
|
||||
'Graveyard Ledge',
|
||||
'Kings Grave Area'
|
||||
],
|
||||
[
|
||||
'Dark Chapel Area',
|
||||
'Dark Graveyard Area'
|
||||
0x53, 0x54
|
||||
]
|
||||
),
|
||||
("Castle", "Regular"): (
|
||||
[
|
||||
0x1a, 0x1b, 0x5a, 0x5b
|
||||
0x1a, 0x1b
|
||||
],
|
||||
[
|
||||
'Forgotten Forest Area',
|
||||
'Hyrule Castle Area',
|
||||
'Hyrule Castle Southwest',
|
||||
'Hyrule Castle Courtyard',
|
||||
'Hyrule Castle Courtyard Northeast',
|
||||
'Hyrule Castle Ledge',
|
||||
'Hyrule Castle East Entry'
|
||||
],
|
||||
[
|
||||
'Shield Shop Area',
|
||||
'Shield Shop Fence',
|
||||
'Pyramid Area',
|
||||
'Pyramid Exit Ledge',
|
||||
'Pyramid Pass'
|
||||
0x5a, 0x5b
|
||||
]
|
||||
),
|
||||
("Witch", "Regular"): (
|
||||
[
|
||||
0x16, 0x56
|
||||
0x16
|
||||
],
|
||||
[
|
||||
'Potion Shop Area',
|
||||
'Potion Shop Northeast',
|
||||
'Potion Shop Water'
|
||||
],
|
||||
[
|
||||
'Dark Witch Area',
|
||||
'Dark Witch Northeast',
|
||||
'Dark Witch Water'
|
||||
0x56
|
||||
]
|
||||
),
|
||||
("Water Approach", "Regular"): (
|
||||
[
|
||||
0x17, 0x57
|
||||
0x17
|
||||
],
|
||||
[
|
||||
'Zora Approach Area',
|
||||
'Zora Approach Ledge',
|
||||
'Zora Approach Water'
|
||||
],
|
||||
[
|
||||
'Catfish Approach Area',
|
||||
'Catfish Approach Ledge',
|
||||
'Catfish Approach Water'
|
||||
0x57
|
||||
]
|
||||
),
|
||||
("Village", "Regular"): (
|
||||
[
|
||||
0x18, 0x58
|
||||
0x18
|
||||
],
|
||||
[
|
||||
'Kakariko Area',
|
||||
'Kakariko Southwest',
|
||||
'Kakariko Grass Yard'
|
||||
],
|
||||
[
|
||||
'Village of Outcasts Area',
|
||||
'Dark Grassy Lawn'
|
||||
0x58
|
||||
]
|
||||
),
|
||||
("Wooden Bridge", "Regular"): (
|
||||
[
|
||||
0x1d, 0x5d
|
||||
0x1d
|
||||
],
|
||||
[
|
||||
'Wooden Bridge Area',
|
||||
'Wooden Bridge Northeast',
|
||||
'Wooden Bridge Water'
|
||||
],
|
||||
[
|
||||
'Broken Bridge Area',
|
||||
'Broken Bridge Northeast',
|
||||
'Broken Bridge West',
|
||||
'Broken Bridge Water'
|
||||
0x5d
|
||||
]
|
||||
),
|
||||
("Eastern", "Regular"): (
|
||||
[
|
||||
0x1e, 0x5e
|
||||
0x1e
|
||||
],
|
||||
[
|
||||
'Eastern Palace Area'
|
||||
],
|
||||
[
|
||||
'Palace of Darkness Area'
|
||||
0x5e
|
||||
]
|
||||
),
|
||||
("Blacksmith", "Regular"): (
|
||||
[
|
||||
0x22, 0x62
|
||||
0x22
|
||||
],
|
||||
[
|
||||
'Blacksmith Area',
|
||||
'Bat Cave Ledge'
|
||||
],
|
||||
[
|
||||
'Hammer Pegs Area',
|
||||
'Hammer Pegs Entry'
|
||||
0x62
|
||||
]
|
||||
),
|
||||
("Dunes", "Regular"): (
|
||||
[
|
||||
0x25, 0x65
|
||||
0x25
|
||||
],
|
||||
[
|
||||
'Sand Dunes Area'
|
||||
],
|
||||
[
|
||||
'Dark Dunes Area'
|
||||
0x65
|
||||
]
|
||||
),
|
||||
("Game", "Regular"): (
|
||||
[
|
||||
0x28, 0x29, 0x68, 0x69
|
||||
0x28, 0x29
|
||||
],
|
||||
[
|
||||
'Maze Race Area',
|
||||
'Maze Race Ledge',
|
||||
'Maze Race Prize',
|
||||
'Kakariko Suburb Area'
|
||||
],
|
||||
[
|
||||
'Dig Game Area',
|
||||
'Dig Game Ledge',
|
||||
'Frog Area',
|
||||
'Frog Prison',
|
||||
'Archery Game Area'
|
||||
0x68, 0x69
|
||||
]
|
||||
),
|
||||
("Grove", "Regular"): (
|
||||
[
|
||||
0x2a, 0x6a
|
||||
0x2a
|
||||
],
|
||||
[
|
||||
'Flute Boy Area',
|
||||
'Flute Boy Pass'
|
||||
],
|
||||
[
|
||||
'Stumpy Area',
|
||||
'Stumpy Pass'
|
||||
0x6a
|
||||
]
|
||||
),
|
||||
("Central Bonk Rocks", "Regular"): (
|
||||
[
|
||||
0x2b, 0x6b
|
||||
0x2b
|
||||
],
|
||||
[
|
||||
'Central Bonk Rocks Area'
|
||||
],
|
||||
[
|
||||
'Dark Bonk Rocks Area'
|
||||
0x6b
|
||||
]
|
||||
),
|
||||
# ("Links", "Regular"): (
|
||||
# [
|
||||
# 0x2c, 0x6c
|
||||
# 0x2c
|
||||
# ],
|
||||
# [
|
||||
# 'Links House Area'
|
||||
# ],
|
||||
# [
|
||||
# 'Big Bomb Shop Area'
|
||||
# 0x6c
|
||||
# ]
|
||||
# ),
|
||||
("Tree Line", "Regular"): (
|
||||
[
|
||||
0x2e, 0x6e
|
||||
0x2e
|
||||
],
|
||||
[
|
||||
'Tree Line Area',
|
||||
'Tree Line Water'
|
||||
],
|
||||
[
|
||||
'Dark Tree Line Area',
|
||||
'Dark Tree Line Water'
|
||||
0x6e
|
||||
]
|
||||
),
|
||||
("Nook", "Regular"): (
|
||||
[
|
||||
0x2f, 0x6f
|
||||
0x2f
|
||||
],
|
||||
[
|
||||
'Eastern Nook Area'
|
||||
],
|
||||
[
|
||||
'Palace of Darkness Nook Area'
|
||||
0x6f
|
||||
]
|
||||
),
|
||||
("Desert", "Regular"): (
|
||||
[
|
||||
0x30, 0x3a, 0x70, 0x7a
|
||||
0x30, 0x3a
|
||||
],
|
||||
[
|
||||
'Desert Area',
|
||||
'Desert Ledge',
|
||||
'Desert Palace Entrance (North) Spot',
|
||||
'Desert Checkerboard Ledge',
|
||||
'Desert Palace Stairs',
|
||||
'Desert Palace Mouth',
|
||||
'Desert Palace Teleporter Ledge',
|
||||
'Bombos Tablet Ledge',
|
||||
'Desert Pass Area',
|
||||
'Desert Pass Southeast',
|
||||
'Desert Pass Ledge'
|
||||
],
|
||||
[
|
||||
'Misery Mire Area',
|
||||
'Misery Mire Teleporter Ledge',
|
||||
'Swamp Nook Area'
|
||||
0x70, 0x7a
|
||||
]
|
||||
),
|
||||
("Grove Approach", "Regular"): (
|
||||
[
|
||||
0x32, 0x72
|
||||
0x32
|
||||
],
|
||||
[
|
||||
'Flute Boy Approach Area',
|
||||
'Flute Boy Bush Entry',
|
||||
'Cave 45 Ledge'
|
||||
],
|
||||
[
|
||||
'Stumpy Approach Area',
|
||||
'Stumpy Approach Bush Entry'
|
||||
0x72
|
||||
]
|
||||
),
|
||||
("Hype", "Regular"): (
|
||||
[
|
||||
0x34, 0x74
|
||||
0x34
|
||||
],
|
||||
[
|
||||
'Statues Area',
|
||||
'Statues Water'
|
||||
],
|
||||
[
|
||||
'Hype Cave Area',
|
||||
'Hype Cave Water'
|
||||
0x74
|
||||
]
|
||||
),
|
||||
("Shopping Mall", "Regular"): (
|
||||
[
|
||||
0x37, 0x77
|
||||
0x37
|
||||
],
|
||||
[
|
||||
'Ice Cave Area'
|
||||
],
|
||||
[
|
||||
'Shopping Mall Area'
|
||||
0x77
|
||||
]
|
||||
),
|
||||
("Swamp", "Regular"): (
|
||||
[
|
||||
0x3b, 0x7b
|
||||
0x3b
|
||||
],
|
||||
[
|
||||
'Dam Area'
|
||||
],
|
||||
[
|
||||
'Swamp Area'
|
||||
0x7b
|
||||
]
|
||||
),
|
||||
("South Pass", "Regular"): (
|
||||
[
|
||||
0x3c, 0x7c
|
||||
0x3c
|
||||
],
|
||||
[
|
||||
'South Pass Area'
|
||||
],
|
||||
[
|
||||
'Dark South Pass Area'
|
||||
0x7c
|
||||
]
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import random, logging, copy
|
||||
from BaseClasses import OWEdge, WorldType, RegionType, Direction, Terrain, PolSlot
|
||||
from OWEdges import OWTileGroups, OWEdgeGroups, OpenStd, parallel_links, IsParallel
|
||||
from OWEdges import OWTileRegions, OWTileGroups, OWEdgeGroups, OpenStd, parallel_links, IsParallel
|
||||
try:
|
||||
from sortedcontainers import SortedList
|
||||
except ImportError:
|
||||
raise Exception('Could not load sortedcontainers module')
|
||||
|
||||
__version__ = '0.1.6.6-u'
|
||||
__version__ = '0.1.6.7-u'
|
||||
|
||||
def link_overworld(world, player):
|
||||
# setup mandatory connections
|
||||
@@ -28,18 +28,24 @@ def link_overworld(world, player):
|
||||
|
||||
for (name, groupType) in OWTileGroups.keys():
|
||||
if world.mode[player] != 'standard' or name not in ['Castle', 'Links', 'Central Bonk Rocks']:
|
||||
(owids, lw_regions, dw_regions) = OWTileGroups[(name, groupType,)]
|
||||
(lw_owids, dw_owids) = OWTileGroups[(name, groupType,)]
|
||||
if world.shuffle[player] in ['vanilla', 'simple', 'dungeonssimple']:
|
||||
(exist_owids, exist_lw_regions, exist_dw_regions) = tile_groups[(name,)]
|
||||
exist_owids.extend(owids)
|
||||
exist_lw_regions.extend(lw_regions)
|
||||
exist_dw_regions.extend(dw_regions)
|
||||
exist_owids.extend(lw_owids)
|
||||
exist_owids.extend(dw_owids)
|
||||
for owid in lw_owids:
|
||||
exist_lw_regions.extend(OWTileRegions[owid])
|
||||
for owid in dw_owids:
|
||||
exist_dw_regions.extend(OWTileRegions[owid])
|
||||
tile_groups[(name,)] = (exist_owids, exist_lw_regions, exist_dw_regions)
|
||||
else:
|
||||
(exist_owids, exist_lw_regions, exist_dw_regions) = tile_groups[(name, groupType)]
|
||||
exist_owids.extend(owids)
|
||||
exist_lw_regions.extend(lw_regions)
|
||||
exist_dw_regions.extend(dw_regions)
|
||||
exist_owids.extend(lw_owids)
|
||||
exist_owids.extend(dw_owids)
|
||||
for owid in lw_owids:
|
||||
exist_lw_regions.extend(OWTileRegions[owid])
|
||||
for owid in dw_owids:
|
||||
exist_dw_regions.extend(OWTileRegions[owid])
|
||||
tile_groups[(name, groupType)] = (exist_owids, exist_lw_regions, exist_dw_regions)
|
||||
|
||||
#tile shuffle happens here, the groups that remain in the list are the tiles that get swapped
|
||||
@@ -1086,12 +1092,14 @@ parallelsimilar_connections = [('Maze Race ES', 'Kakariko Suburb WS'),
|
||||
]
|
||||
|
||||
# non shuffled overworld
|
||||
default_connections = [('Lost Woods SW', 'Lost Woods Pass NW'),
|
||||
default_connections = [#('Lost Woods NW', 'Master Sword Meadow SC'),
|
||||
('Lost Woods SW', 'Lost Woods Pass NW'),
|
||||
('Lost Woods SC', 'Lost Woods Pass NE'),
|
||||
('Lost Woods SE', 'Kakariko Fortune NE'),
|
||||
('Lost Woods EN', 'Lumberjack WN'),
|
||||
('Lumberjack SW', 'Mountain Entry NW'),
|
||||
('Mountain Entry SE', 'Kakariko Pond NE'),
|
||||
#('Zora Waterfall NE', 'Zoras Domain SW'),
|
||||
('Lost Woods Pass SW', 'Kakariko NW'),
|
||||
('Lost Woods Pass SE', 'Kakariko NC'),
|
||||
('Kakariko Fortune SC', 'Kakariko NE'),
|
||||
@@ -1140,6 +1148,7 @@ default_connections = [('Lost Woods SW', 'Lost Woods Pass NW'),
|
||||
('Stone Bridge SC', 'Lake Hylia NW'),
|
||||
('Stone Bridge EN', 'Tree Line WN'),
|
||||
('Stone Bridge EC', 'Tree Line WC'),
|
||||
#('Stone Bridge WC', 'Hobo EC'),
|
||||
('Tree Line SC', 'Lake Hylia NC'),
|
||||
('Tree Line SE', 'Lake Hylia NE'),
|
||||
('Desert EC', 'Desert Pass WC'),
|
||||
|
||||
@@ -12,8 +12,22 @@ Links house can now be shuffled in different ER settings. It will be limited to
|
||||
|
||||
Thanks to qadan, cheuer, & compiling
|
||||
|
||||
## Pseudo Boots
|
||||
|
||||
Thanks to Bonta. You can now start with pseudo boots that let you move fast, but have no other logical uses (bonking open things, hovering, etc)
|
||||
|
||||
## Pendant/Crystal Indicator
|
||||
|
||||
For accessibility, you now get a C or P indicator to the left of the magic bar on the HUD when instead a Crystal or Pendant. Requires ownership of the map of that dungeon for display. Thanks to kan.
|
||||
|
||||
# Bug Fixes and Notes.
|
||||
|
||||
* 0.4.0.11
|
||||
* Some minor base rom fixes
|
||||
* Improved distribution of bombable/dashable doors
|
||||
* 0.4.0.10
|
||||
* Renamed to pseudoboots
|
||||
* Some release note updates
|
||||
* 0.4.0.9
|
||||
* Fixes for stats and P/C indicator (thanks Kara)
|
||||
* Swamp lobby fixes (thanks Catobat)
|
||||
@@ -38,7 +52,7 @@ Thanks to qadan, cheuer, & compiling
|
||||
* Chest turn tracking (not yet in credits)
|
||||
* Damaged and magic stats in credits (gt bk removed)
|
||||
* Fix for infinite bombs
|
||||
* Fake boots option
|
||||
* Pseudo boots option
|
||||
* Always allowed medallions for swordless (no option yet)
|
||||
* 0.4.0.7
|
||||
* Reduce flashing option added
|
||||
|
||||
93
Rom.py
93
Rom.py
@@ -31,7 +31,7 @@ from OverworldShuffle import default_flute_connections, flute_data
|
||||
|
||||
|
||||
JAP10HASH = '03a63945398191337e896e5771f77173'
|
||||
RANDOMIZERBASEHASH = '1dc1961e57d4e588a262fa706de6c753'
|
||||
RANDOMIZERBASEHASH = '487a04cf965bb89636f9b1621dd606d1'
|
||||
|
||||
|
||||
class JsonRom(object):
|
||||
@@ -1248,7 +1248,7 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
||||
rom.write_byte(0x18017E, 0x01) # Fairy fountains only trade in bottles
|
||||
|
||||
# Starting equipment
|
||||
if world.fakeboots[player]:
|
||||
if world.pseudoboots[player]:
|
||||
rom.write_byte(0x18008E, 0x01)
|
||||
|
||||
equip = [0] * (0x340 + 0x4F)
|
||||
@@ -2413,18 +2413,18 @@ def set_inverted_mode(world, player, rom, inverted_buffer):
|
||||
for b in range(0x00, len(inverted_buffer)):
|
||||
inverted_buffer[b] = (inverted_buffer[b] & 0xFE) | ((inverted_buffer[b] + 1) % 2)
|
||||
|
||||
rom.write_byte(snes_to_pc(0x0283E0), 0xF0) # residual portals
|
||||
rom.write_byte(snes_to_pc(0x0283E0), 0xF0) # residual portals
|
||||
rom.write_byte(snes_to_pc(0x02B34D), 0xF0)
|
||||
rom.write_byte(snes_to_pc(0x06DB78), 0x8B) # dark-style portal
|
||||
rom.write_byte(snes_to_pc(0x06DB78), 0x8B) # dark-style portal
|
||||
|
||||
rom.write_byte(snes_to_pc(0x0DB3C5), 0xC6) #vortex
|
||||
rom.write_byte(snes_to_pc(0x0DB3C5), 0xC6) # vortex
|
||||
|
||||
rom.write_byte(snes_to_pc(0x07A3F4), 0xF0) # duck
|
||||
rom.write_byte(snes_to_pc(0x08D40C), 0xD0) # morph poof
|
||||
rom.write_byte(snes_to_pc(0x0ABFBB), 0x90) # move mirror portal indicator to correct map (0xB0 normally)
|
||||
rom.write_byte(snes_to_pc(0x0280A6), 0xD0) # use starting point prompt instead of start at pyramid
|
||||
rom.write_byte(snes_to_pc(0x07A3F4), 0xF0) # duck
|
||||
rom.write_byte(snes_to_pc(0x08D40C), 0xD0) # morph poof
|
||||
rom.write_byte(snes_to_pc(0x0ABFBB), 0x90) # move mirror portal indicator to correct map (0xB0 normally)
|
||||
rom.write_byte(snes_to_pc(0x0280A6), 0xD0) # use starting point prompt instead of start at pyramid
|
||||
|
||||
write_int16(rom, snes_to_pc(0x02D8D4), 0x112) # change sanctuary spawn point to dark sanc
|
||||
write_int16(rom, snes_to_pc(0x02D8D4), 0x112) # change sanctuary spawn point to dark sanc
|
||||
rom.write_bytes(snes_to_pc(0x02D8E8), [0x22, 0x22, 0x22, 0x23, 0x04, 0x04, 0x04, 0x05])
|
||||
write_int16(rom, snes_to_pc(0x02D91A), 0x0400)
|
||||
write_int16(rom, snes_to_pc(0x02D928), 0x222E)
|
||||
@@ -2448,12 +2448,11 @@ def set_inverted_mode(world, player, rom, inverted_buffer):
|
||||
if world.doorShuffle[player] == 'vanilla' or world.intensity[player] < 3:
|
||||
write_int16(rom, 0x15AEE + 2*0x38, 0x00E0)
|
||||
write_int16(rom, 0x15AEE + 2*0x25, 0x000C)
|
||||
|
||||
if (world.mode[player] == 'inverted') != (0x03 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if world.shuffle[player] in ['vanilla', 'dungeonsfull', 'dungeonssimple']:
|
||||
rom.write_bytes(snes_to_pc(0x308350), [0x00, 0x00, 0x01]) # mountain cave starts on OW
|
||||
rom.write_bytes(snes_to_pc(0x308350), [0x00, 0x00, 0x01]) # mountain cave starts on OW
|
||||
|
||||
write_int16(rom, snes_to_pc(0x02D8DE), 0x00F1) # change mountain cave spawn point to just outside old man cave
|
||||
write_int16(rom, snes_to_pc(0x02D8DE), 0x00F1) # change mountain cave spawn point to just outside old man cave
|
||||
rom.write_bytes(snes_to_pc(0x02D910), [0x1F, 0x1E, 0x1F, 0x1F, 0x03, 0x02, 0x03, 0x03])
|
||||
write_int16(rom, snes_to_pc(0x02D924), 0x0300)
|
||||
write_int16(rom, snes_to_pc(0x02D932), 0x1F10)
|
||||
@@ -2471,49 +2470,16 @@ def set_inverted_mode(world, player, rom, inverted_buffer):
|
||||
write_int16(rom, snes_to_pc(0x02D9B0), 0x0007)
|
||||
rom.write_byte(snes_to_pc(0x02D9B8), 0x12)
|
||||
|
||||
rom.write_bytes(0x180247, [0x00, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00]) #indicates the overworld door being used for the single entrance spawn point
|
||||
|
||||
rom.write_byte(0xDBB73 + 0x6F, 0x07) # DDM fairy entrance to old man fetch east UW
|
||||
write_int16(rom, 0x15AEE + 2*0x18, 0x00F1) # old man fetch UW to DDM fairy entrance
|
||||
rom.write_byte(0x15B8C + 0x18, 0x43)
|
||||
write_int16(rom, 0x15BDB + 2 * 0x18, 0x1400)
|
||||
write_int16(rom, 0x15C79 + 2 * 0x18, 0x0294)
|
||||
write_int16(rom, 0x15D17 + 2 * 0x18, 0x0600)
|
||||
write_int16(rom, 0x15DB5 + 2 * 0x18, 0x02E8)
|
||||
write_int16(rom, 0x15E53 + 2 * 0x18, 0x0678)
|
||||
write_int16(rom, 0x15EF1 + 2 * 0x18, 0x0303)
|
||||
write_int16(rom, 0x15F8F + 2 * 0x18, 0x0685)
|
||||
rom.write_byte(0x1602D + 0x18, 0x0A)
|
||||
rom.write_byte(0x1607C + 0x18, 0xF6)
|
||||
write_int16(rom, 0x160CB + 2 * 0x18, 0x0000)
|
||||
write_int16(rom, 0x16169 + 2 * 0x18, 0x0000)
|
||||
|
||||
rom.write_byte(0xDBB73 + 0x06, 0x2E) # old man fetch east entrance to DMD west UW
|
||||
write_int16(rom, 0x15AEE + 2*0x08, 0x00E6) # DMD west UW to old man fetch east entrance
|
||||
if (world.mode[player] == 'inverted') != (0x0A in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
rom.write_byte(0xDBB73 + 0x16, 0x5E) # bumper cave top entrance to DDM Fairy UW
|
||||
else:
|
||||
rom.write_byte(0xDBB73 + 0x2D, 0x5E) # DMD west entrance to DDM Fairy
|
||||
rom.write_bytes(0x180247, [0x00, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00]) #indicates the overworld door being used for the single entrance spawn point
|
||||
if (world.mode[player] == 'inverted') != (0x05 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
rom.write_bytes(snes_to_pc(0x1BC655), [0x4A, 0x1D, 0x82]) # add warp under rock
|
||||
if (world.mode[player] == 'inverted') != (0x07 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
rom.write_bytes(snes_to_pc(0x1BC387), [0xDD, 0xD1]) # add warps under rocks
|
||||
rom.write_bytes(snes_to_pc(0x1BD1DD), [0xA4, 0x06, 0x82, 0x9E, 0x06, 0x82, 0xFF, 0xFF]) # add warps under rocks
|
||||
rom.write_bytes(snes_to_pc(0x1BD1DD), [0xA4, 0x06, 0x82, 0x9E, 0x06, 0x82, 0xFF, 0xFF]) # add warps under rocks
|
||||
rom.write_byte(0x180089, 0x01) # open TR after exit
|
||||
rom.write_bytes(0x0086E, [0x5C, 0x00, 0xA0, 0xA1]) # TR tail
|
||||
if world.shuffle[player] in ['vanilla']:
|
||||
world.fix_trock_doors[player] = True
|
||||
if (world.mode[player] == 'inverted') != (0x0A in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull']:
|
||||
rom.write_byte(0xDBB73 + 0x15, 0x06) # bumper cave bottom entrance to old man fetch west UW
|
||||
write_int16(rom, 0x15AEE + 2*0x17, 0x00F0) # old man fetch west UW to bumper cave bottom entrance
|
||||
rom.write_byte(0xDBB73 + 0x05, 0x16) # old man fetch west entrance to bumper cave bottom UW
|
||||
write_int16(rom, 0x15AEE + 2*0x07, 0x00FB) # bumper cave bottom UW to old man fetch west entrance
|
||||
rom.write_byte(0xDBB73 + 0x2D, 0x17) # DMD west entrance to bumper cave top UW
|
||||
write_int16(rom, 0x15AEE + 2*0x2F, 0x00EB) # bumper cave top UW to DMD west entrance
|
||||
if (world.mode[player] == 'inverted') == (0x03 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
rom.write_byte(0xDBB73 + 0x16, 0x2E) # bumper cave top entrance to DMD west UW
|
||||
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') != (0x1B in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
@@ -2552,7 +2518,7 @@ def set_inverted_mode(world, player, rom, inverted_buffer):
|
||||
rom.write_byte(snes_to_pc(0x00D009), 0x31) # castle hole graphics
|
||||
rom.write_byte(snes_to_pc(0x00D0E8), 0xE0)
|
||||
rom.write_byte(snes_to_pc(0x00D1C7), 0x00)
|
||||
write_int16(rom, snes_to_pc(0x1BE8DA), 0x39AD) # add color for shading for castle hole
|
||||
write_int16(rom, snes_to_pc(0x1BE8DA), 0x39AD) # add color for shading for castle hole
|
||||
|
||||
#castle hole map16 data
|
||||
write_int16s(rom, snes_to_pc(0x0FF1C8), [0x190F, 0x190F, 0x190F, 0x194C, 0x190F,
|
||||
@@ -2566,21 +2532,21 @@ def set_inverted_mode(world, player, rom, inverted_buffer):
|
||||
write_int16s(rom, snes_to_pc(0x0FA480), [0x190F, 0x196B, 0x9D04, 0x9D04, 0x196B,
|
||||
0x190F, 0x9D04, 0x9D04])
|
||||
|
||||
write_int16s(rom, snes_to_pc(0x1BB810), [0x00BE, 0x00C0, 0x013E]) # update pyramid hole entrance
|
||||
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(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(0x00DB9D), 0x1A) # make retreat bat gfx available in HC area
|
||||
rom.write_byte(snes_to_pc(0x00DC09), 0x1A)
|
||||
|
||||
rom.write_byte(snes_to_pc(0x1AF696), 0xF0) # bat sprite retreat : bat X position
|
||||
rom.write_byte(snes_to_pc(0x1AF6B2), 0x33) # bat sprite retreat : bat delay
|
||||
|
||||
write_int16(rom, snes_to_pc(0x1af504), 0x148B) # prioritize retreat Bat and use 3rd sprite group
|
||||
write_int16(rom, snes_to_pc(0x1af504), 0x148B) # prioritize retreat Bat and use 3rd sprite group
|
||||
write_int16(rom, snes_to_pc(0x1af50c), 0x149B)
|
||||
write_int16(rom, snes_to_pc(0x1af514), 0x14A4)
|
||||
write_int16(rom, snes_to_pc(0x1af51c), 0x1489)
|
||||
@@ -2604,28 +2570,11 @@ def set_inverted_mode(world, player, rom, inverted_buffer):
|
||||
|
||||
write_int16(rom, 0xDB96F + 2 * 0x35, 0x001B) # move pyramid exit door
|
||||
write_int16(rom, 0xDBA71 + 2 * 0x35, 0x011C)
|
||||
if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull']:
|
||||
rom.write_byte(0xDBB73 + 0x35, 0x36)
|
||||
|
||||
if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull']:
|
||||
write_int16(rom, 0x15AEE + 2 * 0x37, 0x0010) # pyramid exit to new hc area
|
||||
rom.write_byte(0x15B8C + 0x37, 0x1B)
|
||||
write_int16(rom, 0x15BDB + 2 * 0x37, 0x000E)
|
||||
write_int16(rom, 0x15C79 + 2 * 0x37, 0x0600)
|
||||
write_int16(rom, 0x15D17 + 2 * 0x37, 0x0676)
|
||||
write_int16(rom, 0x15DB5 + 2 * 0x37, 0x0604)
|
||||
write_int16(rom, 0x15E53 + 2 * 0x37, 0x06E8)
|
||||
write_int16(rom, 0x15EF1 + 2 * 0x37, 0x066D)
|
||||
write_int16(rom, 0x15F8F + 2 * 0x37, 0x06F3)
|
||||
rom.write_byte(0x1602D + 0x37, 0x00)
|
||||
rom.write_byte(0x1607C + 0x37, 0x0A)
|
||||
write_int16(rom, 0x160CB + 2 * 0x37, 0x0000)
|
||||
write_int16(rom, 0x16169 + 2 * 0x37, 0x811c)
|
||||
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
|
||||
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'):
|
||||
if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull']:
|
||||
rom.write_byte(0x15B8C, 0x6C) #exit links at bomb shop area
|
||||
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'):
|
||||
|
||||
12
Rules.py
12
Rules.py
@@ -837,6 +837,13 @@ def default_rules(world, player):
|
||||
|
||||
|
||||
def ow_rules(world, player):
|
||||
if world.mode[player] != 'inverted':
|
||||
set_rule(world.get_entrance('Agahnims Tower', player), lambda state: state.has('Cape', player) or state.has_beam_sword(player) or state.has('Beat Agahnim 1', player)) # barrier gets removed after killing agahnim, relevant for entrance shuffle
|
||||
set_rule(world.get_entrance('GT Entry Approach', player), lambda state: state.has_crystals(world.crystals_needed_for_gt[player], player))
|
||||
set_rule(world.get_entrance('GT Entry Leave', player), lambda state: state.has_crystals(world.crystals_needed_for_gt[player], player) or state.world.shuffle[player] in ('restricted', 'full', 'crossed', 'insanity'))
|
||||
else:
|
||||
set_rule(world.get_entrance('Agahnims Tower', player), lambda state: state.has_crystals(world.crystals_needed_for_gt[player], player))
|
||||
|
||||
if (world.mode[player] == 'inverted') == (0x00 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
set_rule(world.get_entrance('Lost Woods East Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Lost Woods Entry Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
@@ -858,9 +865,6 @@ def ow_rules(world, player):
|
||||
set_rule(world.get_entrance('Dark Lumberjack Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
|
||||
if (world.mode[player] == 'inverted') == (0x03 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
set_rule(world.get_entrance('GT Entry Approach', player), lambda state: state.has_crystals(world.crystals_needed_for_gt[player], player))
|
||||
set_rule(world.get_entrance('GT Entry Leave', player), lambda state: state.has_crystals(world.crystals_needed_for_gt[player], player) or state.world.shuffle[player] in ('restricted', 'full', 'crossed', 'insanity'))
|
||||
|
||||
set_rule(world.get_entrance('West Death Mountain (Top) Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Spectacle Rock Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
else:
|
||||
@@ -991,7 +995,6 @@ def ow_rules(world, player):
|
||||
set_rule(world.get_entrance('Inverted Pyramid Hole', player), lambda state: False)
|
||||
set_rule(world.get_entrance('Inverted Pyramid Entrance', player), lambda state: False)
|
||||
set_rule(world.get_entrance('Pyramid Hole', player), lambda state: state.has('Beat Agahnim 2', player) or world.open_pyramid[player])
|
||||
set_rule(world.get_entrance('Agahnims Tower', player), lambda state: state.has('Cape', player) or state.has_beam_sword(player) or state.has('Beat Agahnim 1', player)) # barrier gets removed after killing agahnim, relevant for entrance shuffle
|
||||
|
||||
set_rule(world.get_entrance('HC Area Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('HC Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
@@ -1004,7 +1007,6 @@ def ow_rules(world, player):
|
||||
set_rule(world.get_entrance('Inverted Pyramid Hole', player), lambda state: state.has('Beat Agahnim 2', player) or world.open_pyramid[player])
|
||||
add_rule(world.get_entrance('Pyramid Hole', player), lambda state: False)
|
||||
set_rule(world.get_entrance('Pyramid Entrance', player), lambda state: False)
|
||||
set_rule(world.get_entrance('Agahnims Tower', player), lambda state: state.has_crystals(world.crystals_needed_for_gt[player], player))
|
||||
|
||||
set_rule(world.get_entrance('Pyramid Exit Ledge Drop', player), lambda state: state.has('Hammer', player))
|
||||
set_rule(world.get_entrance('Pyramid Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
|
||||
@@ -580,8 +580,8 @@ dw $00bc, $00a2, $00a3, $00c2, $001a, $0049, $0014, $008c
|
||||
; Ice Many Pots, Swamp Waterfall, GT Gauntlet 3, Eastern Push Block, Eastern Courtyard, Eastern Map Valley
|
||||
; Eastern Cannonball, HC East Hall
|
||||
dw $009f, $0066, $005d, $00a8, $00a9, $00aa, $00b9, $0052
|
||||
; HC West Hall, TR Dash Bridge, TR Hub, Pod Arena, GT Petting Zoo
|
||||
dw $0050, $00c5, $00c6, $0009, $0003, $002a, $007d
|
||||
; HC West Hall, TR Dash Bridge, TR Hub, Pod Arena, GT Petting Zoo, Ice Spike Cross
|
||||
dw $0050, $00c5, $00c6, $0009, $0003, $002a, $007d, $005e
|
||||
dw $ffff
|
||||
|
||||
; dungeon tables
|
||||
|
||||
@@ -353,7 +353,7 @@ OWNewDestination:
|
||||
; turn into bunny
|
||||
lda $5d : cmp #$17 : beq .return
|
||||
lda #$17 : sta $5d
|
||||
lda #$01 : sta $2e0
|
||||
lda #$01 : sta $02e0
|
||||
bra .return
|
||||
.nobunny
|
||||
lda $5d : cmp #$17 : bne .return
|
||||
|
||||
Binary file not shown.
@@ -354,7 +354,7 @@
|
||||
"action": "store_true",
|
||||
"type": "bool"
|
||||
},
|
||||
"fakeboots": {
|
||||
"pseudoboots": {
|
||||
"action": "store_true",
|
||||
"type": "bool"
|
||||
},
|
||||
|
||||
@@ -290,7 +290,7 @@
|
||||
"Keys are universal, shooting arrows costs rupees,",
|
||||
"and a few other little things make this more like Zelda-1. (default: %(default)s)"
|
||||
],
|
||||
"fakeboots": [ " Players starts with fake boots that allow dashing but no item checks (default: %(default)s"],
|
||||
"pseudoboots": [ " Players starts with pseudo boots that allow dashing but no item checks (default: %(default)s"],
|
||||
"startinventory": [ "Specifies a list of items that will be in your starting inventory (separated by commas). (default: %(default)s)" ],
|
||||
"usestartinventory": [ "Toggle usage of Starting Inventory." ],
|
||||
"custom": [ "Not supported." ],
|
||||
|
||||
@@ -206,7 +206,7 @@
|
||||
|
||||
"randomizer.item.hints": "Include Helpful Hints",
|
||||
"randomizer.item.retro": "Retro mode (universal keys)",
|
||||
"randomizer.item.fakeboots": "Start with Fake Boots",
|
||||
"randomizer.item.pseudoboots": "Start with Pseudo Boots",
|
||||
|
||||
"randomizer.item.worldstate": "World State",
|
||||
"randomizer.item.worldstate.standard": "Standard",
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"hints": {
|
||||
"type": "checkbox"
|
||||
},
|
||||
"fakeboots": { "type": "checkbox" }
|
||||
"pseudoboots": { "type": "checkbox" }
|
||||
},
|
||||
"leftItemFrame": {
|
||||
"worldstate": {
|
||||
|
||||
@@ -58,7 +58,7 @@ SETTINGSTOPROCESS = {
|
||||
"hints": "hints",
|
||||
"retro": "retro",
|
||||
"shopsanity": "shopsanity",
|
||||
"fakeboots": "fakeboots",
|
||||
"pseudoboots": "pseudoboots",
|
||||
"worldstate": "mode",
|
||||
"logiclevel": "logic",
|
||||
"goal": "goal",
|
||||
|
||||
Reference in New Issue
Block a user