Merge branch 'DoorDevUnstable' into Synthesis
# Conflicts: # TestSuite.py
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -4,6 +4,9 @@
|
|||||||
*.bmbp
|
*.bmbp
|
||||||
*.log
|
*.log
|
||||||
*_Spoiler.json
|
*_Spoiler.json
|
||||||
|
*_custom.yaml
|
||||||
|
*_meta.txt
|
||||||
|
*.bps
|
||||||
*.pyc
|
*.pyc
|
||||||
*.sfc
|
*.sfc
|
||||||
*.srm
|
*.srm
|
||||||
|
|||||||
@@ -2813,6 +2813,11 @@ class Pot(object):
|
|||||||
item = self.item if not self.indicator else self.standing_item_code
|
item = self.item if not self.indicator else self.standing_item_code
|
||||||
return [self.x, high_byte, item]
|
return [self.x, high_byte, item]
|
||||||
|
|
||||||
|
def get_region(self, world, player):
|
||||||
|
if world.mode[player] == 'inverted' and self.room == 'Links House':
|
||||||
|
return world.get_region('Inverted Links House', 1)
|
||||||
|
return world.get_region(self.room, 1)
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
return self.x == other.x and self.y == other.y and self.room == other.room
|
return self.x == other.x and self.y == other.y and self.room == other.room
|
||||||
|
|
||||||
|
|||||||
@@ -233,7 +233,7 @@ def vanilla_key_logic(world, player):
|
|||||||
key_layout = build_key_layout(builder, start_regions, doors, world, player)
|
key_layout = build_key_layout(builder, start_regions, doors, world, player)
|
||||||
valid = validate_key_layout(key_layout, world, player)
|
valid = validate_key_layout(key_layout, world, player)
|
||||||
if not valid:
|
if not valid:
|
||||||
logging.getLogger('').warning('Vanilla key layout not valid %s', builder.name)
|
logging.getLogger('').info('Vanilla key layout not valid %s', builder.name)
|
||||||
builder.key_door_proposal = doors
|
builder.key_door_proposal = doors
|
||||||
if player not in world.key_logic.keys():
|
if player not in world.key_logic.keys():
|
||||||
world.key_logic[player] = {}
|
world.key_logic[player] = {}
|
||||||
@@ -799,11 +799,17 @@ def main_dungeon_pool(dungeon_pool, world, player):
|
|||||||
else:
|
else:
|
||||||
if 'Hyrule Castle' in pool:
|
if 'Hyrule Castle' in pool:
|
||||||
hc = world.get_dungeon('Hyrule Castle', player)
|
hc = world.get_dungeon('Hyrule Castle', player)
|
||||||
hc.dungeon_items.append(ItemFactory('Compass (Escape)', player))
|
hc_compass = ItemFactory('Compass (Escape)', player)
|
||||||
|
hc_compass.advancement = world.restrict_boss_items[player] != 'none'
|
||||||
|
hc.dungeon_items.append(hc_compass)
|
||||||
if 'Agahnims Tower' in pool:
|
if 'Agahnims Tower' in pool:
|
||||||
at = world.get_dungeon('Agahnims Tower', player)
|
at = world.get_dungeon('Agahnims Tower', player)
|
||||||
at.dungeon_items.append(ItemFactory('Compass (Agahnims Tower)', player))
|
at_compass = ItemFactory('Compass (Agahnims Tower)', player)
|
||||||
at.dungeon_items.append(ItemFactory('Map (Agahnims Tower)', player))
|
at_compass.advancement = world.restrict_boss_items[player] != 'none'
|
||||||
|
at.dungeon_items.append(at_compass)
|
||||||
|
at_map = ItemFactory('Map (Agahnims Tower)', player)
|
||||||
|
at_map.advancement = world.restrict_boss_items[player] != 'none'
|
||||||
|
at.dungeon_items.append(at_map)
|
||||||
sector_pool = convert_to_sectors(region_list, world, player)
|
sector_pool = convert_to_sectors(region_list, world, player)
|
||||||
merge_sectors(sector_pool, world, player)
|
merge_sectors(sector_pool, world, player)
|
||||||
# todo: which dungeon to create
|
# todo: which dungeon to create
|
||||||
@@ -1227,11 +1233,16 @@ def cross_dungeon(world, player):
|
|||||||
paths = determine_required_paths(world, player)
|
paths = determine_required_paths(world, player)
|
||||||
check_required_paths(paths, world, player)
|
check_required_paths(paths, world, player)
|
||||||
|
|
||||||
|
hc_compass = ItemFactory('Compass (Escape)', player)
|
||||||
|
at_compass = ItemFactory('Compass (Agahnims Tower)', player)
|
||||||
|
at_map = ItemFactory('Map (Agahnims Tower)', player)
|
||||||
|
if world.restrict_boss_items[player] != 'none':
|
||||||
|
hc_compass.advancement = at_compass.advancement = at_map.advancement = True
|
||||||
hc = world.get_dungeon('Hyrule Castle', player)
|
hc = world.get_dungeon('Hyrule Castle', player)
|
||||||
hc.dungeon_items.append(ItemFactory('Compass (Escape)', player))
|
hc.dungeon_items.append(hc_compass)
|
||||||
at = world.get_dungeon('Agahnims Tower', player)
|
at = world.get_dungeon('Agahnims Tower', player)
|
||||||
at.dungeon_items.append(ItemFactory('Compass (Agahnims Tower)', player))
|
at.dungeon_items.append(at_compass)
|
||||||
at.dungeon_items.append(ItemFactory('Map (Agahnims Tower)', player))
|
at.dungeon_items.append(at_map)
|
||||||
|
|
||||||
setup_custom_door_types(world, player)
|
setup_custom_door_types(world, player)
|
||||||
assign_cross_keys(dungeon_builders, world, player)
|
assign_cross_keys(dungeon_builders, world, player)
|
||||||
@@ -3196,8 +3207,10 @@ def find_inaccessible_regions(world, player):
|
|||||||
def find_accessible_entrances(world, player, builder):
|
def find_accessible_entrances(world, player, builder):
|
||||||
entrances = [region.name for region in (portal.door.entrance.parent_region for portal in world.dungeon_portals[player]) if region.dungeon.name == builder.name]
|
entrances = [region.name for region in (portal.door.entrance.parent_region for portal in world.dungeon_portals[player]) if region.dungeon.name == builder.name]
|
||||||
entrances.extend(drop_entrances[builder.name])
|
entrances.extend(drop_entrances[builder.name])
|
||||||
|
hc_std = False
|
||||||
|
|
||||||
if world.mode[player] == 'standard' and builder.name == 'Hyrule Castle':
|
if world.mode[player] == 'standard' and builder.name == 'Hyrule Castle':
|
||||||
|
hc_std = True
|
||||||
start_regions = ['Hyrule Castle Courtyard']
|
start_regions = ['Hyrule Castle Courtyard']
|
||||||
elif world.mode[player] != 'inverted':
|
elif world.mode[player] != 'inverted':
|
||||||
start_regions = ['Links House', 'Sanctuary']
|
start_regions = ['Links House', 'Sanctuary']
|
||||||
@@ -3222,6 +3235,8 @@ def find_accessible_entrances(world, player, builder):
|
|||||||
if connect not in queue and connect not in visited_regions:
|
if connect not in queue and connect not in visited_regions:
|
||||||
queue.append(connect)
|
queue.append(connect)
|
||||||
for ext in next_region.exits:
|
for ext in next_region.exits:
|
||||||
|
if hc_std and ext.name == 'Hyrule Castle Main Gate (North)': # just skip it
|
||||||
|
continue
|
||||||
connect = ext.connected_region
|
connect = ext.connected_region
|
||||||
if connect is None or ext.door and ext.door.blocked:
|
if connect is None or ext.door and ext.door.blocked:
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -63,9 +63,10 @@ def link_entrances(world, player):
|
|||||||
connect_caves(world, lw_entrances, [], hyrule_castle_exits, player)
|
connect_caves(world, lw_entrances, [], hyrule_castle_exits, player)
|
||||||
elif world.doorShuffle[player] != 'vanilla':
|
elif world.doorShuffle[player] != 'vanilla':
|
||||||
# sanc is in light world, so must all of HC if door shuffle is on
|
# sanc is in light world, so must all of HC if door shuffle is on
|
||||||
connect_mandatory_exits(world, lw_entrances,
|
hyrule_castle_exits = [('Hyrule Castle Exit (West)', 'Hyrule Castle Exit (East)', 'Hyrule Castle Exit (South)')]
|
||||||
[('Hyrule Castle Exit (West)', 'Hyrule Castle Exit (East)', 'Hyrule Castle Exit (South)')],
|
connect_mandatory_exits(world, lw_entrances, hyrule_castle_exits,
|
||||||
list(LW_Dungeon_Entrances_Must_Exit), player)
|
list(LW_Dungeon_Entrances_Must_Exit), player)
|
||||||
|
connect_caves(world, lw_entrances, [], hyrule_castle_exits, player)
|
||||||
else:
|
else:
|
||||||
connect_mandatory_exits(world, lw_entrances, dungeon_exits, list(LW_Dungeon_Entrances_Must_Exit), player)
|
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)
|
connect_mandatory_exits(world, dw_entrances, dungeon_exits, list(DW_Dungeon_Entrances_Must_Exit), player)
|
||||||
|
|||||||
8
Fill.py
8
Fill.py
@@ -48,6 +48,10 @@ def fill_dungeons_restrictive(world, shuffled_locations):
|
|||||||
bigs, smalls, others = [], [], []
|
bigs, smalls, others = [], [], []
|
||||||
for i in dungeon_items:
|
for i in dungeon_items:
|
||||||
(bigs if i.bigkey else smalls if i.smallkey else others).append(i)
|
(bigs if i.bigkey else smalls if i.smallkey else others).append(i)
|
||||||
|
unplaced_smalls = list(smalls)
|
||||||
|
for i in world.itempool:
|
||||||
|
if i.smallkey and world.keyshuffle[i.player]:
|
||||||
|
unplaced_smalls.append(i)
|
||||||
|
|
||||||
def fill(base_state, items, key_pool):
|
def fill(base_state, items, key_pool):
|
||||||
fill_restrictive(world, base_state, shuffled_locations, items, key_pool, True)
|
fill_restrictive(world, base_state, shuffled_locations, items, key_pool, True)
|
||||||
@@ -56,12 +60,12 @@ def fill_dungeons_restrictive(world, shuffled_locations):
|
|||||||
big_state_base = all_state_base.copy()
|
big_state_base = all_state_base.copy()
|
||||||
for x in smalls + others:
|
for x in smalls + others:
|
||||||
big_state_base.collect(x, True)
|
big_state_base.collect(x, True)
|
||||||
fill(big_state_base, bigs, smalls)
|
fill(big_state_base, bigs, unplaced_smalls)
|
||||||
random.shuffle(shuffled_locations)
|
random.shuffle(shuffled_locations)
|
||||||
small_state_base = all_state_base.copy()
|
small_state_base = all_state_base.copy()
|
||||||
for x in others:
|
for x in others:
|
||||||
small_state_base.collect(x, True)
|
small_state_base.collect(x, True)
|
||||||
fill(small_state_base, smalls, list(smalls))
|
fill(small_state_base, smalls, unplaced_smalls)
|
||||||
random.shuffle(shuffled_locations)
|
random.shuffle(shuffled_locations)
|
||||||
fill(all_state_base, others, None)
|
fill(all_state_base, others, None)
|
||||||
|
|
||||||
|
|||||||
@@ -894,7 +894,7 @@ def shuffle_pots(world, player):
|
|||||||
new_pot.item = PotItem.FiveRupees
|
new_pot.item = PotItem.FiveRupees
|
||||||
|
|
||||||
if new_pot.item == PotItem.Key:
|
if new_pot.item == PotItem.Key:
|
||||||
key = next(location for location in world.get_region(old_pot.room, player).locations if location.name in key_drop_data)
|
key = next(location for location in old_pot.get_region(world, player).locations if location.name in key_drop_data)
|
||||||
key.pot = new_pot
|
key.pot = new_pot
|
||||||
if new_pot.room != old_pot.room:
|
if new_pot.room != old_pot.room:
|
||||||
# Move pot key to new room
|
# Move pot key to new room
|
||||||
@@ -970,7 +970,7 @@ def choose_pots(world, player):
|
|||||||
dungeon_list = []
|
dungeon_list = []
|
||||||
for super_tile, pot_list in vanilla_pots.items():
|
for super_tile, pot_list in vanilla_pots.items():
|
||||||
for pot in pot_list:
|
for pot in pot_list:
|
||||||
if world.get_region(pot.room, player).type == RegionType.Cave:
|
if pot.get_region(world, player).type == RegionType.Cave:
|
||||||
pot_pool.add(pot)
|
pot_pool.add(pot)
|
||||||
else:
|
else:
|
||||||
dungeon_list.append(pot)
|
dungeon_list.append(pot)
|
||||||
@@ -981,7 +981,7 @@ def choose_pots(world, player):
|
|||||||
dungeon_count = 0
|
dungeon_count = 0
|
||||||
for super_tile, pot_list in vanilla_pots.items():
|
for super_tile, pot_list in vanilla_pots.items():
|
||||||
for pot in pot_list:
|
for pot in pot_list:
|
||||||
if world.get_region(pot.room, player).type == RegionType.Cave:
|
if pot.get_region(world, player).type == RegionType.Cave:
|
||||||
pot_pool.add(pot)
|
pot_pool.add(pot)
|
||||||
else:
|
else:
|
||||||
dungeon_map[pot.room].append(pot)
|
dungeon_map[pot.room].append(pot)
|
||||||
|
|||||||
@@ -217,6 +217,8 @@ Same as above but both small keys and bigs keys of the dungeon are not allowed o
|
|||||||
* Fixed an issue where trinity goal would open pyramid unexpectedly. (No longer does so if ER mdoe is shuffling holes). Crystals goal updated to match that behavior.
|
* Fixed an issue where trinity goal would open pyramid unexpectedly. (No longer does so if ER mdoe is shuffling holes). Crystals goal updated to match that behavior.
|
||||||
* Fixed a playthrough issue that was not respecting pot rules
|
* Fixed a playthrough issue that was not respecting pot rules
|
||||||
* Fixed an issue that was conflicting with downstream OWR project
|
* Fixed an issue that was conflicting with downstream OWR project
|
||||||
|
* Fixed an issue with inverted and certain pottery settings
|
||||||
|
* Fixed an issue with small keys being shuffled and big keys not (key distribution)
|
||||||
* 1.0.1.1
|
* 1.0.1.1
|
||||||
* Fixed the pots in Mire Storyteller/ Dark Desert Hint to be colorized when they should be
|
* Fixed the pots in Mire Storyteller/ Dark Desert Hint to be colorized when they should be
|
||||||
* Certain pot items no longer reload when reloading the supertile (matches original pot behavior better)
|
* Certain pot items no longer reload when reloading the supertile (matches original pot behavior better)
|
||||||
|
|||||||
@@ -1073,9 +1073,9 @@ def valid_pot_location(pot, pot_set, world, player):
|
|||||||
return True
|
return True
|
||||||
if world.pottery[player] in ['reduced', 'clustered'] and pot in pot_set:
|
if world.pottery[player] in ['reduced', 'clustered'] and pot in pot_set:
|
||||||
return True
|
return True
|
||||||
if world.pottery[player] == 'dungeon' and world.get_region(pot.room, player).type == RegionType.Dungeon:
|
if world.pottery[player] == 'dungeon' and pot.get_region(world, player).type == RegionType.Dungeon:
|
||||||
return True
|
return True
|
||||||
if world.pottery[player] in ['cave', 'cavekeys'] and world.get_region(pot.room, player).type == RegionType.Cave:
|
if world.pottery[player] in ['cave', 'cavekeys'] and pot.get_region(world, player).type == RegionType.Cave:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|||||||
4
Rules.py
4
Rules.py
@@ -323,8 +323,10 @@ def global_rules(world, player):
|
|||||||
# byrna could work with sufficient magic
|
# byrna could work with sufficient magic
|
||||||
set_rule(world.get_location('Misery Mire - Spike Chest', player), lambda state: (state.world.can_take_damage and state.has_hearts(player, 4)) or state.has('Cane of Byrna', player) or state.has('Cape', player))
|
set_rule(world.get_location('Misery Mire - Spike Chest', player), lambda state: (state.world.can_take_damage and state.has_hearts(player, 4)) or state.has('Cane of Byrna', player) or state.has('Cape', player))
|
||||||
loc = world.get_location('Misery Mire - Spikes Pot Key', player)
|
loc = world.get_location('Misery Mire - Spikes Pot Key', player)
|
||||||
|
if loc.pot:
|
||||||
if loc.pot.x == 48 and loc.pot.y == 28: # pot shuffled to spike area
|
if loc.pot.x == 48 and loc.pot.y == 28: # pot shuffled to spike area
|
||||||
set_rule(loc, lambda state: (state.world.can_take_damage and state.has_hearts(player, 4)) or state.has('Cane of Byrna', player) or state.has('Cape', player))
|
set_rule(loc, lambda state: (state.world.can_take_damage and state.has_hearts(player, 4))
|
||||||
|
or state.has('Cane of Byrna', player) or state.has('Cape', player))
|
||||||
set_rule(world.get_entrance('Mire Left Bridge Hook Path', player), lambda state: state.has('Hookshot', player))
|
set_rule(world.get_entrance('Mire Left Bridge Hook Path', player), lambda state: state.has('Hookshot', player))
|
||||||
set_rule(world.get_entrance('Mire Tile Room NW', player), lambda state: state.has_fire_source(player))
|
set_rule(world.get_entrance('Mire Tile Room NW', player), lambda state: state.has_fire_source(player))
|
||||||
set_rule(world.get_entrance('Mire Attic Hint Hole', player), lambda state: state.has_fire_source(player))
|
set_rule(world.get_entrance('Mire Attic Hint Hole', player), lambda state: state.has_fire_source(player))
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ if os.path.isdir("build") and not sys.platform.find("mac") and not sys.platform.
|
|||||||
subprocess.run(" ".join([f"pyinstaller {SPEC_FILE} ",
|
subprocess.run(" ".join([f"pyinstaller {SPEC_FILE} ",
|
||||||
upx_string,
|
upx_string,
|
||||||
"-y ",
|
"-y ",
|
||||||
"--onefile ",
|
|
||||||
f"--distpath {DEST_DIRECTORY} ",
|
f"--distpath {DEST_DIRECTORY} ",
|
||||||
]),
|
]),
|
||||||
shell=True)
|
shell=True)
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ if os.path.isdir("build") and not sys.platform.find("mac") and not sys.platform.
|
|||||||
subprocess.run(" ".join([f"pyinstaller {SPEC_FILE} ",
|
subprocess.run(" ".join([f"pyinstaller {SPEC_FILE} ",
|
||||||
upx_string,
|
upx_string,
|
||||||
"-y ",
|
"-y ",
|
||||||
"--onefile ",
|
|
||||||
f"--distpath {DEST_DIRECTORY} ",
|
f"--distpath {DEST_DIRECTORY} ",
|
||||||
]),
|
]),
|
||||||
shell=True)
|
shell=True)
|
||||||
|
|||||||
Reference in New Issue
Block a user