Merged in DR v1.2.0.9
This commit is contained in:
@@ -129,7 +129,7 @@ def link_doors_prep(world, player):
|
|||||||
vanilla_key_logic(world, player)
|
vanilla_key_logic(world, player)
|
||||||
|
|
||||||
|
|
||||||
def link_doors_main(world, player):
|
def create_dungeon_pool(world, player):
|
||||||
pool = None
|
pool = None
|
||||||
if world.doorShuffle[player] == 'basic':
|
if world.doorShuffle[player] == 'basic':
|
||||||
pool = [([name], regions) for name, regions in dungeon_regions.items()]
|
pool = [([name], regions) for name, regions in dungeon_regions.items()]
|
||||||
@@ -143,6 +143,11 @@ def link_doors_main(world, player):
|
|||||||
elif world.doorShuffle[player] != 'vanilla':
|
elif world.doorShuffle[player] != 'vanilla':
|
||||||
logging.getLogger('').error('Invalid door shuffle setting: %s' % world.doorShuffle[player])
|
logging.getLogger('').error('Invalid door shuffle setting: %s' % world.doorShuffle[player])
|
||||||
raise Exception('Invalid door shuffle setting: %s' % world.doorShuffle[player])
|
raise Exception('Invalid door shuffle setting: %s' % world.doorShuffle[player])
|
||||||
|
return pool
|
||||||
|
|
||||||
|
|
||||||
|
def link_doors_main(world, player):
|
||||||
|
pool = create_dungeon_pool(world, player)
|
||||||
if pool:
|
if pool:
|
||||||
main_dungeon_pool(pool, world, player)
|
main_dungeon_pool(pool, world, player)
|
||||||
if world.doorShuffle[player] != 'vanilla':
|
if world.doorShuffle[player] != 'vanilla':
|
||||||
@@ -558,7 +563,9 @@ def customizer_portals(master_door_list, world, player):
|
|||||||
custom_doors = world.customizer.get_doors()[player]
|
custom_doors = world.customizer.get_doors()[player]
|
||||||
if custom_doors and 'lobbies' in custom_doors:
|
if custom_doors and 'lobbies' in custom_doors:
|
||||||
for portal, assigned_door in custom_doors['lobbies'].items():
|
for portal, assigned_door in custom_doors['lobbies'].items():
|
||||||
door = next(x for x in master_door_list if x.name == assigned_door)
|
door = next((x for x in master_door_list if x.name == assigned_door), None)
|
||||||
|
if door is None:
|
||||||
|
raise Exception(f'{assigned_door} not found. Check for typos')
|
||||||
custom_portals[portal] = door
|
custom_portals[portal] = door
|
||||||
assigned_doors.add(door)
|
assigned_doors.add(door)
|
||||||
if custom_doors and 'doors' in custom_doors:
|
if custom_doors and 'doors' in custom_doors:
|
||||||
@@ -571,6 +578,24 @@ def customizer_portals(master_door_list, world, player):
|
|||||||
elif 'dest' in dest:
|
elif 'dest' in dest:
|
||||||
door = world.get_door(dest['dest'], player)
|
door = world.get_door(dest['dest'], player)
|
||||||
assigned_doors.add(door)
|
assigned_doors.add(door)
|
||||||
|
# restricts connected doors to the customized portals
|
||||||
|
if assigned_doors:
|
||||||
|
pool = create_dungeon_pool(world, player)
|
||||||
|
if pool:
|
||||||
|
pool_map = {}
|
||||||
|
for pool, region_list in pool:
|
||||||
|
sector_pool = convert_to_sectors(region_list, world, player)
|
||||||
|
merge_sectors(sector_pool, world, player)
|
||||||
|
for p in pool:
|
||||||
|
pool_map[p] = sector_pool
|
||||||
|
for portal, assigned_door in custom_portals.items():
|
||||||
|
portal_region = world.get_door(assigned_door, player).entrance.parent_region
|
||||||
|
portal_dungeon = world.get_region(f'{portal} Portal', player).dungeon.name
|
||||||
|
sector_pool = pool_map[portal_dungeon]
|
||||||
|
sector = next((s for s in sector_pool if portal_region in s.regions), None)
|
||||||
|
for door in sector.outstanding_doors:
|
||||||
|
if door.portalAble:
|
||||||
|
door.dungeonLink = portal_dungeon
|
||||||
return custom_portals, assigned_doors
|
return custom_portals, assigned_doors
|
||||||
|
|
||||||
|
|
||||||
@@ -1719,7 +1744,6 @@ def setup_custom_door_types(world, player):
|
|||||||
custom_doors = custom_doors[player]
|
custom_doors = custom_doors[player]
|
||||||
if 'doors' not in custom_doors:
|
if 'doors' not in custom_doors:
|
||||||
return
|
return
|
||||||
# todo: dash/bomb door pool specific
|
|
||||||
customizeable_types = ['Key Door', 'Dash Door', 'Bomb Door', 'Trap Door', 'Big Key Door']
|
customizeable_types = ['Key Door', 'Dash Door', 'Bomb Door', 'Trap Door', 'Big Key Door']
|
||||||
world.custom_door_types[player] = type_map = {x: defaultdict(list) for x in customizeable_types}
|
world.custom_door_types[player] = type_map = {x: defaultdict(list) for x in customizeable_types}
|
||||||
for door, dest in custom_doors['doors'].items():
|
for door, dest in custom_doors['doors'].items():
|
||||||
@@ -1732,7 +1756,7 @@ def setup_custom_door_types(world, player):
|
|||||||
type_map[door_kind][dungeon.name].append(d)
|
type_map[door_kind][dungeon.name].append(d)
|
||||||
else:
|
else:
|
||||||
# check if the dest is paired
|
# check if the dest is paired
|
||||||
if d.dest.type in [DoorType.Interior, DoorType.Normal] and door_kind != 'Trap Door':
|
if d.dest and d.dest.type in [DoorType.Interior, DoorType.Normal] and door_kind != 'Trap Door':
|
||||||
type_map[door_kind][dungeon.name].append((d, d.dest))
|
type_map[door_kind][dungeon.name].append((d, d.dest))
|
||||||
else:
|
else:
|
||||||
type_map[door_kind][dungeon.name].append(d)
|
type_map[door_kind][dungeon.name].append(d)
|
||||||
@@ -1784,18 +1808,24 @@ def shuffle_door_types(door_type_pools, paths, world, player):
|
|||||||
start_regions_map[name] = start_regions
|
start_regions_map[name] = start_regions
|
||||||
builder.candidates = BuilderDoorCandidates()
|
builder.candidates = BuilderDoorCandidates()
|
||||||
|
|
||||||
|
all_custom = defaultdict(list)
|
||||||
|
if player in world.custom_door_types:
|
||||||
|
for custom_dict in world.custom_door_types[player].values():
|
||||||
|
for dungeon, doors in custom_dict.items():
|
||||||
|
all_custom[dungeon].extend(doors)
|
||||||
|
|
||||||
world.paired_doors[player].clear()
|
world.paired_doors[player].clear()
|
||||||
used_doors = shuffle_trap_doors(door_type_pools, paths, start_regions_map, world, player)
|
used_doors = shuffle_trap_doors(door_type_pools, paths, start_regions_map, all_custom, world, player)
|
||||||
# big keys
|
# big keys
|
||||||
used_doors = shuffle_big_key_doors(door_type_pools, used_doors, start_regions_map, world, player)
|
used_doors = shuffle_big_key_doors(door_type_pools, used_doors, start_regions_map, all_custom, world, player)
|
||||||
# small keys
|
# small keys
|
||||||
used_doors = shuffle_small_key_doors(door_type_pools, used_doors, start_regions_map, world, player)
|
used_doors = shuffle_small_key_doors(door_type_pools, used_doors, start_regions_map, all_custom, world, player)
|
||||||
# bombable / dashable
|
# bombable / dashable
|
||||||
used_doors = shuffle_bomb_dash_doors(door_type_pools, used_doors, start_regions_map, world, player)
|
used_doors = shuffle_bomb_dash_doors(door_type_pools, used_doors, start_regions_map, all_custom, world, player)
|
||||||
# handle paired list
|
# handle paired list
|
||||||
|
|
||||||
|
|
||||||
def shuffle_trap_doors(door_type_pools, paths, start_regions_map, world, player):
|
def shuffle_trap_doors(door_type_pools, paths, start_regions_map, all_custom, world, player):
|
||||||
used_doors = set()
|
used_doors = set()
|
||||||
for pool, door_type_pool in door_type_pools:
|
for pool, door_type_pool in door_type_pools:
|
||||||
if world.trap_door_mode[player] != 'oneway':
|
if world.trap_door_mode[player] != 'oneway':
|
||||||
@@ -1806,15 +1836,14 @@ def shuffle_trap_doors(door_type_pools, paths, start_regions_map, world, player)
|
|||||||
custom_trap_doors = world.custom_door_types[player]['Trap Door']
|
custom_trap_doors = world.custom_door_types[player]['Trap Door']
|
||||||
else:
|
else:
|
||||||
custom_trap_doors = defaultdict(list)
|
custom_trap_doors = defaultdict(list)
|
||||||
|
|
||||||
for dungeon in pool:
|
for dungeon in pool:
|
||||||
builder = world.dungeon_layouts[player][dungeon]
|
builder = world.dungeon_layouts[player][dungeon]
|
||||||
if 'Mire Warping Pool' in builder.master_sector.region_set():
|
if 'Mire Warping Pool' in builder.master_sector.region_set():
|
||||||
custom_trap_doors[dungeon].append(world.get_door('Mire Warping Pool ES', player))
|
custom_trap_doors[dungeon].append(world.get_door('Mire Warping Pool ES', player))
|
||||||
world.custom_door_types[player]['Trap Door'] = custom_trap_doors
|
world.custom_door_types[player]['Trap Door'] = custom_trap_doors
|
||||||
find_trappable_candidates(builder, world, player)
|
find_trappable_candidates(builder, world, player)
|
||||||
if custom_trap_doors[dungeon]:
|
if all_custom[dungeon]:
|
||||||
builder.candidates.trap = filter_key_door_pool(builder.candidates.trap, custom_trap_doors[dungeon])
|
builder.candidates.trap = filter_key_door_pool(builder.candidates.trap, all_custom[dungeon])
|
||||||
remaining -= len(custom_trap_doors[dungeon])
|
remaining -= len(custom_trap_doors[dungeon])
|
||||||
ttl += len(builder.candidates.trap)
|
ttl += len(builder.candidates.trap)
|
||||||
if ttl == 0:
|
if ttl == 0:
|
||||||
@@ -1866,7 +1895,7 @@ def shuffle_trap_doors(door_type_pools, paths, start_regions_map, world, player)
|
|||||||
return used_doors
|
return used_doors
|
||||||
|
|
||||||
|
|
||||||
def shuffle_big_key_doors(door_type_pools, used_doors, start_regions_map, world, player):
|
def shuffle_big_key_doors(door_type_pools, used_doors, start_regions_map, all_custom, world, player):
|
||||||
for pool, door_type_pool in door_type_pools:
|
for pool, door_type_pool in door_type_pools:
|
||||||
ttl = 0
|
ttl = 0
|
||||||
suggestion_map, bk_map, flex_map = {}, {}, {}
|
suggestion_map, bk_map, flex_map = {}, {}, {}
|
||||||
@@ -1879,8 +1908,8 @@ def shuffle_big_key_doors(door_type_pools, used_doors, start_regions_map, world,
|
|||||||
for dungeon in pool:
|
for dungeon in pool:
|
||||||
builder = world.dungeon_layouts[player][dungeon]
|
builder = world.dungeon_layouts[player][dungeon]
|
||||||
find_big_key_candidates(builder, start_regions_map[dungeon], used_doors, world, player)
|
find_big_key_candidates(builder, start_regions_map[dungeon], used_doors, world, player)
|
||||||
if custom_bk_doors[dungeon]:
|
if all_custom[dungeon]:
|
||||||
builder.candidates.big = filter_key_door_pool(builder.candidates.big, custom_bk_doors[dungeon])
|
builder.candidates.big = filter_key_door_pool(builder.candidates.big, all_custom[dungeon])
|
||||||
remaining -= len(custom_bk_doors[dungeon])
|
remaining -= len(custom_bk_doors[dungeon])
|
||||||
ttl += len(builder.candidates.big)
|
ttl += len(builder.candidates.big)
|
||||||
if ttl == 0:
|
if ttl == 0:
|
||||||
@@ -1926,7 +1955,7 @@ def shuffle_big_key_doors(door_type_pools, used_doors, start_regions_map, world,
|
|||||||
return used_doors
|
return used_doors
|
||||||
|
|
||||||
|
|
||||||
def shuffle_small_key_doors(door_type_pools, used_doors, start_regions_map, world, player):
|
def shuffle_small_key_doors(door_type_pools, used_doors, start_regions_map, all_custom, world, player):
|
||||||
max_computation = 11 # this is around 6 billion worse case factorial don't want to exceed this much
|
max_computation = 11 # this is around 6 billion worse case factorial don't want to exceed this much
|
||||||
for pool, door_type_pool in door_type_pools:
|
for pool, door_type_pool in door_type_pools:
|
||||||
ttl = 0
|
ttl = 0
|
||||||
@@ -1944,8 +1973,8 @@ def shuffle_small_key_doors(door_type_pools, used_doors, start_regions_map, worl
|
|||||||
builder.total_keys = total_keys
|
builder.total_keys = total_keys
|
||||||
find_small_key_door_candidates(builder, start_regions_map[dungeon], used_doors, world, player)
|
find_small_key_door_candidates(builder, start_regions_map[dungeon], used_doors, world, player)
|
||||||
custom_doors = 0
|
custom_doors = 0
|
||||||
if custom_key_doors[dungeon]:
|
if all_custom[dungeon]:
|
||||||
builder.candidates.small = filter_key_door_pool(builder.candidates.small, custom_key_doors[dungeon])
|
builder.candidates.small = filter_key_door_pool(builder.candidates.small, all_custom[dungeon])
|
||||||
custom_doors = len(custom_key_doors[dungeon])
|
custom_doors = len(custom_key_doors[dungeon])
|
||||||
remaining -= custom_doors
|
remaining -= custom_doors
|
||||||
builder.key_doors_num = max(0, len(builder.candidates.small) - builder.key_drop_cnt) + custom_doors
|
builder.key_doors_num = max(0, len(builder.candidates.small) - builder.key_drop_cnt) + custom_doors
|
||||||
@@ -1961,13 +1990,10 @@ def shuffle_small_key_doors(door_type_pools, used_doors, start_regions_map, worl
|
|||||||
suggested = min(calculated, limit)
|
suggested = min(calculated, limit)
|
||||||
key_door_num = min(suggested + builder.key_drop_cnt, max_computation)
|
key_door_num = min(suggested + builder.key_drop_cnt, max_computation)
|
||||||
combo_size = ncr(len(builder.candidates.small), key_door_num)
|
combo_size = ncr(len(builder.candidates.small), key_door_num)
|
||||||
while combo_size > 500000 and suggested > 0:
|
|
||||||
suggested -= 1
|
|
||||||
combo_size = ncr(len(builder.candidates.small), key_door_num)
|
|
||||||
suggestion_map[dungeon] = builder.key_doors_num = key_door_num
|
suggestion_map[dungeon] = builder.key_doors_num = key_door_num
|
||||||
remaining -= suggested + builder.key_drop_cnt
|
remaining -= key_door_num + builder.key_drop_cnt
|
||||||
builder.combo_size = combo_size
|
builder.combo_size = combo_size
|
||||||
flex_map[dungeon] = (limit - suggested) if suggested < limit else 0
|
flex_map[dungeon] = (limit - key_door_num) if key_door_num < limit else 0
|
||||||
for dungeon in pool:
|
for dungeon in pool:
|
||||||
builder = world.dungeon_layouts[player][dungeon]
|
builder = world.dungeon_layouts[player][dungeon]
|
||||||
if total_adjustable:
|
if total_adjustable:
|
||||||
@@ -2026,7 +2052,7 @@ def shuffle_small_key_doors(door_type_pools, used_doors, start_regions_map, worl
|
|||||||
return used_doors
|
return used_doors
|
||||||
|
|
||||||
|
|
||||||
def shuffle_bomb_dash_doors(door_type_pools, used_doors, start_regions_map, world, player):
|
def shuffle_bomb_dash_doors(door_type_pools, used_doors, start_regions_map, all_custom, world, player):
|
||||||
for pool, door_type_pool in door_type_pools:
|
for pool, door_type_pool in door_type_pools:
|
||||||
ttl = 0
|
ttl = 0
|
||||||
suggestion_map, bd_map = {}, {}
|
suggestion_map, bd_map = {}, {}
|
||||||
@@ -2043,11 +2069,9 @@ def shuffle_bomb_dash_doors(door_type_pools, used_doors, start_regions_map, worl
|
|||||||
for dungeon in pool:
|
for dungeon in pool:
|
||||||
builder = world.dungeon_layouts[player][dungeon]
|
builder = world.dungeon_layouts[player][dungeon]
|
||||||
find_bd_candidates(builder, start_regions_map[dungeon], used_doors, world, player)
|
find_bd_candidates(builder, start_regions_map[dungeon], used_doors, world, player)
|
||||||
if custom_bomb_doors[dungeon]:
|
if all_custom[dungeon]:
|
||||||
builder.candidates.bomb_dash = filter_key_door_pool(builder.candidates.bomb_dash, custom_bomb_doors[dungeon])
|
builder.candidates.bomb_dash = filter_key_door_pool(builder.candidates.bomb_dash, all_custom[dungeon])
|
||||||
remaining_bomb -= len(custom_bomb_doors[dungeon])
|
remaining_bomb -= len(custom_bomb_doors[dungeon])
|
||||||
if custom_dash_doors[dungeon]:
|
|
||||||
builder.candidates.bomb_dash = filter_key_door_pool(builder.candidates.bomb_dash, custom_dash_doors[dungeon])
|
|
||||||
remaining_dash -= len(custom_dash_doors[dungeon])
|
remaining_dash -= len(custom_dash_doors[dungeon])
|
||||||
ttl += len(builder.candidates.bomb_dash)
|
ttl += len(builder.candidates.bomb_dash)
|
||||||
if ttl == 0:
|
if ttl == 0:
|
||||||
|
|||||||
2
Doors.py
2
Doors.py
@@ -66,7 +66,7 @@ def create_doors(world, player):
|
|||||||
create_door(player, 'Hyrule Castle Back Hall Down Stairs', Sprl).dir(Dn, 0x01, 0, HTL).ss(A, 0x2a, 0x00),
|
create_door(player, 'Hyrule Castle Back Hall Down Stairs', Sprl).dir(Dn, 0x01, 0, HTL).ss(A, 0x2a, 0x00),
|
||||||
create_door(player, 'Hyrule Castle Throne Room Tapestry', Lgcl),
|
create_door(player, 'Hyrule Castle Throne Room Tapestry', Lgcl),
|
||||||
create_door(player, 'Hyrule Castle Tapestry Backwards', Lgcl),
|
create_door(player, 'Hyrule Castle Tapestry Backwards', Lgcl),
|
||||||
create_door(player, 'Hyrule Castle Throne Room N', Nrml).dir(No, 0x51, Mid, High).pos(1),
|
create_door(player, 'Hyrule Castle Throne Room N', Nrml).dir(No, 0x51, Mid, High).pos(0),
|
||||||
create_door(player, 'Hyrule Castle Throne Room South Stairs', StrS).dir(So, 0x51, Mid, Low),
|
create_door(player, 'Hyrule Castle Throne Room South Stairs', StrS).dir(So, 0x51, Mid, Low),
|
||||||
|
|
||||||
# hyrule dungeon level
|
# hyrule dungeon level
|
||||||
|
|||||||
@@ -1824,6 +1824,7 @@ def ensure_crystal_switches_reachable(dungeon_map, crystal_switches, polarized_s
|
|||||||
for name, builder in dungeon_map.items():
|
for name, builder in dungeon_map.items():
|
||||||
if builder.c_switch_present and builder.c_switch_required and not builder.c_locked:
|
if builder.c_switch_present and builder.c_switch_required and not builder.c_locked:
|
||||||
invalid_builders.append(builder)
|
invalid_builders.append(builder)
|
||||||
|
random.shuffle(invalid_builders)
|
||||||
while len(invalid_builders) > 0:
|
while len(invalid_builders) > 0:
|
||||||
valid_builders = []
|
valid_builders = []
|
||||||
for builder in invalid_builders:
|
for builder in invalid_builders:
|
||||||
@@ -1849,6 +1850,7 @@ def ensure_crystal_switches_reachable(dungeon_map, crystal_switches, polarized_s
|
|||||||
if eq.c_switch:
|
if eq.c_switch:
|
||||||
reachable_crystals[hook_from_door(eq.door)] = True
|
reachable_crystals[hook_from_door(eq.door)] = True
|
||||||
valid_ent_sectors = []
|
valid_ent_sectors = []
|
||||||
|
random.shuffle(entrance_sectors)
|
||||||
for entrance_sector in entrance_sectors:
|
for entrance_sector in entrance_sectors:
|
||||||
other_sectors = [x for x in builder.sectors if x != entrance_sector]
|
other_sectors = [x for x in builder.sectors if x != entrance_sector]
|
||||||
reachable, access = is_c_switch_reachable(entrance_sector, reachable_crystals, other_sectors)
|
reachable, access = is_c_switch_reachable(entrance_sector, reachable_crystals, other_sectors)
|
||||||
@@ -1866,7 +1868,12 @@ def ensure_crystal_switches_reachable(dungeon_map, crystal_switches, polarized_s
|
|||||||
while not valid:
|
while not valid:
|
||||||
if len(candidates) <= 0:
|
if len(candidates) <= 0:
|
||||||
raise GenerationException(f'need to provide more sophisticated crystal connection for {entrance_sector}')
|
raise GenerationException(f'need to provide more sophisticated crystal connection for {entrance_sector}')
|
||||||
sector, which_list = random.choice(list(candidates.items()))
|
# prioritize candidates
|
||||||
|
if any(x == 'Crystals' for x in candidates.values()):
|
||||||
|
cand_list = [x for x in candidates.items() if x[1] == 'Crystals']
|
||||||
|
else:
|
||||||
|
cand_list = list(candidates.items())
|
||||||
|
sector, which_list = random.choice(cand_list)
|
||||||
del candidates[sector]
|
del candidates[sector]
|
||||||
valid = global_pole.is_valid_choice(dungeon_map, builder, [sector])
|
valid = global_pole.is_valid_choice(dungeon_map, builder, [sector])
|
||||||
if which_list == 'Polarized':
|
if which_list == 'Polarized':
|
||||||
|
|||||||
2
Main.py
2
Main.py
@@ -36,7 +36,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.8-u'
|
__version__ = '1.2.0.9-u'
|
||||||
|
|
||||||
from source.classes.BabelFish import BabelFish
|
from source.classes.BabelFish import BabelFish
|
||||||
|
|
||||||
|
|||||||
@@ -108,6 +108,19 @@ 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.9-u
|
||||||
|
* Disallowed standard exits (due to ER) are now graphically half blocked instead of missing
|
||||||
|
* Graphical issues with Sanctuary and Swamp Hub lobbies are fixed
|
||||||
|
* Fixes an issue surrounding door state and decoupled doors leading to blocked doors
|
||||||
|
* Customizer improvements:
|
||||||
|
* Better logic around customized lobbies
|
||||||
|
* Better logic around customized door types
|
||||||
|
* Fix to key doors that was causing extra key doors
|
||||||
|
* Generation improvement around crystal switches
|
||||||
|
* Fix bug in dungeon_only that wasn't using pot key locations (known issue still exists in pottery modes)
|
||||||
|
* Fixes for multiworld:
|
||||||
|
* Fixes an issue when keys are found in own dungeon for another player when using the bizhawk plugin.
|
||||||
|
* Fixes an issue with absorbables for another player also being received by the player picking it up.
|
||||||
* 1.2.0.8-u
|
* 1.2.0.8-u
|
||||||
* New Features: trap_door_mode and key_logic_algorithm
|
* New Features: trap_door_mode and key_logic_algorithm
|
||||||
* Change S&Q in door shuffle + standard during escape to spawn as Uncle
|
* Change S&Q in door shuffle + standard during escape to spawn as Uncle
|
||||||
|
|||||||
4
Rom.py
4
Rom.py
@@ -38,7 +38,7 @@ from source.dungeon.RoomList import Room0127
|
|||||||
|
|
||||||
|
|
||||||
JAP10HASH = '03a63945398191337e896e5771f77173'
|
JAP10HASH = '03a63945398191337e896e5771f77173'
|
||||||
RANDOMIZERBASEHASH = '1694ba41bf6ab7086f05e914e8d08433'
|
RANDOMIZERBASEHASH = 'e9a22882bb59523c19845274d76b3761'
|
||||||
|
|
||||||
|
|
||||||
class JsonRom(object):
|
class JsonRom(object):
|
||||||
@@ -573,7 +573,7 @@ class Sprite(object):
|
|||||||
|
|
||||||
def handle_native_dungeon(location, itemid):
|
def handle_native_dungeon(location, itemid):
|
||||||
# Keys in their native dungeon should use the original item code for keys
|
# Keys in their native dungeon should use the original item code for keys
|
||||||
if location.parent_region.dungeon:
|
if location.parent_region.dungeon and location.player == location.item.player:
|
||||||
if location.parent_region.dungeon.name == location.item.dungeon:
|
if location.parent_region.dungeon.name == location.item.dungeon:
|
||||||
if location.item.bigkey:
|
if location.item.bigkey:
|
||||||
return 0x32
|
return 0x32
|
||||||
|
|||||||
@@ -244,7 +244,9 @@ def create_rooms(world, player):
|
|||||||
# Room(player, 0xff, 0x52c9a).door(Position.InteriorW, DoorKind.Bombable).door(Position.InteriorE, DoorKind.Bombable).door(Position.SouthE, DoorKind.CaveEntrance),
|
# Room(player, 0xff, 0x52c9a).door(Position.InteriorW, DoorKind.Bombable).door(Position.InteriorE, DoorKind.Bombable).door(Position.SouthE, DoorKind.CaveEntrance),
|
||||||
]
|
]
|
||||||
# fix some wonky things
|
# fix some wonky things
|
||||||
world.get_room(0x51, player).change(1, DoorKind.Normal) # fix the dungeon changer
|
# should I put back the dungeon changer for certain logic - like no logic? maybe in basic
|
||||||
|
if world.doorShuffle[player] != 'vanilla':
|
||||||
|
world.get_room(0x51, player).delete(1) # remove the dungeon changer
|
||||||
world.get_room(0x60, player).swap(2, 4) # puts the exit at pos 2 - enables pos 3
|
world.get_room(0x60, player).swap(2, 4) # puts the exit at pos 2 - enables pos 3
|
||||||
world.get_room(0x61, player).swap(1, 6) # puts the WN door at pos 1 - enables it
|
world.get_room(0x61, player).swap(1, 6) # puts the WN door at pos 1 - enables it
|
||||||
world.get_room(0x61, player).swap(5, 6) # puts the Incognito Entrance at the end, so it can be deleted
|
world.get_room(0x61, player).swap(5, 6) # puts the Incognito Entrance at the end, so it can be deleted
|
||||||
|
|||||||
@@ -608,16 +608,18 @@ OWEdgeTransition:
|
|||||||
}
|
}
|
||||||
OWSpecialExit:
|
OWSpecialExit:
|
||||||
{
|
{
|
||||||
PHY
|
LDA.l OWMode : ORA.l OWMode+1 : BEQ .vanilla
|
||||||
LDY.b #$00
|
PHY
|
||||||
LDA.w $0418 : LSR : BNE +
|
LDY.b #$00
|
||||||
LDY.w $0704 : BRA ++
|
LDA.w $0418 : LSR : BNE +
|
||||||
+
|
LDY.w $0704 : BRA ++
|
||||||
LDA.w $0704 : BNE ++
|
+
|
||||||
LDY.b #$02
|
LDA.w $0704 : BNE ++
|
||||||
++
|
LDY.b #$02
|
||||||
JSR OWWorldTerrainUpdate
|
++
|
||||||
PLY
|
JSR OWWorldTerrainUpdate
|
||||||
|
PLY
|
||||||
|
.vanilla
|
||||||
LDA.l $7EFD40,X ; what we wrote over
|
LDA.l $7EFD40,X ; what we wrote over
|
||||||
RTL
|
RTL
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
@@ -163,7 +163,7 @@ def create_item_pool_config(world):
|
|||||||
dungeon_set = (mode_grouping['Big Chests'] + mode_grouping['Dungeon Trash'] + mode_grouping['Big Keys'] +
|
dungeon_set = (mode_grouping['Big Chests'] + mode_grouping['Dungeon Trash'] + mode_grouping['Big Keys'] +
|
||||||
mode_grouping['Heart Containers'] + mode_grouping['GT Trash'] + mode_grouping['Small Keys'] +
|
mode_grouping['Heart Containers'] + mode_grouping['GT Trash'] + mode_grouping['Small Keys'] +
|
||||||
mode_grouping['Compasses'] + mode_grouping['Maps'] + mode_grouping['Key Drops'] +
|
mode_grouping['Compasses'] + mode_grouping['Maps'] + mode_grouping['Key Drops'] +
|
||||||
mode_grouping['Big Key Drops'])
|
mode_grouping['Pot Keys'] + mode_grouping['Big Key Drops'])
|
||||||
for player in range(1, world.players + 1):
|
for player in range(1, world.players + 1):
|
||||||
config.item_pool[player] = determine_major_items(world, player)
|
config.item_pool[player] = determine_major_items(world, player)
|
||||||
config.location_groups[0].locations = set(dungeon_set)
|
config.location_groups[0].locations = set(dungeon_set)
|
||||||
|
|||||||
23
test/customizer/multi_test.yaml
Normal file
23
test/customizer/multi_test.yaml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
meta:
|
||||||
|
players: 2
|
||||||
|
settings:
|
||||||
|
1:
|
||||||
|
pottery: cavekeys
|
||||||
|
keysanity: True
|
||||||
|
2:
|
||||||
|
keysanity: True
|
||||||
|
placements:
|
||||||
|
1:
|
||||||
|
Sanctuary: Small Key (Escape)#2
|
||||||
|
'Links House Pot #3': Rupees (20)#2
|
||||||
|
start_inventory:
|
||||||
|
1:
|
||||||
|
- Pegasus Boots
|
||||||
|
- Ocarina (Activated)
|
||||||
|
- Magic Mirror
|
||||||
|
- Boss Heart Container
|
||||||
|
- Boss Heart Container
|
||||||
|
- Boss Heart Container
|
||||||
|
- Boss Heart Container
|
||||||
|
- Red Mail
|
||||||
|
- Golden Sword
|
||||||
@@ -1,28 +1,46 @@
|
|||||||
meta:
|
meta:
|
||||||
players: 1
|
players: 1
|
||||||
race: true
|
algorithm: dungeon_only
|
||||||
settings:
|
settings:
|
||||||
1:
|
1:
|
||||||
shopsanity: true
|
goal: dungeons
|
||||||
pseudoboots: true
|
pseudoboots: true
|
||||||
goal: crystals
|
|
||||||
crystals_gt: random
|
|
||||||
keysanity: true
|
|
||||||
door_shuffle: crossed
|
door_shuffle: crossed
|
||||||
|
decoupledoors: true
|
||||||
intensity: 3
|
intensity: 3
|
||||||
door_type_mode: big
|
door_type_mode: all
|
||||||
pottery: keys
|
|
||||||
dropshuffle: true
|
|
||||||
experimental: true
|
experimental: true
|
||||||
dungeon_counters: 'on'
|
dungeon_counters: 'on'
|
||||||
hints: true
|
compassshuffle: true
|
||||||
msu_resume: true
|
mapshuffle: true
|
||||||
collection_rate: true
|
keydropshuffle: true
|
||||||
quickswap: true
|
doors:
|
||||||
start_inventory:
|
|
||||||
1:
|
1:
|
||||||
- Pegasus Boots
|
lobbies:
|
||||||
- Ocarina (Activated)
|
Hyrule Castle South: Thieves Lobby S
|
||||||
- Magic Mirror
|
doors:
|
||||||
- Boss Heart Container
|
Thieves Lobby NE Edge:
|
||||||
- Blue Mail
|
dest: Hyrule Castle Throne Room South Stairs
|
||||||
|
one-way: True
|
||||||
|
Hyrule Castle Throne Room South Stairs:
|
||||||
|
dest: Desert Beamos Hall NE
|
||||||
|
one-way: True
|
||||||
|
Desert Beamos Hall NE:
|
||||||
|
dest: Ice Spike Cross SE
|
||||||
|
type: Key Door
|
||||||
|
one-way: True
|
||||||
|
Ice Spike Cross SE:
|
||||||
|
dest: Thieves Lobby NE Edge
|
||||||
|
one-way: True
|
||||||
|
Hyrule Castle Throne Room N:
|
||||||
|
dest: Ice Firebar Down Ladder
|
||||||
|
type: Key Door
|
||||||
|
Swamp Lobby S:
|
||||||
|
dest: Thieves Lobby N Edge
|
||||||
|
type: Bomb Door
|
||||||
|
Thieves Lobby E: Thieves Compass Room W
|
||||||
|
Thieves Compass Room NW Edge: Ice Tall Hint SE
|
||||||
|
Thieves Compass Room N Edge: PoD Bow Statue Down Ladder
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user