Merged in DR v1.2.0.18
This commit is contained in:
@@ -1963,7 +1963,7 @@ def shuffle_big_key_doors(door_type_pools, used_doors, start_regions_map, all_cu
|
|||||||
if flex_map[dungeon] > 0:
|
if flex_map[dungeon] > 0:
|
||||||
queue.append(dungeon)
|
queue.append(dungeon)
|
||||||
# time to re-assign
|
# time to re-assign
|
||||||
reassign_big_key_doors(bk_map, world, player)
|
reassign_big_key_doors(bk_map, used_doors, world, player)
|
||||||
for name, big_list in bk_map.items():
|
for name, big_list in bk_map.items():
|
||||||
used_doors.update(flatten_pair_list(big_list))
|
used_doors.update(flatten_pair_list(big_list))
|
||||||
return used_doors
|
return used_doors
|
||||||
@@ -2048,7 +2048,7 @@ def shuffle_small_key_doors(door_type_pools, used_doors, start_regions_map, all_
|
|||||||
else:
|
else:
|
||||||
builder.key_doors_num -= 1
|
builder.key_doors_num -= 1
|
||||||
# time to re-assign
|
# time to re-assign
|
||||||
reassign_key_doors(small_map, world, player)
|
reassign_key_doors(small_map, used_doors, world, player)
|
||||||
for dungeon_name in pool:
|
for dungeon_name in pool:
|
||||||
if world.keyshuffle[player] != 'universal':
|
if world.keyshuffle[player] != 'universal':
|
||||||
builder = world.dungeon_layouts[player][dungeon_name]
|
builder = world.dungeon_layouts[player][dungeon_name]
|
||||||
@@ -2130,7 +2130,7 @@ def shuffle_bomb_dash_doors(door_type_pools, used_doors, start_regions_map, all_
|
|||||||
suggestion_map[dungeon] = pair
|
suggestion_map[dungeon] = pair
|
||||||
queue.append(dungeon)
|
queue.append(dungeon)
|
||||||
# time to re-assign
|
# time to re-assign
|
||||||
reassign_bd_doors(bd_map, world, player)
|
reassign_bd_doors(bd_map, used_doors, world, player)
|
||||||
for name, pair in bd_map.items():
|
for name, pair in bd_map.items():
|
||||||
used_doors.update(flatten_pair_list(pair[0]))
|
used_doors.update(flatten_pair_list(pair[0]))
|
||||||
used_doors.update(flatten_pair_list(pair[1]))
|
used_doors.update(flatten_pair_list(pair[1]))
|
||||||
@@ -2540,7 +2540,7 @@ def find_current_bk_doors(builder):
|
|||||||
return current_doors
|
return current_doors
|
||||||
|
|
||||||
|
|
||||||
def reassign_big_key_doors(bk_map, world, player):
|
def reassign_big_key_doors(bk_map, used_doors, world, player):
|
||||||
logger = logging.getLogger('')
|
logger = logging.getLogger('')
|
||||||
for name, big_doors in bk_map.items():
|
for name, big_doors in bk_map.items():
|
||||||
flat_proposal = flatten_pair_list(big_doors)
|
flat_proposal = flatten_pair_list(big_doors)
|
||||||
@@ -2548,11 +2548,12 @@ def reassign_big_key_doors(bk_map, world, player):
|
|||||||
queue = deque(find_current_bk_doors(builder))
|
queue = deque(find_current_bk_doors(builder))
|
||||||
while len(queue) > 0:
|
while len(queue) > 0:
|
||||||
d = queue.pop()
|
d = queue.pop()
|
||||||
if d.type is DoorType.Interior and d not in flat_proposal and d.dest not in flat_proposal:
|
if (d.type is DoorType.Interior and d not in flat_proposal and d.dest not in flat_proposal
|
||||||
|
and d not in used_doors and d.dest not in used_doors):
|
||||||
if not d.entranceFlag:
|
if not d.entranceFlag:
|
||||||
world.get_room(d.roomIndex, player).change(d.doorListPos, DoorKind.Normal)
|
world.get_room(d.roomIndex, player).change(d.doorListPos, DoorKind.Normal)
|
||||||
d.bigKey = False
|
d.bigKey = False
|
||||||
elif d.type is DoorType.Normal and d not in flat_proposal:
|
elif d.type is DoorType.Normal and d not in flat_proposal and d not in used_doors:
|
||||||
if not d.entranceFlag:
|
if not d.entranceFlag:
|
||||||
world.get_room(d.roomIndex, player).change(d.doorListPos, DoorKind.Normal)
|
world.get_room(d.roomIndex, player).change(d.doorListPos, DoorKind.Normal)
|
||||||
d.bigKey = False
|
d.bigKey = False
|
||||||
@@ -2796,7 +2797,7 @@ def find_valid_bd_combination(builder, suggested, world, player):
|
|||||||
return bomb_proposal, dash_proposal, ttl_needed
|
return bomb_proposal, dash_proposal, ttl_needed
|
||||||
|
|
||||||
|
|
||||||
def reassign_bd_doors(bd_map, world, player):
|
def reassign_bd_doors(bd_map, used_doors, world, player):
|
||||||
for name, pair in bd_map.items():
|
for name, pair in bd_map.items():
|
||||||
flat_bomb_proposal = flatten_pair_list(pair[0])
|
flat_bomb_proposal = flatten_pair_list(pair[0])
|
||||||
flat_dash_proposal = flatten_pair_list(pair[1])
|
flat_dash_proposal = flatten_pair_list(pair[1])
|
||||||
@@ -2809,10 +2810,10 @@ def reassign_bd_doors(bd_map, world, player):
|
|||||||
queue = deque(find_current_bd_doors(builder, world))
|
queue = deque(find_current_bd_doors(builder, world))
|
||||||
while len(queue) > 0:
|
while len(queue) > 0:
|
||||||
d = queue.pop()
|
d = queue.pop()
|
||||||
if d.type is DoorType.Interior and not_in_proposal(d):
|
if d.type is DoorType.Interior and not_in_proposal(d) and d not in used_doors and d.dest not in used_doors:
|
||||||
if not d.entranceFlag:
|
if not d.entranceFlag:
|
||||||
world.get_room(d.roomIndex, player).change(d.doorListPos, DoorKind.Normal)
|
world.get_room(d.roomIndex, player).change(d.doorListPos, DoorKind.Normal)
|
||||||
elif d.type is DoorType.Normal and not_in_proposal(d):
|
elif d.type is DoorType.Normal and not_in_proposal(d) and d not in used_doors:
|
||||||
if not d.entranceFlag:
|
if not d.entranceFlag:
|
||||||
world.get_room(d.roomIndex, player).change(d.doorListPos, DoorKind.Normal)
|
world.get_room(d.roomIndex, player).change(d.doorListPos, DoorKind.Normal)
|
||||||
do_bombable_dashable(pair[0], DoorKind.Bombable, world, player)
|
do_bombable_dashable(pair[0], DoorKind.Bombable, world, player)
|
||||||
@@ -3004,7 +3005,7 @@ def valid_key_door_pair(door1, door2):
|
|||||||
return len(door1.entrance.parent_region.exits) <= 1 or len(door2.entrance.parent_region.exits) <= 1
|
return len(door1.entrance.parent_region.exits) <= 1 or len(door2.entrance.parent_region.exits) <= 1
|
||||||
|
|
||||||
|
|
||||||
def reassign_key_doors(small_map, world, player):
|
def reassign_key_doors(small_map, used_doors, world, player):
|
||||||
logger = logging.getLogger('')
|
logger = logging.getLogger('')
|
||||||
for name, small_doors in small_map.items():
|
for name, small_doors in small_map.items():
|
||||||
logger.debug(f'Key doors for {name}')
|
logger.debug(f'Key doors for {name}')
|
||||||
@@ -3014,7 +3015,7 @@ def reassign_key_doors(small_map, world, player):
|
|||||||
queue = deque(find_current_key_doors(builder))
|
queue = deque(find_current_key_doors(builder))
|
||||||
while len(queue) > 0:
|
while len(queue) > 0:
|
||||||
d = queue.pop()
|
d = queue.pop()
|
||||||
if d.type is DoorType.SpiralStairs and d not in proposal:
|
if d.type is DoorType.SpiralStairs and d not in proposal and d not in used_doors:
|
||||||
room = world.get_room(d.roomIndex, player)
|
room = world.get_room(d.roomIndex, player)
|
||||||
if room.doorList[d.doorListPos][1] == DoorKind.StairKeyLow:
|
if room.doorList[d.doorListPos][1] == DoorKind.StairKeyLow:
|
||||||
room.delete(d.doorListPos)
|
room.delete(d.doorListPos)
|
||||||
@@ -3024,13 +3025,14 @@ def reassign_key_doors(small_map, world, player):
|
|||||||
else:
|
else:
|
||||||
room.delete(d.doorListPos)
|
room.delete(d.doorListPos)
|
||||||
d.smallKey = False
|
d.smallKey = False
|
||||||
elif d.type is DoorType.Interior and d not in flat_proposal and d.dest not in flat_proposal:
|
elif (d.type is DoorType.Interior and d not in flat_proposal and d.dest not in flat_proposal
|
||||||
|
and d not in used_doors and d.dest not in used_doors):
|
||||||
if not d.entranceFlag:
|
if not d.entranceFlag:
|
||||||
world.get_room(d.roomIndex, player).change(d.doorListPos, DoorKind.Normal)
|
world.get_room(d.roomIndex, player).change(d.doorListPos, DoorKind.Normal)
|
||||||
d.smallKey = False
|
d.smallKey = False
|
||||||
d.dest.smallKey = False
|
d.dest.smallKey = False
|
||||||
queue.remove(d.dest)
|
queue.remove(d.dest)
|
||||||
elif d.type is DoorType.Normal and d not in flat_proposal:
|
elif d.type is DoorType.Normal and d not in flat_proposal and d not in used_doors:
|
||||||
if not d.entranceFlag:
|
if not d.entranceFlag:
|
||||||
world.get_room(d.roomIndex, player).change(d.doorListPos, DoorKind.Normal)
|
world.get_room(d.roomIndex, player).change(d.doorListPos, DoorKind.Normal)
|
||||||
d.smallKey = False
|
d.smallKey = False
|
||||||
|
|||||||
40
ItemList.py
40
ItemList.py
@@ -1487,7 +1487,8 @@ def make_customizer_pool(world, player):
|
|||||||
bow_found = next((i for i in pool if i in {'Bow', 'Progressive Bow'}), None)
|
bow_found = next((i for i in pool if i in {'Bow', 'Progressive Bow'}), None)
|
||||||
if not bow_found:
|
if not bow_found:
|
||||||
missing_items.append('Progressive Bow')
|
missing_items.append('Progressive Bow')
|
||||||
logging.getLogger('').warning(f'The following items are not in the custom item pool {", ".join(missing_items)}')
|
if missing_items:
|
||||||
|
logging.getLogger('').warning(f'The following items are not in the custom item pool {", ".join(missing_items)}')
|
||||||
|
|
||||||
g, t = set_default_triforce(world.goal[player], world.treasure_hunt_count[player],
|
g, t = set_default_triforce(world.goal[player], world.treasure_hunt_count[player],
|
||||||
world.treasure_hunt_total[player])
|
world.treasure_hunt_total[player])
|
||||||
@@ -1496,20 +1497,23 @@ def make_customizer_pool(world, player):
|
|||||||
if pieces < t:
|
if pieces < t:
|
||||||
pool.extend(['Triforce Piece'] * (t - pieces))
|
pool.extend(['Triforce Piece'] * (t - pieces))
|
||||||
|
|
||||||
if not world.customizer.get_start_inventory():
|
sphere_0 = world.customizer.get_start_inventory()
|
||||||
if world.logic[player] in ['owglitches', 'nologic']:
|
no_start_inventory = not sphere_0 or not sphere_0[player]
|
||||||
precollected_items.append('Pegasus Boots')
|
init_equip = [] if no_start_inventory else sphere_0[player]
|
||||||
if 'Pegasus Boots' in pool:
|
if (world.logic[player] in ['owglitches', 'nologic']
|
||||||
pool.remove('Pegasus Boots')
|
and (no_start_inventory or all(x != 'Pegasus Boots' for x in init_equip))):
|
||||||
pool.append('Rupees (20)')
|
precollected_items.append('Pegasus Boots')
|
||||||
if world.swords[player] == 'assured':
|
if 'Pegasus Boots' in pool:
|
||||||
precollected_items.append('Progressive Sword')
|
pool.remove('Pegasus Boots')
|
||||||
if 'Progressive Sword' in pool:
|
pool.append('Rupees (20)')
|
||||||
pool.remove('Progressive Sword')
|
if world.swords[player] == 'assured' and (no_start_inventory or all(' Sword' not in x for x in init_equip)):
|
||||||
pool.append('Rupees (50)')
|
precollected_items.append('Progressive Sword')
|
||||||
elif 'Fighter Sword' in pool:
|
if 'Progressive Sword' in pool:
|
||||||
pool.remove('Fighter Sword')
|
pool.remove('Progressive Sword')
|
||||||
pool.append('Rupees (50)')
|
pool.append('Rupees (50)')
|
||||||
|
elif 'Fighter Sword' in pool:
|
||||||
|
pool.remove('Fighter Sword')
|
||||||
|
pool.append('Rupees (50)')
|
||||||
|
|
||||||
return pool, placed_items, precollected_items, clock_mode, 1
|
return pool, placed_items, precollected_items, clock_mode, 1
|
||||||
|
|
||||||
@@ -1578,10 +1582,13 @@ def fill_specific_items(world):
|
|||||||
dungeon_pool, prize_set, prize_pool)
|
dungeon_pool, prize_set, prize_pool)
|
||||||
if item_to_place:
|
if item_to_place:
|
||||||
world.push_item(loc, item_to_place, False)
|
world.push_item(loc, item_to_place, False)
|
||||||
|
loc.locked = True
|
||||||
track_outside_keys(item_to_place, loc, world)
|
track_outside_keys(item_to_place, loc, world)
|
||||||
track_dungeon_items(item_to_place, loc, world)
|
track_dungeon_items(item_to_place, loc, world)
|
||||||
loc.event = (event_flag or item_to_place.advancement
|
loc.event = (event_flag or item_to_place.advancement
|
||||||
or item_to_place.bigkey or item_to_place.smallkey)
|
or item_to_place.bigkey or item_to_place.smallkey)
|
||||||
|
else:
|
||||||
|
raise Exception(f'Did not find "{item}" in item pool to place at "{location}"')
|
||||||
advanced_placements = world.customizer.get_advanced_placements()
|
advanced_placements = world.customizer.get_advanced_placements()
|
||||||
if advanced_placements:
|
if advanced_placements:
|
||||||
for player, placement_list in advanced_placements.items():
|
for player, placement_list in advanced_placements.items():
|
||||||
@@ -1591,7 +1598,7 @@ def fill_specific_items(world):
|
|||||||
item_to_place, event_flag = get_item_and_event_flag(item, world, player,
|
item_to_place, event_flag = get_item_and_event_flag(item, world, player,
|
||||||
dungeon_pool, prize_set, prize_pool)
|
dungeon_pool, prize_set, prize_pool)
|
||||||
if not item_to_place:
|
if not item_to_place:
|
||||||
continue
|
raise Exception(f'Did not find "{item}" in item pool to place for a LocationGroup"')
|
||||||
locations = placement['locations']
|
locations = placement['locations']
|
||||||
handled = False
|
handled = False
|
||||||
while not handled:
|
while not handled:
|
||||||
@@ -1611,6 +1618,7 @@ def fill_specific_items(world):
|
|||||||
if loc.item:
|
if loc.item:
|
||||||
continue
|
continue
|
||||||
world.push_item(loc, item_to_place, False)
|
world.push_item(loc, item_to_place, False)
|
||||||
|
loc.locked = True
|
||||||
track_outside_keys(item_to_place, loc, world)
|
track_outside_keys(item_to_place, loc, world)
|
||||||
track_dungeon_items(item_to_place, loc, world)
|
track_dungeon_items(item_to_place, loc, world)
|
||||||
loc.event = (event_flag or item_to_place.advancement
|
loc.event = (event_flag or item_to_place.advancement
|
||||||
|
|||||||
6
Main.py
6
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_number = '1.2.0.17'
|
version_number = '1.2.0.18'
|
||||||
version_branch = '-u'
|
version_branch = '-u'
|
||||||
__version__ = f'{version_number}{version_branch}'
|
__version__ = f'{version_number}{version_branch}'
|
||||||
|
|
||||||
@@ -814,7 +814,9 @@ def create_playthrough(world):
|
|||||||
|
|
||||||
logging.getLogger('').debug(world.fish.translate("cli", "cli", "building.calculating.spheres"), len(collection_spheres), len(sphere), len(prog_locations))
|
logging.getLogger('').debug(world.fish.translate("cli", "cli", "building.calculating.spheres"), len(collection_spheres), len(sphere), len(prog_locations))
|
||||||
if not sphere:
|
if not sphere:
|
||||||
logging.getLogger('').error(world.fish.translate("cli", "cli", "cannot.reach.items"), [world.fish.translate("cli","cli","cannot.reach.item") % (location.item.name, location.item.player, location.name, location.player) for location in sphere_candidates])
|
if world.accessibility[location.item.player] != 'none':
|
||||||
|
logging.getLogger('').error(world.fish.translate("cli", "cli", "cannot.reach.items"),
|
||||||
|
[world.fish.translate("cli","cli","cannot.reach.item") % (location.item.name, location.item.player, location.name, location.player) for location in sphere_candidates])
|
||||||
if any([location.name not in optional_locations and world.accessibility[location.item.player] != 'none' for location in sphere_candidates]):
|
if any([location.name not in optional_locations and world.accessibility[location.item.player] != 'none' for location in sphere_candidates]):
|
||||||
raise RuntimeError(world.fish.translate("cli", "cli", "cannot.reach.progression"))
|
raise RuntimeError(world.fish.translate("cli", "cli", "cannot.reach.progression"))
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ Please see [Customizer documentation](docs/Customizer.md) on how to create custo
|
|||||||
|
|
||||||
## New Goals
|
## New Goals
|
||||||
|
|
||||||
### Triforce Hunt + Ganon
|
### Ganonhunt
|
||||||
Collect the requisite triforce pieces, then defeat Ganon. (Aga2 not required). Use `ganonhunt` on CLI
|
Collect the requisite triforce pieces, then defeat Ganon. (Aga2 not required). Use `ganonhunt` on CLI
|
||||||
|
|
||||||
### Completionist
|
### Completionist
|
||||||
@@ -109,6 +109,16 @@ These are now independent of retro mode and have three options: None, Random, an
|
|||||||
|
|
||||||
# Bug Fixes and Notes
|
# Bug Fixes and Notes
|
||||||
|
|
||||||
|
* 1.2.0.18u
|
||||||
|
* Fixed an issue with pyramid hole being in logic when it is not opened.
|
||||||
|
* Crystal cutscene at GT use new symmetrical layouts (thanks Codemann)
|
||||||
|
* Fix for Hera Boss music (thanks Codemann)
|
||||||
|
* Fixed an issue where certain vanilla door types would not allow other types to be placed.
|
||||||
|
* Customizer: fixed an issue where last ditch placements would move customized items. Those are now locked and the generation will fail instead is no alternative are found.
|
||||||
|
* Customizer: fixed an issue with assured sword and start_inventory
|
||||||
|
* Customizer: warns when trying to specifically place an item that's not in the item pool
|
||||||
|
* Fixed "accessibility: none" displaying a spoiling message
|
||||||
|
* Fixed warning message about custom item pool when it is fine
|
||||||
* 1.2.0.17u
|
* 1.2.0.17u
|
||||||
* Fixed logic bug that allowed Pearl to be behind Graveyard Cave or King's Tomb entrances with only Mirror and West Dark World access (cross world shuffles only)
|
* Fixed logic bug that allowed Pearl to be behind Graveyard Cave or King's Tomb entrances with only Mirror and West Dark World access (cross world shuffles only)
|
||||||
* Removed backup locations for Dungeon Only and Major Only algorithms. If item cannot be placed in the appropriate location, the seed will fail to generate instead
|
* Removed backup locations for Dungeon Only and Major Only algorithms. If item cannot be placed in the appropriate location, the seed will fail to generate instead
|
||||||
|
|||||||
@@ -269,7 +269,7 @@
|
|||||||
"randomizer.item.goal.triforcehunt": "Triforce Hunt",
|
"randomizer.item.goal.triforcehunt": "Triforce Hunt",
|
||||||
"randomizer.item.goal.trinity": "Trinity",
|
"randomizer.item.goal.trinity": "Trinity",
|
||||||
"randomizer.item.goal.crystals": "Crystals",
|
"randomizer.item.goal.crystals": "Crystals",
|
||||||
"randomizer.item.goal.ganonhunt": "Triforce Hunt + Ganon",
|
"randomizer.item.goal.ganonhunt": "Ganonhunt",
|
||||||
"randomizer.item.goal.completionist": "Completionist",
|
"randomizer.item.goal.completionist": "Completionist",
|
||||||
|
|
||||||
"randomizer.item.crystals_gt": "Crystals to open GT",
|
"randomizer.item.crystals_gt": "Crystals to open GT",
|
||||||
|
|||||||
Reference in New Issue
Block a user