Merge branch 'OverworldShuffleDev' into OverworldShuffle
This commit is contained in:
+28
-13
@@ -1658,14 +1658,15 @@ class Entrance(object):
|
||||
'Missing Smith': ('Frog', True, False, True, True),
|
||||
'Middle Aged Man': ('Dark Blacksmith Ruins', True, False, True, True),
|
||||
'Old Man Drop Off': ('Lost Old Man', True, False, False, False),
|
||||
#'Revealing Light': ('Suspicious Maiden', False, False, False, False) }
|
||||
'Revealing Light': ('Suspicious Maiden', False, False, False, False)
|
||||
}
|
||||
|
||||
if self.name in multi_step_locations:
|
||||
if self not in state.path:
|
||||
world = self.parent_region.world
|
||||
step_location = world.get_location(multi_step_locations[self.name][0], self.player)
|
||||
if step_location.can_reach(state) and self.can_reach_thru(state, step_location, multi_step_locations[self.name][1], multi_step_locations[self.name][2], multi_step_locations[self.name][3], multi_step_locations[self.name][4]) and self.access_rule(state):
|
||||
multi_step_loc = multi_step_locations[self.name]
|
||||
step_location = world.get_location(multi_step_loc[0], self.player)
|
||||
if step_location.can_reach(state) and self.can_reach_thru(state, step_location, multi_step_loc[1], multi_step_loc[2], multi_step_loc[3], multi_step_loc[4]) and self.access_rule(state):
|
||||
if not self in state.path:
|
||||
path = state.path.get(step_location.parent_region, (step_location.parent_region.name, None))
|
||||
item_name = step_location.item.name if step_location.item else 'Pick Up Item'
|
||||
@@ -1729,7 +1730,8 @@ class Entrance(object):
|
||||
# this is checked first as this often the shortest path
|
||||
follower_region = start_region
|
||||
if follower_region.type not in [RegionType.LightWorld, RegionType.DarkWorld]:
|
||||
follower_region = [i for i in start_region.entrances if i.parent_region.name != 'Menu'][0].parent_region
|
||||
ent_list = [e for e in start_region.entrances if e.parent_region.type != RegionType.Menu]
|
||||
follower_region = ent_list[0].parent_region
|
||||
if (follower_region.world.mode[self.player] != 'inverted') == (follower_region.type == RegionType.LightWorld):
|
||||
from OverworldShuffle import get_mirror_edges
|
||||
mirror_map = get_mirror_edges(follower_region.world, follower_region, self.player)
|
||||
@@ -1747,7 +1749,8 @@ class Entrance(object):
|
||||
path = (follower_region.name, (mirror_exit, path))
|
||||
item_name = step_location.item.name if step_location.item else 'Pick Up Item'
|
||||
if start_region.name != follower_region.name:
|
||||
path = (start_region.name, (start_region.entrances[0].name, path))
|
||||
ent_list = [e for e in start_region.entrances if e.parent_region.type != RegionType.Menu]
|
||||
path = (start_region.name, (ent_list[0].name, path))
|
||||
path = (f'{step_location.parent_region.name} Exit', ('Leave Item Area', (item_name, path)))
|
||||
else:
|
||||
path = (item_name, path)
|
||||
@@ -1758,25 +1761,36 @@ class Entrance(object):
|
||||
path = (self.parent_region.name, path)
|
||||
state.path[self] = (self.name, path)
|
||||
|
||||
if not found:
|
||||
# check normal paths
|
||||
traverse_paths(start_region.entrances[0].parent_region, self.parent_region)
|
||||
for ent in start_region.entrances:
|
||||
if not found:
|
||||
# check normal paths
|
||||
if ent.parent_region.type != RegionType.Menu and (ent.parent_region.type == start_region.type or \
|
||||
ent.parent_region.type in [RegionType.LightWorld, RegionType.DarkWorld] or not ignore_underworld):
|
||||
traverse_paths(ent.parent_region, self.parent_region)
|
||||
|
||||
if not found and allow_save_quit:
|
||||
# check paths involving save and quit
|
||||
exit = self.parent_region.world.get_entrance('Links House S&Q', self.player)
|
||||
traverse_paths(exit.connected_region, self.parent_region, [exit])
|
||||
if not found:
|
||||
world = self.parent_region.world
|
||||
exit = world.get_entrance('Sanctuary S&Q', self.player)
|
||||
# only allow save and quit at Sanc if the lobby is guaranteed vanilla
|
||||
if exit.connected_region != 'Sanctuary' or world.mode[self.player] == 'standard' \
|
||||
or world.doorShuffle[self.player] == 'vanilla' or world.intensity[self.player] < 3:
|
||||
traverse_paths(exit.connected_region, self.parent_region, [exit])
|
||||
|
||||
if not found and allow_mirror_reentry and state.has_Mirror(self.player):
|
||||
# check for paths using mirror portal re-entry at location of final destination
|
||||
# this is checked last as this is the most complicated/exhaustive check
|
||||
follower_region = start_region
|
||||
if follower_region.type not in [RegionType.LightWorld, RegionType.DarkWorld]:
|
||||
follower_region = start_region.entrances[0].parent_region
|
||||
ent_list = [e for e in start_region.entrances if e.parent_region.type != RegionType.Menu]
|
||||
follower_region = ent_list[0].parent_region
|
||||
if (follower_region.world.mode[self.player] != 'inverted') == (follower_region.type == RegionType.LightWorld):
|
||||
dest_region = self.parent_region
|
||||
if dest_region.type not in [RegionType.LightWorld, RegionType.DarkWorld]:
|
||||
dest_region = start_region.entrances[0].parent_region
|
||||
dest_region = dest_region.entrances[0].parent_region
|
||||
if (dest_region.world.mode[self.player] != 'inverted') != (dest_region.type == RegionType.LightWorld):
|
||||
# loop thru potential places to leave a mirror portal
|
||||
from OverworldShuffle import get_mirror_edges
|
||||
@@ -1829,7 +1843,8 @@ class Entrance(object):
|
||||
self.target = target
|
||||
self.addresses = addresses
|
||||
self.vanilla = vanilla
|
||||
region.entrances.append(self)
|
||||
if self not in region.entrances:
|
||||
region.entrances.append(self)
|
||||
|
||||
def __str__(self):
|
||||
return str(self.__unicode__())
|
||||
@@ -3119,9 +3134,9 @@ class Spoiler(object):
|
||||
self.bosses[str(player)] = OrderedDict()
|
||||
self.bosses[str(player)]["Eastern Palace"] = self.world.get_dungeon("Eastern Palace", player).boss.name
|
||||
self.bosses[str(player)]["Desert Palace"] = self.world.get_dungeon("Desert Palace", player).boss.name
|
||||
self.bosses[str(player)]["Tower Of Hera"] = self.world.get_dungeon("Tower of Hera", player).boss.name
|
||||
self.bosses[str(player)]["Tower of Hera"] = self.world.get_dungeon("Tower of Hera", player).boss.name
|
||||
self.bosses[str(player)]["Hyrule Castle"] = "Agahnim"
|
||||
self.bosses[str(player)]["Palace Of Darkness"] = self.world.get_dungeon("Palace of Darkness", player).boss.name
|
||||
self.bosses[str(player)]["Palace of Darkness"] = self.world.get_dungeon("Palace of Darkness", player).boss.name
|
||||
self.bosses[str(player)]["Swamp Palace"] = self.world.get_dungeon("Swamp Palace", player).boss.name
|
||||
self.bosses[str(player)]["Skull Woods"] = self.world.get_dungeon("Skull Woods", player).boss.name
|
||||
self.bosses[str(player)]["Thieves Town"] = self.world.get_dungeon("Thieves Town", player).boss.name
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
# Changelog
|
||||
|
||||
## 0.5.0.6
|
||||
- New improved Pseudoboots behavior
|
||||
- Fixed issue with missing Blue Potion in Dark Lake Shop in Inverted
|
||||
- Various generation and logic fixes for HMG/NL
|
||||
- Fixed error with prize plando
|
||||
- Fixed error with District ER
|
||||
- Added TT Maiden pathing to spoiler log
|
||||
- Corrected and improved some pathing logic
|
||||
|
||||
## 0.5.0.5
|
||||
- Fixed issue with vanilla HCBK acting like a small key
|
||||
|
||||
|
||||
@@ -3792,6 +3792,7 @@ logical_connections = [
|
||||
('Thieves Conveyor Block Path', 'Thieves Conveyor Bridge'),
|
||||
("Thieves Blind's Cell Door", "Thieves Blind's Cell Interior"),
|
||||
("Thieves Blind's Cell Exit", "Thieves Blind's Cell"),
|
||||
('Revealing Light', 'Revealing Light'),
|
||||
('Thieves Town Boss', 'Thieves Boss Spoils'),
|
||||
|
||||
('Ice Cross Bottom Push Block Left', 'Ice Floor Switch'),
|
||||
|
||||
@@ -727,6 +727,7 @@ def create_doors(world, player):
|
||||
create_door(player, 'Thieves Big Chest Room ES', Intr).dir(Ea, 0x44, Bot, High).small_key().pos(1),
|
||||
create_door(player, 'Thieves Conveyor Block WN', Intr).dir(We, 0x44, Top, High).pos(0),
|
||||
create_door(player, 'Thieves Trap EN', Intr).dir(Ea, 0x44, Left, Top).pos(0),
|
||||
create_door(player, 'Revealing Light', Lgcl),
|
||||
create_door(player, 'Thieves Town Boss', Lgcl),
|
||||
|
||||
create_door(player, 'Ice Lobby SE', Nrml).dir(So, 0x0e, Right, High).pos(2).portal(X, 0x00),
|
||||
|
||||
+2
-1
@@ -139,7 +139,8 @@ thieves_regions = [
|
||||
'Thieves Attic', 'Thieves Attic Hint', 'Thieves Attic Switch', 'Thieves Cricket Hall Left',
|
||||
'Thieves Cricket Hall Right', 'Thieves Attic Window', 'Thieves Basement Block', 'Thieves Blocked Entry',
|
||||
'Thieves Lonely Zazak', "Thieves Blind's Cell", "Thieves Blind's Cell Interior", 'Thieves Conveyor Bridge',
|
||||
'Thieves Conveyor Block', 'Thieves Big Chest Room', 'Thieves Trap', 'Thieves Boss Spoils', 'Thieves Town Portal'
|
||||
'Thieves Conveyor Block', 'Thieves Big Chest Room', 'Thieves Trap', 'Revealing Light',
|
||||
'Thieves Boss Spoils', 'Thieves Town Portal'
|
||||
]
|
||||
|
||||
ice_regions = [
|
||||
|
||||
+8
-8
@@ -520,8 +520,8 @@ def set_up_take_anys(world, player, skip_adjustments=False):
|
||||
world.regions.append(old_man_take_any)
|
||||
world.dynamic_regions.append(old_man_take_any)
|
||||
|
||||
reg = regions.pop()
|
||||
entrance = world.get_region(reg, player).entrances[0]
|
||||
reg = world.get_region(regions.pop(), player)
|
||||
entrance = next((e for e in reg.entrances if e.parent_region.type in [RegionType.LightWorld, RegionType.DarkWorld]))
|
||||
connect_entrance(world, entrance, old_man_take_any, player)
|
||||
entrance.target = 0x58
|
||||
old_man_take_any.shop = Shop(old_man_take_any, 0x0112, ShopType.TakeAny, 0xE2, True, not world.shopsanity[player], 32)
|
||||
@@ -1669,16 +1669,16 @@ def get_item_and_event_flag(item, world, player, dungeon_pool, prize_set, prize_
|
||||
item_player = player if len(item_parts) < 2 else int(item_parts[1])
|
||||
item_name = item_parts[0]
|
||||
event_flag = False
|
||||
if is_dungeon_item(item_name, world, item_player):
|
||||
item_to_place = next(x for x in dungeon_pool
|
||||
if x.name == item_name and x.player == item_player)
|
||||
dungeon_pool.remove(item_to_place)
|
||||
event_flag = True
|
||||
elif item_name in prize_set:
|
||||
if item_name in prize_set:
|
||||
item_player = player # prizes must be for that player
|
||||
item_to_place = ItemFactory(item_name, item_player)
|
||||
prize_pool.remove(item_name)
|
||||
event_flag = True
|
||||
elif is_dungeon_item(item_name, world, item_player):
|
||||
item_to_place = next(x for x in dungeon_pool
|
||||
if x.name == item_name and x.player == item_player)
|
||||
dungeon_pool.remove(item_to_place)
|
||||
event_flag = True
|
||||
else:
|
||||
matcher = lambda x: x.name == item_name and x.player == item_player
|
||||
if item_name == 'Bottle':
|
||||
|
||||
@@ -28,7 +28,7 @@ from Fill import distribute_items_restrictive, promote_dungeon_items, fill_dunge
|
||||
from Fill import dungeon_tracking
|
||||
from Fill import sell_potions, sell_keys, balance_multiworld_progression, balance_money_progression, lock_shop_locations, set_prize_drops
|
||||
from ItemList import generate_itempool, difficulties, fill_prizes, customize_shops, fill_specific_items, create_farm_locations
|
||||
from UnderworldGlitchRules import create_hybridmajor_connections, create_hybridmajor_connectors
|
||||
from UnderworldGlitchRules import create_hybridmajor_connections, get_hybridmajor_connection_entrances
|
||||
from Utils import output_path, parse_player_names
|
||||
|
||||
from source.item.District import init_districts
|
||||
@@ -176,8 +176,6 @@ def main(args, seed=None, fish=None):
|
||||
world.data_tables[player] = init_data_tables(world, player)
|
||||
place_bosses(world, player)
|
||||
randomize_enemies(world, player)
|
||||
if world.logic[player] in ('nologic', 'hybridglitches'):
|
||||
create_hybridmajor_connections(world, player)
|
||||
adjust_locations(world, player)
|
||||
|
||||
if any(world.potshuffle.values()):
|
||||
@@ -204,8 +202,6 @@ def main(args, seed=None, fish=None):
|
||||
|
||||
for player in range(1, world.players + 1):
|
||||
link_entrances_new(world, player)
|
||||
if world.logic[player] in ('nologic', 'hybridglitches'):
|
||||
create_hybridmajor_connectors(world, player)
|
||||
|
||||
logger.info(world.fish.translate("cli", "cli", "shuffling.prep"))
|
||||
|
||||
@@ -227,6 +223,8 @@ def main(args, seed=None, fish=None):
|
||||
create_farm_locations(world, player)
|
||||
|
||||
for player in range(1, world.players + 1):
|
||||
if world.logic[player] in ('nologic', 'hybridglitches'):
|
||||
create_hybridmajor_connections(world, player)
|
||||
generate_itempool(world, player)
|
||||
|
||||
verify_item_pool_config(world)
|
||||
@@ -372,6 +370,10 @@ def main(args, seed=None, fish=None):
|
||||
if 'debug' in world.spoiler.settings:
|
||||
world.spoiler.extras(output_path(f'{outfilebase}_Spoiler.txt'))
|
||||
|
||||
player_logics = set(world.logic.values())
|
||||
if len(player_logics) == 1 and 'nologic' in player_logics:
|
||||
args.skip_playthrough = True
|
||||
|
||||
if not args.skip_playthrough:
|
||||
logger.info(world.fish.translate("cli","cli","calc.playthrough"))
|
||||
create_playthrough(world)
|
||||
@@ -624,8 +626,6 @@ def copy_world(world):
|
||||
create_owg_connections(ret, player)
|
||||
create_dynamic_exits(ret, player)
|
||||
create_dungeon_regions(ret, player)
|
||||
if world.logic[player] in ('nologic', 'hybridglitches'):
|
||||
create_hybridmajor_connections(ret, player)
|
||||
create_owedges(ret, player)
|
||||
create_shops(ret, player)
|
||||
#create_doors(ret, player)
|
||||
@@ -656,6 +656,11 @@ def copy_world(world):
|
||||
|
||||
# connect copied world
|
||||
copied_locations = {(loc.name, loc.player): loc for loc in ret.get_locations()} # caches all locations
|
||||
|
||||
# We have to skip these for now. They require both the rest of the entrances _and_ the dungeon portals to be copied first
|
||||
# We will connect them later
|
||||
hmg_entrances = get_hybridmajor_connection_entrances()
|
||||
|
||||
for region in world.regions:
|
||||
copied_region = ret.get_region(region.name, region.player)
|
||||
copied_region.is_light_world = region.is_light_world
|
||||
@@ -665,6 +670,8 @@ def copy_world(world):
|
||||
for location in copied_region.locations:
|
||||
location.parent_region = copied_region
|
||||
for entrance in region.entrances:
|
||||
if entrance.name in hmg_entrances:
|
||||
continue
|
||||
ret.get_entrance(entrance.name, entrance.player).connect(copied_region)
|
||||
for exit in region.exits:
|
||||
if exit.connected_region:
|
||||
@@ -732,7 +739,16 @@ def copy_world(world):
|
||||
categorize_world_regions(ret, player)
|
||||
create_farm_locations(ret, player)
|
||||
if world.logic[player] in ('nologic', 'hybridglitches'):
|
||||
create_hybridmajor_connectors(ret, player)
|
||||
create_hybridmajor_connections(ret, player)
|
||||
|
||||
for region in world.regions:
|
||||
copied_region = ret.get_region(region.name, region.player)
|
||||
for entrance in region.entrances:
|
||||
if entrance.name not in hmg_entrances:
|
||||
continue
|
||||
ret.get_entrance(entrance.name, entrance.player).connect(copied_region)
|
||||
|
||||
for player in range(1, world.players + 1):
|
||||
set_rules(ret, player)
|
||||
|
||||
return ret
|
||||
@@ -823,8 +839,6 @@ def copy_world_premature(world, player):
|
||||
create_owg_connections(ret, player)
|
||||
create_dynamic_exits(ret, player)
|
||||
create_dungeon_regions(ret, player)
|
||||
if world.logic[player] in ('nologic', 'hybridglitches'):
|
||||
create_hybridmajor_connections(ret, player)
|
||||
create_owedges(ret, player)
|
||||
create_shops(ret, player)
|
||||
create_doors(ret, player)
|
||||
@@ -849,7 +863,9 @@ def copy_world_premature(world, player):
|
||||
for location in copied_region.locations:
|
||||
location.parent_region = copied_region
|
||||
for entrance in region.entrances:
|
||||
copied_region.entrances.append(ret.get_entrance(entrance.name, entrance.player))
|
||||
ent = ret.get_entrance(entrance.name, entrance.player)
|
||||
if ent not in copied_region.entrances:
|
||||
copied_region.entrances.append(ent)
|
||||
for exit in region.exits:
|
||||
if exit.connected_region:
|
||||
dest_region = ret.get_region(exit.connected_region.name, region.player)
|
||||
@@ -884,7 +900,7 @@ def copy_world_premature(world, player):
|
||||
connect_portal(portal, ret, player)
|
||||
|
||||
if world.logic[player] in ('nologic', 'hybridglitches'):
|
||||
create_hybridmajor_connectors(ret, player)
|
||||
create_hybridmajor_connections(ret, player)
|
||||
|
||||
set_rules(ret, player)
|
||||
|
||||
|
||||
+11
-3
@@ -2,7 +2,7 @@
|
||||
Helper functions to deliver entrance/exit/region sets to OWG rules.
|
||||
"""
|
||||
|
||||
from BaseClasses import Entrance
|
||||
from BaseClasses import Entrance, Region
|
||||
from OWEdges import OWTileRegions
|
||||
|
||||
# Cave regions that superbunny can get through - but only with a sword.
|
||||
@@ -327,10 +327,18 @@ def add_additional_rule(entrance, rule):
|
||||
entrance.access_rule = lambda state: old_rule(state) and rule(state)
|
||||
|
||||
|
||||
def create_no_logic_connections(player, world, connections):
|
||||
def create_no_logic_connections(player, world, connections, connect_external=False):
|
||||
for entrance, parent_region, target_region, *_ in connections:
|
||||
parent = world.get_region(parent_region, player)
|
||||
target = world.get_region(target_region, player)
|
||||
|
||||
if isinstance(target_region, Region):
|
||||
target_region = target_region.name
|
||||
|
||||
if connect_external and target_region.endswith(" Portal"):
|
||||
target = world.get_portal(target_region[:-7], player).find_portal_entrance().parent_region
|
||||
else:
|
||||
target = world.get_region(target_region, player)
|
||||
|
||||
connection = Entrance(player, entrance, parent)
|
||||
connection.spot_type = 'OWG'
|
||||
parent.exits.append(connection)
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ from OWEdges import OWTileRegions, OWEdgeGroups, OWEdgeGroupsTerrain, OWExitType
|
||||
from OverworldGlitchRules import create_owg_connections
|
||||
from Utils import bidict
|
||||
|
||||
version_number = '0.5.0.5'
|
||||
version_number = '0.5.0.6'
|
||||
# branch indicator is intentionally different across branches
|
||||
version_branch = ''
|
||||
|
||||
|
||||
+3
-2
@@ -718,7 +718,8 @@ def create_dungeon_regions(world, player):
|
||||
create_dungeon_region(player, 'Thieves Compass Room', 'Thieves\' Town', ['Thieves\' Town - Compass Chest'], ['Thieves Compass Room NW Edge', 'Thieves Compass Room N Edge', 'Thieves Compass Room WS Edge', 'Thieves Compass Room W']),
|
||||
create_dungeon_region(player, 'Thieves Big Chest Nook', 'Thieves\' Town', ['Thieves\' Town - Big Key Chest'], ['Thieves Big Chest Nook ES Edge']),
|
||||
create_dungeon_region(player, 'Thieves Hallway', 'Thieves\' Town', ['Thieves\' Town - Hallway Pot Key'], ['Thieves Hallway SE', 'Thieves Hallway NE', 'Thieves Hallway WN', 'Thieves Hallway WS']),
|
||||
create_dungeon_region(player, 'Thieves Boss', 'Thieves\' Town', ['Revealing Light'], ['Thieves Boss SE', 'Thieves Town Boss']),
|
||||
create_dungeon_region(player, 'Thieves Boss', 'Thieves\' Town', None, ['Thieves Boss SE', 'Revealing Light']),
|
||||
create_dungeon_region(player, 'Revealing Light', 'Thieves\' Town', ['Revealing Light'], ['Thieves Town Boss']),
|
||||
create_dungeon_region(player, 'Thieves Boss Spoils', 'Thieves\' Town', ['Thieves\' Town - Boss', 'Thieves\' Town - Prize', 'Thieves\' Town - Boss Kill']),
|
||||
create_dungeon_region(player, 'Thieves Pot Alcove Mid', 'Thieves\' Town', None, ['Thieves Pot Alcove Mid ES', 'Thieves Pot Alcove Mid WS']),
|
||||
create_dungeon_region(player, 'Thieves Pot Alcove Bottom', 'Thieves\' Town', None, ['Thieves Pot Alcove Bottom SW']),
|
||||
@@ -1161,7 +1162,7 @@ def create_shops(world, player):
|
||||
world.shops[player] = []
|
||||
for region_name, (room_id, type, shopkeeper, custom, locked, inventory, sram) in shop_table.items():
|
||||
if world.mode[player] == 'inverted':
|
||||
if (not world.is_tile_swapped(0x35, player) and region_name == 'Dark Lake Hylia Shop') \
|
||||
if (world.is_tile_swapped(0x35, player) and region_name == 'Dark Lake Hylia Shop') \
|
||||
or (not world.is_tile_swapped(0x35, player) and region_name == 'Lake Hylia Shop'):
|
||||
locked = True
|
||||
inventory = [('Blue Potion', 160), ('Blue Shield', 50), ('Bombs (10)', 50)]
|
||||
|
||||
@@ -43,7 +43,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings
|
||||
|
||||
|
||||
JAP10HASH = '03a63945398191337e896e5771f77173'
|
||||
RANDOMIZERBASEHASH = '2d658871687c966f35dd9597a4195256'
|
||||
RANDOMIZERBASEHASH = 'a51679f0e31ee29f59247545d705992a'
|
||||
|
||||
|
||||
class JsonRom(object):
|
||||
|
||||
@@ -98,7 +98,8 @@ def set_rules(world, player):
|
||||
|
||||
# These rules go here because they overwrite/add to some of the above rules
|
||||
if world.logic[player] == 'hybridglitches':
|
||||
underworld_glitches_rules(world, player)
|
||||
if not world.is_copied_world:
|
||||
underworld_glitches_rules(world, player)
|
||||
|
||||
def mirrorless_path_to_location(world, startName, targetName, player):
|
||||
# If Agahnim is defeated then the courtyard needs to be accessible without using the mirror for the mirror offset glitch.
|
||||
|
||||
+130
-117
@@ -1,17 +1,19 @@
|
||||
from BaseClasses import Entrance
|
||||
import functools
|
||||
from BaseClasses import Entrance, DoorType
|
||||
from DoorShuffle import connect_simple_door
|
||||
import Rules
|
||||
from OverworldGlitchRules import create_no_logic_connections
|
||||
from Doors import create_door
|
||||
|
||||
kikiskip_spots = [
|
||||
("Kiki Skip", "Spectacle Rock Cave (Bottom)", "Palace of Darkness Portal")
|
||||
]
|
||||
|
||||
mireheraswamp_spots = [
|
||||
("Mire to Hera Clip", "Mire Torches Top", "Hera Portal"),
|
||||
("Hera to Swamp Clip", "Mire Torches Top", "Swamp Portal"),
|
||||
]
|
||||
mirehera_spots = [("Mire to Hera Clip", "Mire Torches Top", "Hera Portal")]
|
||||
|
||||
icepalace_spots = [("Ice Lobby Clip", "Ice Portal", "Ice Bomb Drop")]
|
||||
heraswamp_spots = [("Hera to Swamp Clip", "Mire Torches Top", "Swamp Portal")]
|
||||
|
||||
icepalace_spots = [("Ice Lobby Clip", "Ice Portal", "Ice Bomb Drop - Top")]
|
||||
|
||||
thievesdesert_spots = [
|
||||
("Thieves to Desert West Clip", "Thieves Attic", "Desert West Portal"),
|
||||
@@ -27,74 +29,46 @@ paradox_spots = [
|
||||
("Paradox Front Teleport", "Paradox Cave Front", "Paradox Cave Chest Area")
|
||||
]
|
||||
|
||||
|
||||
# We need to make connectors at a separate time from the connections, because of how dungeons are linked to regions
|
||||
kikiskip_connectors = [
|
||||
("Kiki Skip Connector", "Spectacle Rock Cave (Bottom)", "Palace of Darkness Exit")
|
||||
]
|
||||
|
||||
|
||||
mireheraswamp_connectors = [
|
||||
("Mire to Hera Connector", "Mire Torches Top", "Tower of Hera Exit"),
|
||||
("Mire to Swamp Connector", "Mire Torches Top", "Swamp Palace Exit"),
|
||||
]
|
||||
|
||||
|
||||
thievesdesert_connectors = [
|
||||
("Thieves to Desert West Connector", "Thieves Attic", "Desert Palace Exit (West)"),
|
||||
(
|
||||
"Thieves to Desert South Connector",
|
||||
"Thieves Attic",
|
||||
"Desert Palace Exit (South)",
|
||||
),
|
||||
("Thieves to Desert East Connector", "Thieves Attic", "Desert Palace Exit (East)"),
|
||||
]
|
||||
|
||||
specrock_connectors = [
|
||||
(
|
||||
"Spec Rock Top Connector",
|
||||
"Spectacle Rock Cave (Peak)",
|
||||
"Spectacle Rock Cave Exit (Top)",
|
||||
),
|
||||
(
|
||||
"Spec Rock Exit Connector",
|
||||
"Spectacle Rock Cave (Peak)",
|
||||
"Spectacle Rock Cave Exit",
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
# Create connections between dungeons/locations
|
||||
def create_hybridmajor_connections(world, player):
|
||||
fix_fake_worlds = world.fix_fake_world[player]
|
||||
|
||||
for spots in [
|
||||
kikiskip_spots,
|
||||
mireheraswamp_spots,
|
||||
mirehera_spots,
|
||||
heraswamp_spots,
|
||||
icepalace_spots,
|
||||
thievesdesert_spots,
|
||||
specrock_spots,
|
||||
paradox_spots,
|
||||
]:
|
||||
create_no_logic_connections(player, world, spots)
|
||||
create_no_logic_connections(player, world, spots, connect_external=fix_fake_worlds)
|
||||
|
||||
# Add the new Ice path (back of bomb drop to front) to the world and model it properly
|
||||
clip_door = create_door(player, "Ice Bomb Drop Clip", DoorType.Logical)
|
||||
world.doors += [clip_door]
|
||||
world.initialize_doors([clip_door])
|
||||
|
||||
# Turn dungeons into connectors
|
||||
def create_hybridmajor_connectors(world, player):
|
||||
for connectors in [
|
||||
kikiskip_connectors,
|
||||
mireheraswamp_connectors,
|
||||
thievesdesert_connectors,
|
||||
specrock_connectors,
|
||||
]:
|
||||
new_connectors = [
|
||||
(
|
||||
connector[0],
|
||||
connector[1],
|
||||
world.get_entrance(connector[2], player).connected_region,
|
||||
)
|
||||
for connector in connectors
|
||||
]
|
||||
new_connectors = [c for c in new_connectors if c[2] is not None]
|
||||
create_no_logic_connections(player, world, new_connectors)
|
||||
ice_bomb_top_reg = world.get_region("Ice Bomb Drop - Top", player)
|
||||
ice_bomb_top_reg.exits.append(
|
||||
Entrance(player, "Ice Bomb Drop Clip", ice_bomb_top_reg)
|
||||
)
|
||||
connect_simple_door(world, "Ice Bomb Drop Clip", "Ice Bomb Drop", player)
|
||||
|
||||
def get_hybridmajor_connection_entrances():
|
||||
connections = []
|
||||
for connector in (
|
||||
kikiskip_spots
|
||||
+ mirehera_spots
|
||||
+ heraswamp_spots
|
||||
+ icepalace_spots
|
||||
+ thievesdesert_spots
|
||||
+ specrock_spots
|
||||
+ paradox_spots
|
||||
):
|
||||
connections.append(connector[0])
|
||||
connections.append('Ice Bomb Drop Clip')
|
||||
return set(connections)
|
||||
|
||||
|
||||
# For some entrances, we need to fake having pearl, because we're in fake DW/LW.
|
||||
@@ -110,19 +84,40 @@ def fake_pearl_state(state, player):
|
||||
# Sets the rules on where we can actually go using this clip.
|
||||
# Behavior differs based on what type of ER shuffle we're playing.
|
||||
def dungeon_reentry_rules(
|
||||
world, player, clip: Entrance, dungeon_region: str, dungeon_exit: str
|
||||
world,
|
||||
player,
|
||||
clip: Entrance,
|
||||
dungeon_region: str,
|
||||
):
|
||||
fix_dungeon_exits = world.fix_palaceofdarkness_exit[player]
|
||||
fix_fake_worlds = world.fix_fake_world[player]
|
||||
|
||||
all_clips = [
|
||||
x[0]
|
||||
for x in kikiskip_spots
|
||||
+ mirehera_spots
|
||||
+ heraswamp_spots
|
||||
+ icepalace_spots
|
||||
+ thievesdesert_spots
|
||||
+ specrock_spots
|
||||
+ paradox_spots
|
||||
]
|
||||
|
||||
dungeon_entrance = [
|
||||
r
|
||||
for r in world.get_region(dungeon_region, player).entrances
|
||||
if r.name != clip.name
|
||||
if r.name not in all_clips
|
||||
][0]
|
||||
if (
|
||||
not fix_dungeon_exits
|
||||
): # vanilla, simple, restricted, dungeonssimple; should never have fake worlds fix
|
||||
|
||||
dungeon_exit = [
|
||||
r
|
||||
for r in world.get_region(dungeon_region, player).exits
|
||||
if r.name not in all_clips
|
||||
][0]
|
||||
|
||||
|
||||
if not fix_dungeon_exits:
|
||||
# vanilla, simple, restricted, dungeonssimple; should never have fake worlds fix
|
||||
# Dungeons are only shuffled among themselves. We need to check SW, MM, and AT because they can't be reentered trivially.
|
||||
|
||||
# entrance doesn't exist until you fire rod it from the other side
|
||||
@@ -173,32 +168,66 @@ def dungeon_reentry_rules(
|
||||
|
||||
|
||||
def underworld_glitches_rules(world, player):
|
||||
# Ice Palace Entrance Clip, needs bombs or cane of somaria to exit bomb drop room
|
||||
Rules.add_rule(
|
||||
world.get_entrance("Ice Bomb Drop SE", player),
|
||||
lambda state: state.can_dash_clip(world.get_region("Ice Lobby", player), player)
|
||||
and (state.can_use_bombs(player) or state.has("Cane of Somaria", player)),
|
||||
combine="or",
|
||||
)
|
||||
|
||||
# Kiki Skip
|
||||
kks = world.get_entrance("Kiki Skip", player)
|
||||
Rules.set_rule(kks, lambda state: state.can_bomb_clip(kks.parent_region, player))
|
||||
dungeon_reentry_rules(
|
||||
world, player, kks, "Palace of Darkness Portal", "Palace of Darkness Exit"
|
||||
)
|
||||
|
||||
# Mire -> Hera -> Swamp
|
||||
def mire_clip(state):
|
||||
return state.can_reach(
|
||||
"Mire Torches Top", "Region", player
|
||||
) and state.can_dash_clip(world.get_region("Mire Torches Top", player), player)
|
||||
|
||||
def hera_clip(state):
|
||||
return state.can_reach("Hera 4F", "Region", player) and state.can_dash_clip(
|
||||
world.get_region("Hera 4F", player), player
|
||||
torches = world.get_region("Mire Torches Top", player)
|
||||
return state.can_dash_clip(torches, player) or (
|
||||
state.can_bomb_clip(torches, player) and state.has_fire_source(player)
|
||||
)
|
||||
|
||||
def hera_clip(state):
|
||||
hera = world.get_region("Hera 4F", player)
|
||||
return state.can_bomb_clip(hera, player) or state.can_dash_clip(hera, player)
|
||||
|
||||
# We use these plus functool.partial because lambdas don't work in loops properly.
|
||||
def bomb_clip(state, region, player):
|
||||
return state.can_bomb_clip(region, player)
|
||||
|
||||
def dash_clip(state, region, player):
|
||||
return state.can_dash_clip(region, player)
|
||||
# Bomb clips
|
||||
for clip in (
|
||||
kikiskip_spots
|
||||
+ icepalace_spots
|
||||
+ thievesdesert_spots
|
||||
+ specrock_spots
|
||||
):
|
||||
region = world.get_region(clip[1], player)
|
||||
Rules.set_rule(
|
||||
world.get_entrance(clip[0], player),
|
||||
functools.partial(bomb_clip, region=region, player=player),
|
||||
)
|
||||
# Dash clips
|
||||
for clip in icepalace_spots:
|
||||
region = world.get_region(clip[1], player)
|
||||
Rules.add_rule(
|
||||
world.get_entrance(clip[0], player),
|
||||
functools.partial(dash_clip, region=region, player=player),
|
||||
combine="or",
|
||||
)
|
||||
|
||||
for spot in kikiskip_spots + thievesdesert_spots:
|
||||
dungeon_reentry_rules(
|
||||
world,
|
||||
player,
|
||||
world.get_entrance(spot[0], player),
|
||||
spot[2],
|
||||
)
|
||||
|
||||
for clip in mirehera_spots:
|
||||
Rules.set_rule(
|
||||
world.get_entrance(clip[0], player),
|
||||
lambda state: mire_clip(state),
|
||||
)
|
||||
|
||||
# Need to be able to escape by hitting the switch from the back
|
||||
Rules.set_rule(
|
||||
world.get_entrance("Ice Bomb Drop Clip", player),
|
||||
lambda state: (
|
||||
state.can_use_bombs(player) or state.has("Cane of Somaria", player)
|
||||
),
|
||||
)
|
||||
|
||||
# Allow mire big key to be used in Hera
|
||||
Rules.add_rule(
|
||||
world.get_entrance("Hera Startile Corner NW", player),
|
||||
lambda state: mire_clip(state) and state.has("Big Key (Misery Mire)", player),
|
||||
@@ -209,20 +238,10 @@ def underworld_glitches_rules(world, player):
|
||||
lambda state: mire_clip(state) and state.has("Big Key (Misery Mire)", player),
|
||||
combine="or",
|
||||
)
|
||||
|
||||
mire_to_hera = world.get_entrance("Mire to Hera Clip", player)
|
||||
mire_to_swamp = world.get_entrance("Hera to Swamp Clip", player)
|
||||
Rules.set_rule(mire_to_hera, mire_clip)
|
||||
# This uses the mire clip because it's always expected to come from mire
|
||||
Rules.set_rule(
|
||||
mire_to_swamp, lambda state: mire_clip(state) and state.has("Flippers", player)
|
||||
)
|
||||
|
||||
# Using the entrances for various ER types. Hera -> Swamp never matters because you can only logically traverse with the mire keys
|
||||
dungeon_reentry_rules(
|
||||
world, player, mire_to_hera, "Hera Lobby", "Tower of Hera Exit"
|
||||
)
|
||||
dungeon_reentry_rules(
|
||||
world, player, mire_to_swamp, "Swamp Lobby", "Swamp Palace Exit"
|
||||
world.get_entrance("Hera to Swamp Clip", player),
|
||||
lambda state: mire_clip(state) and state.has("Flippers", player),
|
||||
)
|
||||
# We need to set _all_ swamp doors to be openable with mire keys, otherwise the small key can't be behind them - 6 keys because of Pots
|
||||
# Flippers required for all of these doors to prevent locks when flooding
|
||||
@@ -246,7 +265,6 @@ def underworld_glitches_rules(world, player):
|
||||
and state.has("Flippers", player),
|
||||
combine="or",
|
||||
)
|
||||
# Rules.add_rule(world.get_entrance(door, player), lambda state: mire_clip(state) and state.has('Flippers', player), combine="or")
|
||||
|
||||
Rules.add_rule(
|
||||
world.get_location("Trench 1 Switch", player),
|
||||
@@ -272,16 +290,16 @@ def underworld_glitches_rules(world, player):
|
||||
)
|
||||
),
|
||||
}
|
||||
inverted = world.mode[player] == "inverted"
|
||||
inverted_dm = (world.mode[player] == "inverted") != world.is_tile_swapped(0x03, player)
|
||||
|
||||
def hera_rule(state):
|
||||
return (state.has("Moon Pearl", player) or not inverted) and rule_map.get(
|
||||
return (state.has("Moon Pearl", player) or not inverted_dm) and rule_map.get(
|
||||
world.get_entrance("Tower of Hera", player).connected_region.name,
|
||||
lambda state: False,
|
||||
)(state)
|
||||
|
||||
def gt_rule(state):
|
||||
return (state.has("Moon Pearl", player) or inverted) and rule_map.get(
|
||||
return (state.has("Moon Pearl", player) or inverted_dm) and rule_map.get(
|
||||
world.get_entrance(("Ganons Tower"), player).connected_region.name,
|
||||
lambda state: False,
|
||||
)(state)
|
||||
@@ -299,21 +317,16 @@ def underworld_glitches_rules(world, player):
|
||||
lambda state: mirrorless_moat_rule(state),
|
||||
combine="or",
|
||||
)
|
||||
desert_exits = ["West", "South", "East"]
|
||||
|
||||
for desert_exit in ["East", "South", "West"]:
|
||||
for desert_exit in desert_exits:
|
||||
Rules.add_rule(
|
||||
world.get_entrance(f"Thieves to Desert {desert_exit} Connector", player),
|
||||
world.get_entrance(f"Thieves to Desert {desert_exit} Clip", player),
|
||||
lambda state: state.can_dash_clip(
|
||||
world.get_region("Thieves Attic", player), player
|
||||
),
|
||||
)
|
||||
dungeon_reentry_rules(
|
||||
world,
|
||||
player,
|
||||
world.get_entrance(f"Thieves to Desert {desert_exit} Connector", player),
|
||||
f"Desert {desert_exit} Portal",
|
||||
f"Desert Palace Exit ({desert_exit})",
|
||||
)
|
||||
|
||||
|
||||
# Collecting left chests in Paradox Cave using a dash clip -> dash citrus, 1f right, teleport up
|
||||
paradox_left_chests = [
|
||||
|
||||
Binary file not shown.
@@ -21,7 +21,7 @@ UwGeneralDeny:
|
||||
- [ 0x0016, 1, [ "SparkCW", "SparkCCW", "RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalRight", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper", "GreenMimic", "RedMimic", "Pikit" ] ] #"Swamp Palace - Pool - Zol 2"
|
||||
- [ 0x0016, 2, [ "SparkCW", "SparkCCW", "RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalRight", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper", "GreenMimic", "RedMimic", "Pikit" ] ] #"Swamp Palace - Pool - Blue Bari"
|
||||
- [ 0x0016, 3, [ "RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalRight", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Swamp Palace - Pool - Zol 3"
|
||||
- [ 0x0017, 5, [ "Beamos", "AntiFairyCircle", "SpikeBlock", "Bumper" ] ] #"Tower Of Hera - Bumper Room - Fire Bar (Clockwise)"
|
||||
- [ 0x0017, 5, [ "Beamos", "AntiFairyCircle", "SpikeBlock", "Bumper" ] ] #"Tower of Hera - Bumper Room - Fire Bar (Clockwise)"
|
||||
- [ 0x0019, 0, [ "SparkCW", "SparkCCW", "RollerVerticalDown", "Beamos", "AntiFairyCircle", "BigSpike", "Bumper" ] ] #"Palace of Darkness - Dark Maze - Kodongo 1"
|
||||
- [ 0x0019, 1, [ "RollerVerticalUp" ] ] #"Palace of Darkness - Dark Maze - Kodongo 2"
|
||||
- [ 0x0019, 2, [ "RollerVerticalDown", "RollerVerticalUp" ] ] #"Palace of Darkness - Dark Maze - Kodongo 3"
|
||||
@@ -46,11 +46,11 @@ UwGeneralDeny:
|
||||
- [ 0x0026, 9, [ "RollerHorizontalRight", "Statue" ] ] #"Swamp Palace - Big Spoon - Kyameron"
|
||||
- [ 0x0026, 10, [ "Statue" ] ] # multiple push statues in this room can cause issues
|
||||
- [ 0x0026, 11, [ "Statue" ] ] # multiple push statues in this room can cause issues
|
||||
- [ 0x0027, 0, [ "SparkCW", "SparkCCW", "RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalLeft", "FirebarCW" ] ] #"Tower Of Hera - Petting Zoo - Mini Moldorm 1"
|
||||
- [ 0x0027, 1, [ "RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalRight", "RollerHorizontalLeft", "AntiFairyCircle", "SpikeBlock", "Bumper" ] ] #"Tower Of Hera - Petting Zoo - Mini Moldorm 2"
|
||||
- [ 0x0027, 2, [ "RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalRight", "RollerHorizontalLeft", "AntiFairyCircle", "SpikeBlock", "Bumper" ] ] #"Tower Of Hera - Petting Zoo - Mini Moldorm 3"
|
||||
- [ 0x0027, 0, [ "SparkCW", "SparkCCW", "RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalLeft", "FirebarCW" ] ] #"Tower of Hera - Petting Zoo - Mini Moldorm 1"
|
||||
- [ 0x0027, 1, [ "RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalRight", "RollerHorizontalLeft", "AntiFairyCircle", "SpikeBlock", "Bumper" ] ] #"Tower of Hera - Petting Zoo - Mini Moldorm 2"
|
||||
- [ 0x0027, 2, [ "RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalRight", "RollerHorizontalLeft", "AntiFairyCircle", "SpikeBlock", "Bumper" ] ] #"Tower of Hera - Petting Zoo - Mini Moldorm 3"
|
||||
- [ 0x0027, 4, ["Bumper", "BigSpike", "AntiFairyCircle", "RollerVerticalDown", "RollerVerticalUp"]]
|
||||
- [ 0x0027, 5, [ "SparkCW", "SparkCCW", "RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Tower Of Hera - Petting Zoo - Kodongo 1"
|
||||
- [ 0x0027, 5, [ "SparkCW", "SparkCCW", "RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Tower of Hera - Petting Zoo - Kodongo 1"
|
||||
- [0x0028, 0, ["Raven", "Poe", "GreenZirro", "BlueZirro", "Swamola", "Zora"]]
|
||||
- [0x0028, 1, ["Raven", "Poe", "GreenZirro", "BlueZirro", "Swamola", "Zora"]]
|
||||
- [0x0028, 2, ["Raven", "Poe", "GreenZirro", "BlueZirro", "Swamola", "Zora"]]
|
||||
|
||||
@@ -111,7 +111,7 @@ def resolve_districts(world):
|
||||
visited = set()
|
||||
while len(queue) > 0:
|
||||
region = queue.pop()
|
||||
if not region:
|
||||
if region is None:
|
||||
RuntimeError(f'No region connected to entrance: {ent.name} Likely a missing entry in OWExitTypes')
|
||||
visited.add(region)
|
||||
if region.type == RegionType.Cave:
|
||||
|
||||
@@ -907,7 +907,7 @@ def figure_out_connectors(exits, avail, cross_world=True):
|
||||
cave_list = list(Connector_List)
|
||||
if avail.assumed_loose_caves or (not avail.skull_handled and (cross_world or not avail.world.is_tile_swapped(0x00, avail.player))):
|
||||
skull_connector = [x for x in ['Skull Woods Second Section Exit (West)', 'Skull Woods Second Section Exit (East)'] if x in exits]
|
||||
cave_list.extend(skull_connector)
|
||||
cave_list.extend([skull_connector])
|
||||
if avail.assumed_loose_caves or not avail.keep_drops_together:
|
||||
cave_list.extend([[entrance_map[e]] for e in linked_drop_map.values() if 'Inverted ' not in e and 'Skull Woods ' not in e])
|
||||
|
||||
@@ -1631,7 +1631,8 @@ def do_mandatory_connections(avail, entrances, cave_options, must_exit):
|
||||
cave_entrances = []
|
||||
for cave_exit in rnd_cave[:-1]:
|
||||
if avail.swapped and cave_exit not in avail.exits:
|
||||
entrance = avail.world.get_entrance(cave_exit, avail.player).parent_region.entrances[0].name
|
||||
entrance = avail.world.get_entrance(cave_exit, avail.player)
|
||||
entrance = next((e for e in entrance.parent_region.entrances if e.parent_region.type in [RegionType.LightWorld, RegionType.DarkWorld])).name
|
||||
cave_entrances.append(entrance)
|
||||
else:
|
||||
entrance = next(e for e in entrances[::-1] if e not in invalid_connections[exit] and e not in must_exit
|
||||
@@ -1917,8 +1918,8 @@ def connect_exit(exit_name, entrancename, avail):
|
||||
exit.connected_region.entrances.remove(exit)
|
||||
|
||||
dest_region = entrance.parent_region
|
||||
if dest_region.name == 'Pyramid Crack':
|
||||
# Needs to logically exit into greater Pyramid Area
|
||||
if dest_region.name in ['Pyramid Crack', 'GT Stairs']:
|
||||
# Needs to logically exit into greater OW area
|
||||
dest_region = entrance.parent_region.entrances[0].parent_region
|
||||
|
||||
exit.connect(dest_region, door_addresses[entrance.name][1], exit_ids[exit.name][1])
|
||||
|
||||
@@ -19,8 +19,6 @@ advanced_placements:
|
||||
locations:
|
||||
Link's House: True
|
||||
Magic Bat: False
|
||||
advanced_placements:
|
||||
1:
|
||||
- type: Verification
|
||||
item: Progressive Glove
|
||||
locations:
|
||||
|
||||
@@ -5,7 +5,6 @@ settings:
|
||||
logic: hybridglitches
|
||||
mode: inverted
|
||||
shuffle: crossed
|
||||
|
||||
start_inventory:
|
||||
1:
|
||||
- Pegasus Boots
|
||||
@@ -15,6 +14,8 @@ start_inventory:
|
||||
placements:
|
||||
1:
|
||||
Desert Palace - Boss: Moon Pearl
|
||||
Desert Palace - Prize: Green Pendant
|
||||
Sahasrahla: Magic Mirror
|
||||
entrances:
|
||||
1:
|
||||
two-way:
|
||||
@@ -23,4 +24,6 @@ entrances:
|
||||
Thieves Town: Thieves Town Exit
|
||||
Hyrule Castle Entrance (East): Desert Palace Exit (South)
|
||||
Hyrule Castle Entrance (West): Desert Palace Exit (North)
|
||||
entrances:
|
||||
Agahnims Tower: Pyramid Fairy
|
||||
|
||||
|
||||
@@ -15,6 +15,9 @@ start_inventory:
|
||||
- Ether
|
||||
- Quake
|
||||
- Bombos
|
||||
- Big Key (Tower of Hera)
|
||||
- Big Key (Desert Palace)
|
||||
- Big Key (Eastern Palace)
|
||||
advanced_placements:
|
||||
1:
|
||||
- type: Verification
|
||||
|
||||
@@ -3,6 +3,7 @@ meta:
|
||||
settings:
|
||||
1:
|
||||
logic: hybridglitches
|
||||
shuffle: vanilla
|
||||
start_inventory:
|
||||
1:
|
||||
- Pegasus Boots
|
||||
@@ -10,9 +11,8 @@ start_inventory:
|
||||
- Fire Rod
|
||||
- Book of Mudora
|
||||
- Progressive Sword
|
||||
- Progressive Sword
|
||||
- Lamp
|
||||
- Magic Mirror
|
||||
- Hammer
|
||||
- Ether
|
||||
- Quake
|
||||
- Bombos
|
||||
@@ -41,6 +41,7 @@ advanced_placements:
|
||||
C-Shaped House: True
|
||||
Pyramid Fairy - Left: True
|
||||
Swamp Palace - Entrance: False
|
||||
Swamp Palace - Boss: False
|
||||
Thieves' Town - Map Chest: False
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
meta:
|
||||
players: 1
|
||||
settings:
|
||||
1:
|
||||
logic: hybridglitches
|
||||
shuffle: vanilla
|
||||
start_inventory:
|
||||
1:
|
||||
- Pegasus Boots
|
||||
- Flippers
|
||||
- Fire Rod
|
||||
- Book of Mudora
|
||||
- Progressive Sword
|
||||
- Lamp
|
||||
- Hammer
|
||||
- Ether
|
||||
- Quake
|
||||
- Bombos
|
||||
- Bombs (10)
|
||||
placements:
|
||||
1:
|
||||
# Put mirror in PF so we can't DMD
|
||||
Pyramid Fairy - Right: Magic Mirror
|
||||
# Lock all swords and cape behind pearl so we can't do aga 1 for pyramid access
|
||||
Thieves' Town - Big Chest: Progressive Sword
|
||||
Thieves' Town - Attic: Progressive Sword
|
||||
Thieves' Town - Blind's Cell: Progressive Sword
|
||||
Thieves' Town - Map Chest: Cape
|
||||
advanced_placements:
|
||||
1:
|
||||
- type: Verification
|
||||
item: Moon Pearl
|
||||
locations:
|
||||
Palace of Darkness - Shooter Room: True
|
||||
Palace of Darkness - The Arena - Bridge: True
|
||||
Palace of Darkness - Stalfos Basement: True
|
||||
Palace of Darkness - Big Key Chest: True
|
||||
Palace of Darkness - The Arena - Ledge: True
|
||||
Palace of Darkness - Map Chest: True
|
||||
Palace of Darkness - Compass Chest: True
|
||||
Palace of Darkness - Dark Basement - Left: True
|
||||
Palace of Darkness - Dark Basement - Right: True
|
||||
Palace of Darkness - Dark Maze - Top: True
|
||||
Palace of Darkness - Dark Maze - Bottom: True
|
||||
Palace of Darkness - Big Chest: True
|
||||
Palace of Darkness - Harmless Hellway: True
|
||||
Palace of Darkness - Boss: True
|
||||
Pyramid Fairy - Left: False
|
||||
Pyramid: False
|
||||
@@ -9,6 +9,7 @@ start_inventory:
|
||||
- Flippers
|
||||
- Pegasus Boots
|
||||
- Progressive Sword
|
||||
- Progressive Sword
|
||||
- Hammer
|
||||
- Progressive Glove
|
||||
- Progressive Glove
|
||||
@@ -17,9 +18,16 @@ start_inventory:
|
||||
- Bottle
|
||||
- Magic Mirror
|
||||
- Lamp
|
||||
- Beat Agahnim 1
|
||||
- Cane of Somaria
|
||||
- Hookshot
|
||||
- Quake
|
||||
- Ether
|
||||
- Bombos
|
||||
advanced_placements:
|
||||
1:
|
||||
- type: Verification
|
||||
item: Moon Pearl
|
||||
locations:
|
||||
Skull Woods - Bridge Room: True
|
||||
Skull Woods - Boss: True
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
meta:
|
||||
players: 1
|
||||
settings:
|
||||
1:
|
||||
logic: hybridglitches
|
||||
mode: open
|
||||
shuffle: vanilla
|
||||
start_inventory:
|
||||
1:
|
||||
- Pegasus Boots
|
||||
placements:
|
||||
1:
|
||||
Palace of Darkness - Shooter Room: Moon Pearl
|
||||
Reference in New Issue
Block a user