Merge branch 'Ambrosia' into Bias
This commit is contained in:
@@ -14,7 +14,7 @@ from RoomData import DoorKind, PairedDoor, reset_rooms
|
|||||||
from DungeonGenerator import ExplorationState, convert_regions, generate_dungeon, pre_validate, determine_required_paths, drop_entrances
|
from DungeonGenerator import ExplorationState, convert_regions, generate_dungeon, pre_validate, determine_required_paths, drop_entrances
|
||||||
from DungeonGenerator import create_dungeon_builders, split_dungeon_builder, simple_dungeon_builder, default_dungeon_entrances
|
from DungeonGenerator import create_dungeon_builders, split_dungeon_builder, simple_dungeon_builder, default_dungeon_entrances
|
||||||
from DungeonGenerator import dungeon_portals, dungeon_drops, GenerationException
|
from DungeonGenerator import dungeon_portals, dungeon_drops, GenerationException
|
||||||
from KeyDoorShuffle import analyze_dungeon, build_key_layout, validate_key_layout
|
from KeyDoorShuffle import analyze_dungeon, build_key_layout, validate_key_layout, determine_prize_lock
|
||||||
from Utils import ncr, kth_combination
|
from Utils import ncr, kth_combination
|
||||||
|
|
||||||
|
|
||||||
@@ -1384,10 +1384,8 @@ def combine_layouts(recombinant_builders, dungeon_builders, entrances_map):
|
|||||||
if recombine.master_sector is None:
|
if recombine.master_sector is None:
|
||||||
recombine.master_sector = builder.master_sector
|
recombine.master_sector = builder.master_sector
|
||||||
recombine.master_sector.name = recombine.name
|
recombine.master_sector.name = recombine.name
|
||||||
recombine.pre_open_stonewalls = builder.pre_open_stonewalls
|
|
||||||
else:
|
else:
|
||||||
recombine.master_sector.regions.extend(builder.master_sector.regions)
|
recombine.master_sector.regions.extend(builder.master_sector.regions)
|
||||||
recombine.pre_open_stonewalls.update(builder.pre_open_stonewalls)
|
|
||||||
recombine.layout_starts = list(entrances_map[recombine.name])
|
recombine.layout_starts = list(entrances_map[recombine.name])
|
||||||
dungeon_builders[recombine.name] = recombine
|
dungeon_builders[recombine.name] = recombine
|
||||||
|
|
||||||
@@ -1491,6 +1489,7 @@ def find_valid_combination(builder, start_regions, world, player, drop_keys=True
|
|||||||
start_regions = [x for x in start_regions if x not in excluded.keys()]
|
start_regions = [x for x in start_regions if x not in excluded.keys()]
|
||||||
|
|
||||||
key_layout = build_key_layout(builder, start_regions, proposal, world, player)
|
key_layout = build_key_layout(builder, start_regions, proposal, world, player)
|
||||||
|
determine_prize_lock(key_layout, world, player)
|
||||||
while not validate_key_layout(key_layout, world, player):
|
while not validate_key_layout(key_layout, world, player):
|
||||||
itr += 1
|
itr += 1
|
||||||
stop_early = False
|
stop_early = False
|
||||||
@@ -2069,8 +2068,8 @@ class DROptions(Flag):
|
|||||||
Debug = 0x08
|
Debug = 0x08
|
||||||
# Rails = 0x10 # Unused bit now
|
# Rails = 0x10 # Unused bit now
|
||||||
OriginalPalettes = 0x20
|
OriginalPalettes = 0x20
|
||||||
Open_PoD_Wall = 0x40 # If on, pre opens the PoD wall, no bow required
|
# Open_PoD_Wall = 0x40 # No longer pre-opening pod wall - unused
|
||||||
Open_Desert_Wall = 0x80 # If on, pre opens the desert wall, no fire required
|
# Open_Desert_Wall = 0x80 # No longer pre-opening desert wall - unused
|
||||||
Hide_Total = 0x100
|
Hide_Total = 0x100
|
||||||
DarkWorld_Spawns = 0x200
|
DarkWorld_Spawns = 0x200
|
||||||
|
|
||||||
|
|||||||
@@ -56,24 +56,6 @@ def pre_validate(builder, entrance_region_names, split_dungeon, world, player):
|
|||||||
|
|
||||||
|
|
||||||
def generate_dungeon(builder, entrance_region_names, split_dungeon, world, player):
|
def generate_dungeon(builder, entrance_region_names, split_dungeon, world, player):
|
||||||
stonewalls = check_for_stonewalls(builder)
|
|
||||||
sector = generate_dungeon_main(builder, entrance_region_names, split_dungeon, world, player)
|
|
||||||
for stonewall in stonewalls:
|
|
||||||
if not stonewall_valid(stonewall):
|
|
||||||
builder.pre_open_stonewalls.add(stonewall)
|
|
||||||
return sector
|
|
||||||
|
|
||||||
|
|
||||||
def check_for_stonewalls(builder):
|
|
||||||
stonewalls = set()
|
|
||||||
for sector in builder.sectors:
|
|
||||||
for door in sector.outstanding_doors:
|
|
||||||
if door.stonewall:
|
|
||||||
stonewalls.add(door)
|
|
||||||
return stonewalls
|
|
||||||
|
|
||||||
|
|
||||||
def generate_dungeon_main(builder, entrance_region_names, split_dungeon, world, player):
|
|
||||||
if builder.valid_proposal: # we made this earlier in gen, just use it
|
if builder.valid_proposal: # we made this earlier in gen, just use it
|
||||||
proposed_map = builder.valid_proposal
|
proposed_map = builder.valid_proposal
|
||||||
else:
|
else:
|
||||||
@@ -112,6 +94,15 @@ def generate_dungeon_find_proposal(builder, entrance_region_names, split_dungeon
|
|||||||
if (access_region.name in world.inaccessible_regions[player] and
|
if (access_region.name in world.inaccessible_regions[player] and
|
||||||
region.name not in world.enabled_entrances[player]):
|
region.name not in world.enabled_entrances[player]):
|
||||||
excluded[region] = None
|
excluded[region] = None
|
||||||
|
elif len(region.entrances) == 1: # for holes
|
||||||
|
access_region = next(x.parent_region for x in region.entrances
|
||||||
|
if x.parent_region.type in [RegionType.LightWorld, RegionType.DarkWorld]
|
||||||
|
or x.parent_region.name == 'Sewer Drop')
|
||||||
|
if access_region.name == 'Sewer Drop':
|
||||||
|
access_region = next(x.parent_region for x in access_region.entrances)
|
||||||
|
if (access_region.name in world.inaccessible_regions[player] and
|
||||||
|
region.name not in world.enabled_entrances[player]):
|
||||||
|
excluded[region] = None
|
||||||
entrance_regions = [x for x in entrance_regions if x not in excluded.keys()]
|
entrance_regions = [x for x in entrance_regions if x not in excluded.keys()]
|
||||||
doors_to_connect = {}
|
doors_to_connect = {}
|
||||||
all_regions = set()
|
all_regions = set()
|
||||||
@@ -586,7 +577,8 @@ def determine_paths_for_dungeon(world, player, all_regions, name):
|
|||||||
paths.append(boss)
|
paths.append(boss)
|
||||||
if 'Thieves Boss' in all_r_names:
|
if 'Thieves Boss' in all_r_names:
|
||||||
paths.append('Thieves Boss')
|
paths.append('Thieves Boss')
|
||||||
paths.append(('Thieves Blind\'s Cell', 'Thieves Boss'))
|
if world.get_dungeon("Thieves Town", player).boss.enemizer_name == 'Blind':
|
||||||
|
paths.append(('Thieves Blind\'s Cell', 'Thieves Boss'))
|
||||||
for drop_check in drop_path_checks:
|
for drop_check in drop_path_checks:
|
||||||
if drop_check in all_r_names:
|
if drop_check in all_r_names:
|
||||||
paths.append((drop_check, non_hole_portals))
|
paths.append((drop_check, non_hole_portals))
|
||||||
@@ -612,35 +604,6 @@ def winnow_hangers(hangers, hooks):
|
|||||||
hangers[hanger].remove(door)
|
hangers[hanger].remove(door)
|
||||||
|
|
||||||
|
|
||||||
def stonewall_valid(stonewall):
|
|
||||||
bad_door = stonewall.dest
|
|
||||||
if bad_door.blocked:
|
|
||||||
return True # great we're done with this one
|
|
||||||
loop_region = stonewall.entrance.parent_region
|
|
||||||
start_regions = [bad_door.entrance.parent_region]
|
|
||||||
if bad_door.dependents:
|
|
||||||
for dep in bad_door.dependents:
|
|
||||||
start_regions.append(dep.entrance.parent_region)
|
|
||||||
queue = deque(start_regions)
|
|
||||||
visited = set(start_regions)
|
|
||||||
while len(queue) > 0:
|
|
||||||
region = queue.popleft()
|
|
||||||
if region == loop_region:
|
|
||||||
return False # guaranteed loop
|
|
||||||
possible_entrances = list(region.entrances)
|
|
||||||
for entrance in possible_entrances:
|
|
||||||
parent = entrance.parent_region
|
|
||||||
if parent.type != RegionType.Dungeon:
|
|
||||||
return False # you can get stuck from an entrance
|
|
||||||
else:
|
|
||||||
door = entrance.door
|
|
||||||
if (door is None or (door != stonewall and not door.blocked)) and parent not in visited:
|
|
||||||
visited.add(parent)
|
|
||||||
queue.append(parent)
|
|
||||||
# we didn't find anything bad
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def create_graph_piece_from_state(door, o_state, b_state, proposed_map, exception, world, player):
|
def create_graph_piece_from_state(door, o_state, b_state, proposed_map, exception, world, player):
|
||||||
# todo: info about dungeon events - not sure about that
|
# todo: info about dungeon events - not sure about that
|
||||||
graph_piece = GraphPiece()
|
graph_piece = GraphPiece()
|
||||||
@@ -1222,8 +1185,6 @@ class DungeonBuilder(object):
|
|||||||
self.path_entrances = None # used for pathing/key doors, I think
|
self.path_entrances = None # used for pathing/key doors, I think
|
||||||
self.split_flag = False
|
self.split_flag = False
|
||||||
|
|
||||||
self.pre_open_stonewalls = set() # used by stonewall system
|
|
||||||
|
|
||||||
self.candidates = None
|
self.candidates = None
|
||||||
self.total_keys = None
|
self.total_keys = None
|
||||||
self.key_doors_num = None
|
self.key_doors_num = None
|
||||||
@@ -1300,6 +1261,9 @@ def create_dungeon_builders(all_sectors, connections_tuple, world, player,
|
|||||||
for r_name in ['Hyrule Dungeon Cellblock', 'Sanctuary']: # need to deliver zelda
|
for r_name in ['Hyrule Dungeon Cellblock', 'Sanctuary']: # need to deliver zelda
|
||||||
assign_sector(find_sector(r_name, candidate_sectors), current_dungeon,
|
assign_sector(find_sector(r_name, candidate_sectors), current_dungeon,
|
||||||
candidate_sectors, global_pole)
|
candidate_sectors, global_pole)
|
||||||
|
if key == 'Thieves Town' and world.get_dungeon("Thieves Town", player).boss.enemizer_name == 'Blind':
|
||||||
|
assign_sector(find_sector("Thieves Blind's Cell", candidate_sectors), current_dungeon,
|
||||||
|
candidate_sectors, global_pole)
|
||||||
entrances_map, potentials, connections = connections_tuple
|
entrances_map, potentials, connections = connections_tuple
|
||||||
accessible_sectors, reverse_d_map = set(), {}
|
accessible_sectors, reverse_d_map = set(), {}
|
||||||
for key in dungeon_entrances.keys():
|
for key in dungeon_entrances.keys():
|
||||||
@@ -3955,7 +3919,7 @@ dungeon_boss_sectors = {
|
|||||||
'Palace of Darkness': ['PoD Boss'],
|
'Palace of Darkness': ['PoD Boss'],
|
||||||
'Swamp Palace': ['Swamp Boss'],
|
'Swamp Palace': ['Swamp Boss'],
|
||||||
'Skull Woods': ['Skull Boss'],
|
'Skull Woods': ['Skull Boss'],
|
||||||
'Thieves Town': ['Thieves Blind\'s Cell', 'Thieves Boss'],
|
'Thieves Town': ['Thieves Boss'],
|
||||||
'Ice Palace': ['Ice Boss'],
|
'Ice Palace': ['Ice Boss'],
|
||||||
'Misery Mire': ['Mire Boss'],
|
'Misery Mire': ['Mire Boss'],
|
||||||
'Turtle Rock': ['TR Boss'],
|
'Turtle Rock': ['TR Boss'],
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import math
|
|||||||
import RaceRandom as random
|
import RaceRandom as random
|
||||||
|
|
||||||
from BaseClasses import Region, RegionType, Shop, ShopType, Location, CollectionState
|
from BaseClasses import Region, RegionType, Shop, ShopType, Location, CollectionState
|
||||||
from Bosses import place_bosses
|
|
||||||
from EntranceShuffle import connect_entrance
|
from EntranceShuffle import connect_entrance
|
||||||
from Regions import shop_to_location_table, retro_shops, shop_table_by_location
|
from Regions import shop_to_location_table, retro_shops, shop_table_by_location
|
||||||
from Fill import FillError, fill_restrictive, fast_fill, get_dungeon_item_pool
|
from Fill import FillError, fill_restrictive, fast_fill, get_dungeon_item_pool
|
||||||
@@ -376,7 +375,6 @@ def generate_itempool(world, player):
|
|||||||
tr_medallion = ['Ether', 'Quake', 'Bombos'][random.randint(0, 2)]
|
tr_medallion = ['Ether', 'Quake', 'Bombos'][random.randint(0, 2)]
|
||||||
world.required_medallions[player] = (mm_medallion, tr_medallion)
|
world.required_medallions[player] = (mm_medallion, tr_medallion)
|
||||||
|
|
||||||
place_bosses(world, player)
|
|
||||||
set_up_shops(world, player)
|
set_up_shops(world, player)
|
||||||
|
|
||||||
if world.retro[player]:
|
if world.retro[player]:
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ class KeyLayout(object):
|
|||||||
|
|
||||||
self.found_doors = set()
|
self.found_doors = set()
|
||||||
self.prize_relevant = None
|
self.prize_relevant = None
|
||||||
|
self.prize_can_lock = None # if true, then you may need to beat the bo
|
||||||
# bk special?
|
# bk special?
|
||||||
# bk required? True if big chests or big doors exists
|
# bk required? True if big chests or big doors exists
|
||||||
|
|
||||||
@@ -1440,7 +1441,10 @@ def validate_key_layout_sub_loop(key_layout, state, checked_states, flat_proposa
|
|||||||
found_forced_bk = state.found_forced_bk()
|
found_forced_bk = state.found_forced_bk()
|
||||||
smalls_done = not smalls_avail or not enough_small_locations(state, available_small_locations)
|
smalls_done = not smalls_avail or not enough_small_locations(state, available_small_locations)
|
||||||
bk_done = state.big_key_opened or num_bigs == 0 or (available_big_locations == 0 and not found_forced_bk)
|
bk_done = state.big_key_opened or num_bigs == 0 or (available_big_locations == 0 and not found_forced_bk)
|
||||||
prize_done = not key_layout.prize_relevant or state.prize_doors_opened
|
# prize door should not be opened if the boss is reachable - but not reached yet
|
||||||
|
allow_for_prize_lock = (key_layout.prize_can_lock and
|
||||||
|
not any(x for x in state.found_locations if '- Prize' in x.name))
|
||||||
|
prize_done = not key_layout.prize_relevant or state.prize_doors_opened or allow_for_prize_lock
|
||||||
if smalls_done and bk_done and prize_done:
|
if smalls_done and bk_done and prize_done:
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
@@ -1524,6 +1528,39 @@ def enough_small_locations(state, avail_small_loc):
|
|||||||
return avail_small_loc >= len(unique_d_set)
|
return avail_small_loc >= len(unique_d_set)
|
||||||
|
|
||||||
|
|
||||||
|
def determine_prize_lock(key_layout, world, player):
|
||||||
|
if ((world.retro[player] and (world.mode[player] != 'standard' or key_layout.sector.name != 'Hyrule Castle'))
|
||||||
|
or world.logic[player] == 'nologic'):
|
||||||
|
return # done, doesn't matter what
|
||||||
|
flat_proposal = key_layout.flat_prop
|
||||||
|
state = ExplorationState(dungeon=key_layout.sector.name)
|
||||||
|
state.key_locations = key_layout.max_chests
|
||||||
|
state.big_key_special = check_bk_special(key_layout.sector.regions, world, player)
|
||||||
|
prize_lock_possible = False
|
||||||
|
for region in key_layout.start_regions:
|
||||||
|
dungeon_entrance, portal_door = find_outside_connection(region)
|
||||||
|
prize_relevant_flag = prize_relevance(key_layout, dungeon_entrance)
|
||||||
|
if prize_relevant_flag:
|
||||||
|
state.append_door_to_list(portal_door, state.prize_doors)
|
||||||
|
state.prize_door_set[portal_door] = dungeon_entrance
|
||||||
|
key_layout.prize_relevant = prize_relevant_flag
|
||||||
|
prize_lock_possible = True
|
||||||
|
else:
|
||||||
|
state.visit_region(region, key_checks=True)
|
||||||
|
state.add_all_doors_check_keys(region, flat_proposal, world, player)
|
||||||
|
if not prize_lock_possible:
|
||||||
|
return # done, no prize entrances to worry about
|
||||||
|
expand_key_state(state, flat_proposal, world, player)
|
||||||
|
while len(state.small_doors) > 0 or len(state.big_doors) > 0:
|
||||||
|
if len(state.big_doors) > 0:
|
||||||
|
open_a_door(state.big_doors[0].door, state, flat_proposal, world, player)
|
||||||
|
elif len(state.small_doors) > 0:
|
||||||
|
open_a_door(state.small_doors[0].door, state, flat_proposal, world, player)
|
||||||
|
expand_key_state(state, flat_proposal, world, player)
|
||||||
|
if any(x for x in state.found_locations if '- Prize' in x.name):
|
||||||
|
key_layout.prize_can_lock = True
|
||||||
|
|
||||||
|
|
||||||
def cnt_avail_small_locations(free_locations, key_only, state, world, player):
|
def cnt_avail_small_locations(free_locations, key_only, state, world, player):
|
||||||
if not world.keyshuffle[player] and not world.retro[player]:
|
if not world.keyshuffle[player] and not world.retro[player]:
|
||||||
bk_adj = 1 if state.big_key_opened and not state.big_key_special else 0
|
bk_adj = 1 if state.big_key_opened and not state.big_key_special else 0
|
||||||
|
|||||||
4
Main.py
4
Main.py
@@ -10,6 +10,7 @@ import time
|
|||||||
import zlib
|
import zlib
|
||||||
|
|
||||||
from BaseClasses import World, CollectionState, Item, Region, Location, Shop, Entrance, Settings
|
from BaseClasses import World, CollectionState, Item, Region, Location, Shop, Entrance, Settings
|
||||||
|
from Bosses import place_bosses
|
||||||
from Items import ItemFactory
|
from Items import ItemFactory
|
||||||
from KeyDoorShuffle import validate_key_placement
|
from KeyDoorShuffle import validate_key_placement
|
||||||
from OverworldGlitchRules import create_owg_connections
|
from OverworldGlitchRules import create_owg_connections
|
||||||
@@ -31,7 +32,7 @@ from Utils import output_path, parse_player_names
|
|||||||
from source.item.BiasedFill import create_item_pool_config, massage_item_pool
|
from source.item.BiasedFill import create_item_pool_config, massage_item_pool
|
||||||
|
|
||||||
|
|
||||||
__version__ = '0.5.1.1-u'
|
__version__ = '1.0.0.1-u'
|
||||||
|
|
||||||
from source.classes.BabelFish import BabelFish
|
from source.classes.BabelFish import BabelFish
|
||||||
|
|
||||||
@@ -150,6 +151,7 @@ def main(args, seed=None, fish=None):
|
|||||||
create_rooms(world, player)
|
create_rooms(world, player)
|
||||||
create_dungeons(world, player)
|
create_dungeons(world, player)
|
||||||
adjust_locations(world, player)
|
adjust_locations(world, player)
|
||||||
|
place_bosses(world, player)
|
||||||
|
|
||||||
if any(world.potshuffle.values()):
|
if any(world.potshuffle.values()):
|
||||||
logger.info(world.fish.translate("cli", "cli", "shuffling.pots"))
|
logger.info(world.fish.translate("cli", "cli", "shuffling.pots"))
|
||||||
|
|||||||
@@ -15,6 +15,14 @@ CLI: ```--bombbag```
|
|||||||
|
|
||||||
# Bug Fixes and Notes.
|
# Bug Fixes and Notes.
|
||||||
|
|
||||||
|
* 0.5.1.2
|
||||||
|
* Allowed Blind's Cell to be shuffled anywhere if Blind is not the boss of Thieves Town
|
||||||
|
* Remove unique annotation from a FastEnum that was causing problems
|
||||||
|
* Updated prevent mixed_travel setting to prevent more mixed travel
|
||||||
|
* Prevent key door loops on the same supertile where you could have spent 2 keys on one logical door
|
||||||
|
* Promoted dynamic soft-lock prevention on "stonewalls" from experimental to be the primary prevention (Stonewalls are now never pre-opened)
|
||||||
|
* Fix to money balancing algorithm with small item_pool, thanks Catobat
|
||||||
|
* Many fixes and refinements to key logic and generation
|
||||||
* 0.5.1.1
|
* 0.5.1.1
|
||||||
* Shop hints in ER are now more generic instead of using "near X" because they aren't near that anymore
|
* Shop hints in ER are now more generic instead of using "near X" because they aren't near that anymore
|
||||||
* Added memory location for mutliworld scripts to read what item was just obtain (longer than one frame)
|
* Added memory location for mutliworld scripts to read what item was just obtain (longer than one frame)
|
||||||
|
|||||||
9
Rom.py
9
Rom.py
@@ -32,7 +32,7 @@ from source.classes.SFX import randomize_sfx
|
|||||||
|
|
||||||
|
|
||||||
JAP10HASH = '03a63945398191337e896e5771f77173'
|
JAP10HASH = '03a63945398191337e896e5771f77173'
|
||||||
RANDOMIZERBASEHASH = 'ef6e3e1aa59838c01dbd5b1b2387e70c'
|
RANDOMIZERBASEHASH = '11f4f494e999a919aafd7d2624e67679'
|
||||||
|
|
||||||
|
|
||||||
class JsonRom(object):
|
class JsonRom(object):
|
||||||
@@ -754,13 +754,6 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
|||||||
rom.write_bytes(paired_door.address_a(world, player), paired_door.rom_data_a(world, player))
|
rom.write_bytes(paired_door.address_a(world, player), paired_door.rom_data_a(world, player))
|
||||||
rom.write_bytes(paired_door.address_b(world, player), paired_door.rom_data_b(world, player))
|
rom.write_bytes(paired_door.address_b(world, player), paired_door.rom_data_b(world, player))
|
||||||
if world.doorShuffle[player] != 'vanilla':
|
if world.doorShuffle[player] != 'vanilla':
|
||||||
if not world.experimental[player]:
|
|
||||||
for builder in world.dungeon_layouts[player].values():
|
|
||||||
for stonewall in builder.pre_open_stonewalls:
|
|
||||||
if stonewall.name == 'Desert Wall Slide NW':
|
|
||||||
dr_flags |= DROptions.Open_Desert_Wall
|
|
||||||
elif stonewall.name == 'PoD Bow Statue Down Ladder':
|
|
||||||
dr_flags |= DROptions.Open_PoD_Wall
|
|
||||||
for name, pair in boss_indicator.items():
|
for name, pair in boss_indicator.items():
|
||||||
dungeon_id, boss_door = pair
|
dungeon_id, boss_door = pair
|
||||||
opposite_door = world.get_door(boss_door, player).dest
|
opposite_door = world.get_door(boss_door, player).dest
|
||||||
|
|||||||
6
Rules.py
6
Rules.py
@@ -1973,7 +1973,7 @@ def add_key_logic_rules(world, player):
|
|||||||
big_chest = world.get_location(chest.name, player)
|
big_chest = world.get_location(chest.name, player)
|
||||||
add_rule(big_chest, create_rule(d_logic.bk_name, player))
|
add_rule(big_chest, create_rule(d_logic.bk_name, player))
|
||||||
if len(d_logic.bk_doors) == 0 and len(d_logic.bk_chests) <= 1:
|
if len(d_logic.bk_doors) == 0 and len(d_logic.bk_chests) <= 1:
|
||||||
set_always_allow(big_chest, lambda state, item: item.name == d_logic.bk_name and item.player == player)
|
set_always_allow(big_chest, allow_big_key_in_big_chest(d_logic.bk_name, player))
|
||||||
if world.retro[player]:
|
if world.retro[player]:
|
||||||
for d_name, layout in world.key_layout[player].items():
|
for d_name, layout in world.key_layout[player].items():
|
||||||
for door in layout.flat_prop:
|
for door in layout.flat_prop:
|
||||||
@@ -2011,6 +2011,10 @@ def eval_small_key_door(door_name, dungeon, player):
|
|||||||
return lambda state: eval_small_key_door_main(state, door_name, dungeon, player)
|
return lambda state: eval_small_key_door_main(state, door_name, dungeon, player)
|
||||||
|
|
||||||
|
|
||||||
|
def allow_big_key_in_big_chest(bk_name, player):
|
||||||
|
return lambda state, item: item.name == bk_name and item.player == player
|
||||||
|
|
||||||
|
|
||||||
def retro_in_hc(spot):
|
def retro_in_hc(spot):
|
||||||
return spot.parent_region.dungeon.name == 'Hyrule Castle' if spot.parent_region.dungeon else False
|
return spot.parent_region.dungeon.name == 'Hyrule Castle' if spot.parent_region.dungeon else False
|
||||||
|
|
||||||
|
|||||||
@@ -35,11 +35,7 @@ rtl
|
|||||||
|
|
||||||
OnFileLoadOverride:
|
OnFileLoadOverride:
|
||||||
jsl OnFileLoad ; what I wrote over
|
jsl OnFileLoad ; what I wrote over
|
||||||
lda.l DRFlags : and #$80 : beq + ;flag is off
|
+ lda.l DRFlags : and #$02 : beq + ; Mirror Scroll
|
||||||
lda $7ef086 : ora #$80 : sta $7ef086
|
|
||||||
+ lda.l DRFlags : and #$40 : beq + ;flag is off
|
|
||||||
lda $7ef036 : ora #$80 : sta $7ef036
|
|
||||||
+ lda.l DRFlags : and #$02 : beq +
|
|
||||||
lda $7ef353 : bne +
|
lda $7ef353 : bne +
|
||||||
lda #$01 : sta $7ef353
|
lda #$01 : sta $7ef353
|
||||||
+ rtl
|
+ rtl
|
||||||
|
|||||||
Binary file not shown.
@@ -20,6 +20,7 @@ def create_item_pool_config(world):
|
|||||||
d_name = "Thieves' Town" if dungeon.startswith('Thieves') else dungeon
|
d_name = "Thieves' Town" if dungeon.startswith('Thieves') else dungeon
|
||||||
config.reserved_locations[player].add(f'{d_name} - Boss')
|
config.reserved_locations[player].add(f'{d_name} - Boss')
|
||||||
for dungeon in world.dungeons:
|
for dungeon in world.dungeons:
|
||||||
for item in dungeon.all_items:
|
if world.restrict_boss_items[dungeon.player] != 'none':
|
||||||
if item.map or item.compass:
|
for item in dungeon.all_items:
|
||||||
item.advancement = True
|
if item.map or item.compass:
|
||||||
|
item.advancement = True
|
||||||
|
|||||||
Reference in New Issue
Block a user