Merged in DR v1.2.0.7
This commit is contained in:
@@ -814,6 +814,15 @@ class CollectionState(object):
|
|||||||
rrp[k] = missing_regions[k]
|
rrp[k] = missing_regions[k]
|
||||||
possible_path = terminal_states[0].path[k]
|
possible_path = terminal_states[0].path[k]
|
||||||
self.path[k] = paths[k] = possible_path
|
self.path[k] = paths[k] = possible_path
|
||||||
|
for conn in k.exits:
|
||||||
|
if self.is_small_door(conn):
|
||||||
|
door = conn.door if conn.door.smallKey else conn.door.controller
|
||||||
|
key_logic = self.world.key_logic[player][dungeon_name]
|
||||||
|
if door.name not in self.reached_doors[player]:
|
||||||
|
self.door_counter[player][0][dungeon_name] += 1
|
||||||
|
self.reached_doors[player].add(door.name)
|
||||||
|
if key_logic.sm_doors[door]:
|
||||||
|
self.reached_doors[player].add(key_logic.sm_doors[door].name)
|
||||||
missing_bc = {}
|
missing_bc = {}
|
||||||
for blocked, crystal in common_bc.items():
|
for blocked, crystal in common_bc.items():
|
||||||
if (blocked not in bc and blocked.parent_region in rrp
|
if (blocked not in bc and blocked.parent_region in rrp
|
||||||
@@ -3076,6 +3085,7 @@ class Spoiler(object):
|
|||||||
outfile.write('Enemy Health:'.ljust(line_width) + '%s\n' % self.metadata['enemy_health'][player])
|
outfile.write('Enemy Health:'.ljust(line_width) + '%s\n' % self.metadata['enemy_health'][player])
|
||||||
outfile.write('Enemy Damage:'.ljust(line_width) + '%s\n' % self.metadata['enemy_damage'][player])
|
outfile.write('Enemy Damage:'.ljust(line_width) + '%s\n' % self.metadata['enemy_damage'][player])
|
||||||
outfile.write('Hints:'.ljust(line_width) + '%s\n' % yn(self.metadata['hints'][player]))
|
outfile.write('Hints:'.ljust(line_width) + '%s\n' % yn(self.metadata['hints'][player]))
|
||||||
|
outfile.write('Race:'.ljust(line_width) + '%s\n' % yn(self.world.settings.world_rep['meta']['race']))
|
||||||
|
|
||||||
if self.startinventory:
|
if self.startinventory:
|
||||||
outfile.write('Starting Inventory:'.ljust(line_width))
|
outfile.write('Starting Inventory:'.ljust(line_width))
|
||||||
|
|||||||
5
CLI.py
5
CLI.py
@@ -123,6 +123,11 @@ def parse_cli(argv, no_defaults=False):
|
|||||||
for player in range(1, player_num + 1):
|
for player in range(1, player_num + 1):
|
||||||
playerargs = parse_cli(shlex.split(getattr(ret, f"p{player}")), True)
|
playerargs = parse_cli(shlex.split(getattr(ret, f"p{player}")), True)
|
||||||
|
|
||||||
|
if playerargs.filename:
|
||||||
|
playersettings = apply_settings_file({}, playerargs.filename)
|
||||||
|
for k, v in playersettings.items():
|
||||||
|
setattr(playerargs, k, v)
|
||||||
|
|
||||||
for name in ['logic', 'mode', 'swords', 'goal', 'difficulty', 'item_functionality', 'ow_shuffle',
|
for name in ['logic', 'mode', 'swords', 'goal', 'difficulty', 'item_functionality', 'ow_shuffle',
|
||||||
'ow_terrain', 'ow_crossed', 'ow_keepsimilar', 'ow_mixed', 'ow_whirlpool', 'ow_fluteshuffle',
|
'ow_terrain', 'ow_crossed', 'ow_keepsimilar', 'ow_mixed', 'ow_whirlpool', 'ow_fluteshuffle',
|
||||||
'flute_mode', 'bow_mode', 'take_any', 'boots_hint',
|
'flute_mode', 'bow_mode', 'take_any', 'boots_hint',
|
||||||
|
|||||||
@@ -477,14 +477,14 @@ def choose_portals(world, player):
|
|||||||
info.required_passage = {x: y for x, y in info.required_passage.items() if len(y) > 0}
|
info.required_passage = {x: y for x, y in info.required_passage.items() if len(y) > 0}
|
||||||
for target_region, possible_portals in info.required_passage.items():
|
for target_region, possible_portals in info.required_passage.items():
|
||||||
candidates = find_portal_candidates(master_door_list, dungeon, custom, allowed, need_passage=True,
|
candidates = find_portal_candidates(master_door_list, dungeon, custom, allowed, need_passage=True,
|
||||||
bk_shuffle=bk_shuffle, rupee_bow=rupee_bow_flag)
|
bk_shuffle=bk_shuffle, standard=std_flag, rupee_bow=rupee_bow_flag)
|
||||||
choice, portal = assign_portal(candidates, possible_portals, custom, world, player)
|
choice, portal = assign_portal(candidates, possible_portals, custom, world, player)
|
||||||
portal.destination = True
|
portal.destination = True
|
||||||
clean_up_portal_assignment(portal_assignment, dungeon, portal, master_door_list, outstanding_portals)
|
clean_up_portal_assignment(portal_assignment, dungeon, portal, master_door_list, outstanding_portals)
|
||||||
dead_end_choices = info.total - 1 - len(portal_assignment[dungeon])
|
dead_end_choices = info.total - 1 - len(portal_assignment[dungeon])
|
||||||
for i in range(0, dead_end_choices):
|
for i in range(0, dead_end_choices):
|
||||||
candidates = find_portal_candidates(master_door_list, dungeon, custom, allowed, dead_end_allowed=True,
|
candidates = find_portal_candidates(master_door_list, dungeon, custom, allowed, dead_end_allowed=True,
|
||||||
bk_shuffle=bk_shuffle, rupee_bow=rupee_bow_flag)
|
bk_shuffle=bk_shuffle, standard=std_flag, rupee_bow=rupee_bow_flag)
|
||||||
possible_portals = outstanding_portals if not info.sole_entrance else [x for x in outstanding_portals if x != info.sole_entrance]
|
possible_portals = outstanding_portals if not info.sole_entrance else [x for x in outstanding_portals if x != info.sole_entrance]
|
||||||
choice, portal = assign_portal(candidates, possible_portals, custom, world, player)
|
choice, portal = assign_portal(candidates, possible_portals, custom, world, player)
|
||||||
if choice.deadEnd:
|
if choice.deadEnd:
|
||||||
@@ -796,15 +796,18 @@ def main_dungeon_pool(dungeon_pool, world, player):
|
|||||||
hc = world.get_dungeon('Hyrule Castle', player)
|
hc = world.get_dungeon('Hyrule Castle', player)
|
||||||
hc_compass = ItemFactory('Compass (Escape)', player)
|
hc_compass = ItemFactory('Compass (Escape)', player)
|
||||||
hc_compass.advancement = world.restrict_boss_items[player] != 'none'
|
hc_compass.advancement = world.restrict_boss_items[player] != 'none'
|
||||||
hc.dungeon_items.append(hc_compass)
|
if hc.dungeon_items.count(hc_compass) < 1:
|
||||||
|
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_compass = ItemFactory('Compass (Agahnims Tower)', player)
|
at_compass = ItemFactory('Compass (Agahnims Tower)', player)
|
||||||
at_compass.advancement = world.restrict_boss_items[player] != 'none'
|
at_compass.advancement = world.restrict_boss_items[player] != 'none'
|
||||||
at.dungeon_items.append(at_compass)
|
if at.dungeon_items.count(at_compass) < 1:
|
||||||
|
at.dungeon_items.append(at_compass)
|
||||||
at_map = ItemFactory('Map (Agahnims Tower)', player)
|
at_map = ItemFactory('Map (Agahnims Tower)', player)
|
||||||
at_map.advancement = world.restrict_boss_items[player] != 'none'
|
at_map.advancement = world.restrict_boss_items[player] != 'none'
|
||||||
at.dungeon_items.append(at_map)
|
if at.dungeon_items.count(at_map) < 1:
|
||||||
|
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
|
||||||
@@ -1238,10 +1241,13 @@ def cross_dungeon(world, player):
|
|||||||
if world.restrict_boss_items[player] != 'none':
|
if world.restrict_boss_items[player] != 'none':
|
||||||
hc_compass.advancement = at_compass.advancement = at_map.advancement = True
|
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(hc_compass)
|
if hc.dungeon_items.count(hc_compass) < 1:
|
||||||
|
hc.dungeon_items.append(hc_compass)
|
||||||
at = world.get_dungeon('Agahnims Tower', player)
|
at = world.get_dungeon('Agahnims Tower', player)
|
||||||
at.dungeon_items.append(at_compass)
|
if at.dungeon_items.count(at_compass) < 1:
|
||||||
at.dungeon_items.append(at_map)
|
at.dungeon_items.append(at_compass)
|
||||||
|
if at.dungeon_items.count(at_map) < 1:
|
||||||
|
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)
|
||||||
|
|||||||
1
Doors.py
1
Doors.py
@@ -1521,6 +1521,7 @@ def create_doors(world, player):
|
|||||||
world.get_door("GT Bob\'s Room SE", player).passage = False
|
world.get_door("GT Bob\'s Room SE", player).passage = False
|
||||||
world.get_door('Desert Tiles 2 SE', player).bk_shuffle_req = True # key-drop note: allows this to be a portal
|
world.get_door('Desert Tiles 2 SE', player).bk_shuffle_req = True # key-drop note: allows this to be a portal
|
||||||
world.get_door('Swamp Lobby S', player).standard_restricted = True
|
world.get_door('Swamp Lobby S', player).standard_restricted = True
|
||||||
|
world.get_door('Sanctuary S', player).standard_restricted = True
|
||||||
world.get_door('PoD Mimics 2 SW', player).rupee_bow_restricted = True # bow statue
|
world.get_door('PoD Mimics 2 SW', player).rupee_bow_restricted = True # bow statue
|
||||||
# enemizer logic could get rid of the following restriction
|
# enemizer logic could get rid of the following restriction
|
||||||
world.get_door('PoD Pit Room S', player).rupee_bow_restricted = True # so mimics 1 shouldn't be required
|
world.get_door('PoD Pit Room S', player).rupee_bow_restricted = True # so mimics 1 shouldn't be required
|
||||||
|
|||||||
5
Fill.py
5
Fill.py
@@ -386,6 +386,11 @@ def distribute_items_restrictive(world, gftower_trash=False, fill_locations=None
|
|||||||
random.shuffle(fill_locations)
|
random.shuffle(fill_locations)
|
||||||
|
|
||||||
random.shuffle(world.itempool)
|
random.shuffle(world.itempool)
|
||||||
|
if world.item_pool_config.preferred:
|
||||||
|
pref = list(world.item_pool_config.preferred.keys())
|
||||||
|
pref_len = len(pref)
|
||||||
|
world.itempool.sort(key=lambda i: pref_len - pref.index((i.name, i.player))
|
||||||
|
if (i.name, i.player) in world.item_pool_config.preferred else 0)
|
||||||
progitempool = [item for item in world.itempool if item.advancement]
|
progitempool = [item for item in world.itempool if item.advancement]
|
||||||
prioitempool = [item for item in world.itempool if not item.advancement and item.priority]
|
prioitempool = [item for item in world.itempool if not item.advancement and item.priority]
|
||||||
restitempool = [item for item in world.itempool if not item.advancement and not item.priority]
|
restitempool = [item for item in world.itempool if not item.advancement and not item.priority]
|
||||||
|
|||||||
@@ -145,8 +145,8 @@ class InitialSram:
|
|||||||
'Big Key (Misery Mire)': (0x367, 0x01), 'Compass (Misery Mire)': (0x365, 0x01), 'Map (Misery Mire)': (0x369, 0x01),
|
'Big Key (Misery Mire)': (0x367, 0x01), 'Compass (Misery Mire)': (0x365, 0x01), 'Map (Misery Mire)': (0x369, 0x01),
|
||||||
'Big Key (Turtle Rock)': (0x366, 0x08), 'Compass (Turtle Rock)': (0x364, 0x08), 'Map (Turtle Rock)': (0x368, 0x08),
|
'Big Key (Turtle Rock)': (0x366, 0x08), 'Compass (Turtle Rock)': (0x364, 0x08), 'Map (Turtle Rock)': (0x368, 0x08),
|
||||||
'Big Key (Ganons Tower)': (0x366, 0x04), 'Compass (Ganons Tower)': (0x364, 0x04), 'Map (Ganons Tower)': (0x368, 0x04)}
|
'Big Key (Ganons Tower)': (0x366, 0x04), 'Compass (Ganons Tower)': (0x364, 0x04), 'Map (Ganons Tower)': (0x368, 0x04)}
|
||||||
set_or_table = {'Flippers': (0x356, 1, 0x379, 0x02),'Pegasus Boots': (0x355, 1, 0x379, 0x04),
|
set_or_table = {'Flippers': (0x356, 1, 0x379, 0x02), 'Pegasus Boots': (0x355, 1, 0x379, 0x04),
|
||||||
'Shovel': (0x34C, 1, 0x38C, 0x04), 'Ocarina': (0x34C, 3, 0x38C, 0x01),
|
'Shovel': (0x34C, 1, 0x38C, 0x04), 'Ocarina': (0x34C, 2, 0x38C, 0x02),
|
||||||
'Ocarina (Activated)': (0x34C, 3, 0x38C, 0x01),
|
'Ocarina (Activated)': (0x34C, 3, 0x38C, 0x01),
|
||||||
'Mushroom': (0x344, 1, 0x38C, 0x20 | 0x08), 'Magic Powder': (0x344, 2, 0x38C, 0x10),
|
'Mushroom': (0x344, 1, 0x38C, 0x20 | 0x08), 'Magic Powder': (0x344, 2, 0x38C, 0x10),
|
||||||
'Blue Boomerang': (0x341, 1, 0x38C, 0x80), 'Red Boomerang': (0x341, 2, 0x38C, 0x40)}
|
'Blue Boomerang': (0x341, 1, 0x38C, 0x80), 'Red Boomerang': (0x341, 2, 0x38C, 0x40)}
|
||||||
|
|||||||
2
Main.py
2
Main.py
@@ -35,7 +35,7 @@ from source.overworld.EntranceShuffle2 import link_entrances_new
|
|||||||
from source.tools.BPS import create_bps_from_data
|
from source.tools.BPS import create_bps_from_data
|
||||||
from source.classes.CustomSettings import CustomSettings
|
from source.classes.CustomSettings import CustomSettings
|
||||||
|
|
||||||
__version__ = '1.2.0.5-u'
|
__version__ = '1.2.0.7-u'
|
||||||
|
|
||||||
from source.classes.BabelFish import BabelFish
|
from source.classes.BabelFish import BabelFish
|
||||||
|
|
||||||
|
|||||||
@@ -108,6 +108,15 @@ These are now independent of retro mode and have three options: None, Random, an
|
|||||||
* Bonk Fairy (Dark)
|
* Bonk Fairy (Dark)
|
||||||
|
|
||||||
# Bug Fixes and Notes
|
# Bug Fixes and Notes
|
||||||
|
* 1.2.0.7-u
|
||||||
|
* Fix for some misery mire key logic
|
||||||
|
* Minor standard generation fix
|
||||||
|
* Fix for inactive flute start
|
||||||
|
* Settingsfile for multiworld generation support
|
||||||
|
* Fix for duped HC/AT Maps/Compasses
|
||||||
|
* 1.2.0.6-u
|
||||||
|
* Fix for light cone in Escape when entering from Dark World post-zelda
|
||||||
|
* Fix for light cone in Escape when lighting a torch with fire rod
|
||||||
* 1.2.0.5.u
|
* 1.2.0.5.u
|
||||||
* Logic fix for Sanctuary mirror (it wasn't resetting the crystal state)
|
* Logic fix for Sanctuary mirror (it wasn't resetting the crystal state)
|
||||||
* Minor bugfixes for customizer
|
* Minor bugfixes for customizer
|
||||||
|
|||||||
@@ -632,7 +632,7 @@ def do_fixed_shuffle(avail, entrance_list):
|
|||||||
rules = Restrictions()
|
rules = Restrictions()
|
||||||
rules.size = size
|
rules.size = size
|
||||||
if ('Hyrule Castle Entrance (South)' in entrances and
|
if ('Hyrule Castle Entrance (South)' in entrances and
|
||||||
avail.world.doorShuffle[avail.player] in ['basic', 'crossed']):
|
avail.world.doorShuffle[avail.player] != 'vanilla'):
|
||||||
rules.must_exit_to_lw = True
|
rules.must_exit_to_lw = True
|
||||||
if 'Inverted Ganons Tower' in entrances and not avail.world.shuffle_ganon:
|
if 'Inverted Ganons Tower' in entrances and not avail.world.shuffle_ganon:
|
||||||
rules.fixed = True
|
rules.fixed = True
|
||||||
@@ -1025,12 +1025,15 @@ def connect_custom(avail_pool, world, player):
|
|||||||
if world.customizer and world.customizer.get_entrances():
|
if world.customizer and world.customizer.get_entrances():
|
||||||
custom_entrances = world.customizer.get_entrances()
|
custom_entrances = world.customizer.get_entrances()
|
||||||
player_key = player
|
player_key = player
|
||||||
for ent_name, exit_name in custom_entrances[player_key]['two-way'].items():
|
if 'two-way' in custom_entrances[player_key]:
|
||||||
connect_two_way(ent_name, exit_name, avail_pool)
|
for ent_name, exit_name in custom_entrances[player_key]['two-way'].items():
|
||||||
for ent_name, exit_name in custom_entrances[player_key]['entrances'].items():
|
connect_two_way(ent_name, exit_name, avail_pool)
|
||||||
connect_entrance(ent_name, exit_name, avail_pool)
|
if 'entrances' in custom_entrances[player_key]:
|
||||||
for ent_name, exit_name in custom_entrances[player_key]['exits'].items():
|
for ent_name, exit_name in custom_entrances[player_key]['entrances'].items():
|
||||||
connect_exit(exit_name, ent_name, avail_pool)
|
connect_entrance(ent_name, exit_name, avail_pool)
|
||||||
|
if 'exits' in custom_entrances[player_key]:
|
||||||
|
for ent_name, exit_name in custom_entrances[player_key]['exits'].items():
|
||||||
|
connect_exit(exit_name, ent_name, avail_pool)
|
||||||
|
|
||||||
|
|
||||||
def connect_simple(world, exit_name, region_name, player):
|
def connect_simple(world, exit_name, region_name, player):
|
||||||
|
|||||||
Reference in New Issue
Block a user