Standard + Crossed bug with Hyrule Castle
Big Key logic for standard Some generation issues with ER Redesigned Map/Compass section of Keysanity menu
This commit is contained in:
@@ -1620,6 +1620,15 @@ class Location(object):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def forced_big_key(self):
|
||||||
|
if self.forced_item and self.forced_item.bigkey and self.player == self.forced_item.player:
|
||||||
|
item_dungeon = self.forced_item.name.split('(')[1][:-1]
|
||||||
|
if item_dungeon == 'Escape':
|
||||||
|
item_dungeon = 'Hyrule Castle'
|
||||||
|
if self.parent_region.dungeon.name == item_dungeon:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return str(self.__unicode__())
|
return str(self.__unicode__())
|
||||||
|
|
||||||
|
|||||||
213
DoorShuffle.py
213
DoorShuffle.py
@@ -42,18 +42,22 @@ def link_doors(world, player):
|
|||||||
for entrance, ext in straight_staircases:
|
for entrance, ext in straight_staircases:
|
||||||
connect_two_way(world, entrance, ext, player)
|
connect_two_way(world, entrance, ext, player)
|
||||||
|
|
||||||
if world.doorShuffle[player] in ['basic', 'crossed']:
|
find_inaccessible_regions(world, player)
|
||||||
find_inaccessible_regions(world, player)
|
|
||||||
|
|
||||||
if world.intensity[player] >= 3:
|
if world.intensity[player] >= 3 and world.doorShuffle[player] in ['basic', 'crossed']:
|
||||||
choose_portals(world, player)
|
choose_portals(world, player)
|
||||||
else:
|
else:
|
||||||
|
if world.shuffle[player] == 'vanilla':
|
||||||
|
if world.mode[player] == 'standard':
|
||||||
|
world.get_portal('Sanctuary', player).destination = True
|
||||||
|
world.get_portal('Desert East', player).destination = True
|
||||||
|
world.get_portal('Skull 2 West', player).destination = True
|
||||||
|
world.get_portal('Turtle Rock Lazy Eyes', player).destination = True
|
||||||
|
world.get_portal('Turtle Rock Eye Bridge', player).destination = True
|
||||||
|
else:
|
||||||
|
analyze_portals(world, player)
|
||||||
for portal in world.dungeon_portals[player]:
|
for portal in world.dungeon_portals[player]:
|
||||||
connect_portal(portal, world, player)
|
connect_portal(portal, world, player)
|
||||||
world.get_portal('Desert East', player).destination = True
|
|
||||||
world.get_portal('Skull 2 West', player).destination = True
|
|
||||||
world.get_portal('Turtle Rock Lazy Eyes', player).destination = True
|
|
||||||
world.get_portal('Turtle Rock Eye Bridge', player).destination = True
|
|
||||||
|
|
||||||
if world.doorShuffle[player] == 'vanilla':
|
if world.doorShuffle[player] == 'vanilla':
|
||||||
for entrance, ext in open_edges:
|
for entrance, ext in open_edges:
|
||||||
@@ -150,8 +154,8 @@ def vanilla_key_logic(world, player):
|
|||||||
builders.append(builder)
|
builders.append(builder)
|
||||||
world.dungeon_layouts[player][builder.name] = builder
|
world.dungeon_layouts[player][builder.name] = builder
|
||||||
|
|
||||||
overworld_prep(world, player)
|
add_inaccessible_doors(world, player)
|
||||||
entrances_map, potentials, connections = determine_entrance_list(world, player)
|
entrances_map, potentials, connections = determine_entrance_list_vanilla(world, player)
|
||||||
|
|
||||||
enabled_entrances = {}
|
enabled_entrances = {}
|
||||||
sector_queue = deque(builders)
|
sector_queue = deque(builders)
|
||||||
@@ -412,6 +416,48 @@ def choose_portals(world, player):
|
|||||||
world.swamp_patch_required[player] = True
|
world.swamp_patch_required[player] = True
|
||||||
|
|
||||||
|
|
||||||
|
def analyze_portals(world, player):
|
||||||
|
info_map = {}
|
||||||
|
for dungeon, portal_list in dungeon_portals.items():
|
||||||
|
info = DungeonInfo(dungeon)
|
||||||
|
region_map = defaultdict(list)
|
||||||
|
reachable_portals = []
|
||||||
|
inaccessible_portals = []
|
||||||
|
for portal in portal_list:
|
||||||
|
placeholder = world.get_region(portal + ' Placeholder', player)
|
||||||
|
portal_region = placeholder.exits[0].connected_region
|
||||||
|
name = portal_region.name
|
||||||
|
if portal_region.type == RegionType.LightWorld:
|
||||||
|
world.get_portal(portal, player).light_world = True
|
||||||
|
if name in world.inaccessible_regions[player]:
|
||||||
|
name_key = 'Desert Ledge' if name == 'Desert Palace Entrance (North) Spot' else name
|
||||||
|
region_map[name_key].append(portal)
|
||||||
|
inaccessible_portals.append(portal)
|
||||||
|
else:
|
||||||
|
reachable_portals.append(portal)
|
||||||
|
info.total = len(portal_list)
|
||||||
|
info.required_passage = region_map
|
||||||
|
if len(reachable_portals) == 0:
|
||||||
|
if len(inaccessible_portals) == 1:
|
||||||
|
info.sole_entrance = inaccessible_portals[0]
|
||||||
|
info.required_passage.clear()
|
||||||
|
else:
|
||||||
|
raise Exception('please inspect this case')
|
||||||
|
if len(reachable_portals) == 1:
|
||||||
|
info.sole_entrance = reachable_portals[0]
|
||||||
|
info_map[dungeon] = info
|
||||||
|
|
||||||
|
for dungeon, info in info_map.items():
|
||||||
|
if dungeon == 'Hyrule Castle' and world.mode[player] == 'standard':
|
||||||
|
sanc = world.get_portal('Sanctuary', player)
|
||||||
|
sanc.destination = True
|
||||||
|
for target_region, possible_portals in info.required_passage.items():
|
||||||
|
if len(possible_portals) == 1:
|
||||||
|
world.get_portal(possible_portals[0], player).destination = True
|
||||||
|
elif len(possible_portals) > 1:
|
||||||
|
world.get_portal(random.choice(possible_portals), player).destination = True
|
||||||
|
|
||||||
|
|
||||||
def connect_portal(portal, world, player):
|
def connect_portal(portal, world, player):
|
||||||
ent, ext = portal_map[portal.name]
|
ent, ext = portal_map[portal.name]
|
||||||
if world.mode[player] == 'inverted' and portal.name in ['Ganons Tower', 'Agahnims Tower']:
|
if world.mode[player] == 'inverted' and portal.name in ['Ganons Tower', 'Agahnims Tower']:
|
||||||
@@ -516,60 +562,56 @@ def create_dungeon_entrances(world, player):
|
|||||||
split_map: DefaultDict[str, DefaultDict[str, List]] = defaultdict(lambda: defaultdict(list))
|
split_map: DefaultDict[str, DefaultDict[str, List]] = defaultdict(lambda: defaultdict(list))
|
||||||
originating: DefaultDict[str, DefaultDict[str, Dict]] = defaultdict(lambda: defaultdict(dict))
|
originating: DefaultDict[str, DefaultDict[str, Dict]] = defaultdict(lambda: defaultdict(dict))
|
||||||
for key, portal_list in dungeon_portals.items():
|
for key, portal_list in dungeon_portals.items():
|
||||||
if world.mode[player] == 'standard' and key in standard_starts.keys():
|
if key in dungeon_drops.keys():
|
||||||
portal = world.get_portal('Hyrule Castle South', player)
|
entrance_map[key].extend(dungeon_drops[key])
|
||||||
entrance_map[key].append(portal.door.entrance.parent_region.name)
|
if key in split_portals.keys() and world.intensity[player] >= 3:
|
||||||
|
dead_ends = []
|
||||||
|
destinations = []
|
||||||
|
the_rest = []
|
||||||
|
for portal_name in portal_list:
|
||||||
|
portal = world.get_portal(portal_name, player)
|
||||||
|
entrance_map[key].append(portal.door.entrance.parent_region.name)
|
||||||
|
if portal.deadEnd:
|
||||||
|
dead_ends.append(portal)
|
||||||
|
elif portal.destination:
|
||||||
|
destinations.append(portal)
|
||||||
|
else:
|
||||||
|
the_rest.append(portal)
|
||||||
|
choices = list(split_portals[key])
|
||||||
|
for portal in dead_ends:
|
||||||
|
choice = random.choice(choices)
|
||||||
|
choices.remove(choice)
|
||||||
|
r_name = portal.door.entrance.parent_region.name
|
||||||
|
split_map[key][choice].append(r_name)
|
||||||
|
for portal in the_rest:
|
||||||
|
if len(choices) == 0:
|
||||||
|
choices.append('Extra')
|
||||||
|
choice = random.choice(choices)
|
||||||
|
p_entrance = portal.door.entrance
|
||||||
|
r_name = p_entrance.parent_region.name
|
||||||
|
split_map[key][choice].append(r_name)
|
||||||
|
originating[key][choice][p_entrance.connected_region.name] = None
|
||||||
|
dest_choices = [x for x in choices if len(split_map[key][x]) > 0]
|
||||||
|
for portal in destinations:
|
||||||
|
restricted = portal.door.entrance.connected_region.name in world.inaccessible_regions[player]
|
||||||
|
if restricted:
|
||||||
|
filtered_choices = [x for x in choices if any(y not in world.inaccessible_regions[player] for y in originating[key][x].keys())]
|
||||||
|
else:
|
||||||
|
filtered_choices = dest_choices
|
||||||
|
choice = random.choice(filtered_choices)
|
||||||
|
r_name = portal.door.entrance.parent_region.name
|
||||||
|
split_map[key][choice].append(r_name)
|
||||||
else:
|
else:
|
||||||
if key in dungeon_drops.keys():
|
for portal_name in portal_list:
|
||||||
entrance_map[key].extend(dungeon_drops[key])
|
portal = world.get_portal(portal_name, player)
|
||||||
if key in split_portals.keys() and world.intensity[player] >= 3:
|
r_name = portal.door.entrance.parent_region.name
|
||||||
dead_ends = []
|
entrance_map[key].append(r_name)
|
||||||
destinations = []
|
if key in split_portals.keys():
|
||||||
the_rest = []
|
for split_key in split_portals[key]:
|
||||||
for portal_name in portal_list:
|
if split_key not in split_map[key]:
|
||||||
portal = world.get_portal(portal_name, player)
|
split_map[key][split_key] = []
|
||||||
entrance_map[key].append(portal.door.entrance.parent_region.name)
|
if world.intensity[player] < 3:
|
||||||
if portal.deadEnd:
|
split_map[key][split_portal_defaults[key][r_name]].append(r_name)
|
||||||
dead_ends.append(portal)
|
|
||||||
elif portal.destination:
|
|
||||||
destinations.append(portal)
|
|
||||||
else:
|
|
||||||
the_rest.append(portal)
|
|
||||||
choices = list(split_portals[key])
|
|
||||||
for portal in dead_ends:
|
|
||||||
choice = random.choice(choices)
|
|
||||||
choices.remove(choice)
|
|
||||||
r_name = portal.door.entrance.parent_region.name
|
|
||||||
split_map[key][choice].append(r_name)
|
|
||||||
for portal in the_rest:
|
|
||||||
if len(choices) == 0:
|
|
||||||
choices.append('Extra')
|
|
||||||
choice = random.choice(choices)
|
|
||||||
p_entrance = portal.door.entrance
|
|
||||||
r_name = p_entrance.parent_region.name
|
|
||||||
split_map[key][choice].append(r_name)
|
|
||||||
originating[key][choice][p_entrance.connected_region.name] = None
|
|
||||||
dest_choices = [x for x in choices if len(split_map[key][x]) > 0]
|
|
||||||
for portal in destinations:
|
|
||||||
restricted = portal.door.entrance.connected_region.name in world.inaccessible_regions[player]
|
|
||||||
if restricted:
|
|
||||||
filtered_choices = [x for x in choices if any(y not in world.inaccessible_regions[player] for y in originating[key][x].keys())]
|
|
||||||
else:
|
|
||||||
filtered_choices = dest_choices
|
|
||||||
choice = random.choice(filtered_choices)
|
|
||||||
r_name = portal.door.entrance.parent_region.name
|
|
||||||
split_map[key][choice].append(r_name)
|
|
||||||
else:
|
|
||||||
for portal_name in portal_list:
|
|
||||||
portal = world.get_portal(portal_name, player)
|
|
||||||
r_name = portal.door.entrance.parent_region.name
|
|
||||||
entrance_map[key].append(r_name)
|
|
||||||
if key in split_portals.keys():
|
|
||||||
for split_key in split_portals[key]:
|
|
||||||
if split_key not in split_map[key]:
|
|
||||||
split_map[key][split_key] = []
|
|
||||||
if world.intensity[player] < 3:
|
|
||||||
split_map[key][split_portal_defaults[key][r_name]].append(r_name)
|
|
||||||
return entrance_map, split_map
|
return entrance_map, split_map
|
||||||
|
|
||||||
|
|
||||||
@@ -580,7 +622,7 @@ def create_dungeon_entrances(world, player):
|
|||||||
def within_dungeon(world, player):
|
def within_dungeon(world, player):
|
||||||
fix_big_key_doors_with_ugly_smalls(world, player)
|
fix_big_key_doors_with_ugly_smalls(world, player)
|
||||||
add_inaccessible_doors(world, player)
|
add_inaccessible_doors(world, player)
|
||||||
entrances_map, potentials, connections = determine_entrance_list_2(world, player)
|
entrances_map, potentials, connections = determine_entrance_list(world, player)
|
||||||
connections_tuple = (entrances_map, potentials, connections)
|
connections_tuple = (entrances_map, potentials, connections)
|
||||||
|
|
||||||
dungeon_builders = {}
|
dungeon_builders = {}
|
||||||
@@ -672,14 +714,14 @@ def main_dungeon_generation(dungeon_builders, recombinant_builders, connections_
|
|||||||
world.dungeon_layouts[player] = dungeon_builders
|
world.dungeon_layouts[player] = dungeon_builders
|
||||||
|
|
||||||
|
|
||||||
def determine_entrance_list(world, player):
|
def determine_entrance_list_vanilla(world, player):
|
||||||
entrance_map = {}
|
entrance_map = {}
|
||||||
potential_entrances = {}
|
potential_entrances = {}
|
||||||
connections = {}
|
connections = {}
|
||||||
for key, r_names in region_starts.items():
|
for key, r_names in region_starts.items():
|
||||||
entrance_map[key] = []
|
entrance_map[key] = []
|
||||||
if world.mode[player] == 'standard' and key in standard_starts.keys():
|
if world.mode[player] == 'standard' and key in standard_starts.keys():
|
||||||
r_names = standard_starts[key]
|
r_names = ['Hyrule Castle Lobby']
|
||||||
for region_name in r_names:
|
for region_name in r_names:
|
||||||
region = world.get_region(region_name, player)
|
region = world.get_region(region_name, player)
|
||||||
for ent in region.entrances:
|
for ent in region.entrances:
|
||||||
@@ -695,28 +737,26 @@ def determine_entrance_list(world, player):
|
|||||||
return entrance_map, potential_entrances, connections
|
return entrance_map, potential_entrances, connections
|
||||||
|
|
||||||
|
|
||||||
def determine_entrance_list_2(world, player):
|
def determine_entrance_list(world, player):
|
||||||
entrance_map = {}
|
entrance_map = {}
|
||||||
potential_entrances = {}
|
potential_entrances = {}
|
||||||
connections = {}
|
connections = {}
|
||||||
for key, portal_list in dungeon_portals.items():
|
for key, portal_list in dungeon_portals.items():
|
||||||
entrance_map[key] = []
|
entrance_map[key] = []
|
||||||
r_names = []
|
r_names = {}
|
||||||
if world.mode[player] == 'standard' and key in standard_starts.keys():
|
if key in dungeon_drops.keys():
|
||||||
portal = world.get_portal('Hyrule Castle South', player)
|
for drop in dungeon_drops[key]:
|
||||||
r_names.append(portal.door.entrance.parent_region.name)
|
r_names[drop] = None
|
||||||
else:
|
for portal_name in portal_list:
|
||||||
if key in dungeon_drops.keys():
|
portal = world.get_portal(portal_name, player)
|
||||||
r_names.extend(dungeon_drops[key])
|
r_names[portal.door.entrance.parent_region.name] = portal
|
||||||
for portal_name in portal_list:
|
for region_name, portal in r_names.items():
|
||||||
portal = world.get_portal(portal_name, player)
|
|
||||||
r_names.append(portal.door.entrance.parent_region.name)
|
|
||||||
for region_name in r_names:
|
|
||||||
region = world.get_region(region_name, player)
|
region = world.get_region(region_name, player)
|
||||||
for ent in region.entrances:
|
for ent in region.entrances:
|
||||||
parent = ent.parent_region
|
parent = ent.parent_region
|
||||||
if (parent.type != RegionType.Dungeon and parent.name != 'Menu') or parent.name == 'Sewer Drop':
|
if (parent.type != RegionType.Dungeon and parent.name != 'Menu') or parent.name == 'Sewer Drop':
|
||||||
if parent.name not in world.inaccessible_regions[player]:
|
std_inaccessible = is_standard_inaccessible(key, portal, world, player)
|
||||||
|
if parent.name not in world.inaccessible_regions[player] and not std_inaccessible:
|
||||||
entrance_map[key].append(region_name)
|
entrance_map[key].append(region_name)
|
||||||
else:
|
else:
|
||||||
if parent not in potential_entrances.keys():
|
if parent not in potential_entrances.keys():
|
||||||
@@ -727,10 +767,14 @@ def determine_entrance_list_2(world, player):
|
|||||||
return entrance_map, potential_entrances, connections
|
return entrance_map, potential_entrances, connections
|
||||||
|
|
||||||
|
|
||||||
|
def is_standard_inaccessible(key, portal, world, player):
|
||||||
|
return world.mode[player] == 'standard' and key in standard_starts and (not portal or portal.name not in standard_starts[key])
|
||||||
|
|
||||||
|
|
||||||
def add_shuffled_entrances(sectors, region_list, entrance_list):
|
def add_shuffled_entrances(sectors, region_list, entrance_list):
|
||||||
for sector in sectors:
|
for sector in sectors:
|
||||||
for region in sector.regions:
|
for region in sector.regions:
|
||||||
if region.name in region_list:
|
if region.name in region_list and region.name not in entrance_list:
|
||||||
entrance_list.append(region.name)
|
entrance_list.append(region.name)
|
||||||
|
|
||||||
|
|
||||||
@@ -805,8 +849,8 @@ def aga_tower_enabled(enabled):
|
|||||||
|
|
||||||
def cross_dungeon(world, player):
|
def cross_dungeon(world, player):
|
||||||
fix_big_key_doors_with_ugly_smalls(world, player)
|
fix_big_key_doors_with_ugly_smalls(world, player)
|
||||||
overworld_prep(world, player)
|
add_inaccessible_doors(world, player)
|
||||||
entrances_map, potentials, connections = determine_entrance_list_2(world, player)
|
entrances_map, potentials, connections = determine_entrance_list(world, player)
|
||||||
connections_tuple = (entrances_map, potentials, connections)
|
connections_tuple = (entrances_map, potentials, connections)
|
||||||
|
|
||||||
all_sectors, all_regions = [], []
|
all_sectors, all_regions = [], []
|
||||||
@@ -826,7 +870,7 @@ def cross_dungeon(world, player):
|
|||||||
key_name = dungeon_keys[builder.name] if loc.name != 'Hyrule Castle - Big Key Drop' else dungeon_bigs[builder.name]
|
key_name = dungeon_keys[builder.name] if loc.name != 'Hyrule Castle - Big Key Drop' else dungeon_bigs[builder.name]
|
||||||
loc.forced_item = loc.item = ItemFactory(key_name, player)
|
loc.forced_item = loc.item = ItemFactory(key_name, player)
|
||||||
recombinant_builders = {}
|
recombinant_builders = {}
|
||||||
builder_info = None, None, world, player
|
builder_info = entrances, splits, world, player
|
||||||
handle_split_dungeons(dungeon_builders, recombinant_builders, entrances_map, builder_info)
|
handle_split_dungeons(dungeon_builders, recombinant_builders, entrances_map, builder_info)
|
||||||
|
|
||||||
main_dungeon_generation(dungeon_builders, recombinant_builders, connections_tuple, world, player)
|
main_dungeon_generation(dungeon_builders, recombinant_builders, connections_tuple, world, player)
|
||||||
@@ -1486,11 +1530,6 @@ def random_door_type(door, partner, world, player, type_a, type_b, room_a, room_
|
|||||||
world.spoiler.set_door_type(door.name + ' <-> ' + partner.name, spoiler_type, player)
|
world.spoiler.set_door_type(door.name + ' <-> ' + partner.name, spoiler_type, player)
|
||||||
|
|
||||||
|
|
||||||
def overworld_prep(world, player):
|
|
||||||
find_inaccessible_regions(world, player)
|
|
||||||
add_inaccessible_doors(world, player)
|
|
||||||
|
|
||||||
|
|
||||||
def find_inaccessible_regions(world, player):
|
def find_inaccessible_regions(world, player):
|
||||||
world.inaccessible_regions[player] = []
|
world.inaccessible_regions[player] = []
|
||||||
if world.mode[player] != 'inverted':
|
if world.mode[player] != 'inverted':
|
||||||
|
|||||||
@@ -858,10 +858,6 @@ class ExplorationState(object):
|
|||||||
if location.name in flooded_keys_reverse.keys() and self.location_found(
|
if location.name in flooded_keys_reverse.keys() and self.location_found(
|
||||||
flooded_keys_reverse[location.name]):
|
flooded_keys_reverse[location.name]):
|
||||||
self.perform_event(flooded_keys_reverse[location.name], key_region)
|
self.perform_event(flooded_keys_reverse[location.name], key_region)
|
||||||
if key_checks and region.name == 'Hyrule Dungeon Cellblock' and not self.big_key_opened:
|
|
||||||
self.big_key_opened = True
|
|
||||||
self.avail_doors.extend(self.big_doors)
|
|
||||||
self.big_doors.clear()
|
|
||||||
|
|
||||||
def flooded_key_check(self, location):
|
def flooded_key_check(self, location):
|
||||||
if location.name not in flooded_keys.keys():
|
if location.name not in flooded_keys.keys():
|
||||||
@@ -980,6 +976,12 @@ class ExplorationState(object):
|
|||||||
def visited_at_all(self, region):
|
def visited_at_all(self, region):
|
||||||
return region in self.visited_blue or region in self.visited_orange
|
return region in self.visited_blue or region in self.visited_orange
|
||||||
|
|
||||||
|
def found_forced_bk(self):
|
||||||
|
for location in self.found_locations:
|
||||||
|
if location.forced_big_key():
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
def can_traverse(self, door, exception=None):
|
def can_traverse(self, door, exception=None):
|
||||||
if door.blocked:
|
if door.blocked:
|
||||||
return exception(door) if exception else False
|
return exception(door) if exception else False
|
||||||
@@ -2763,7 +2765,7 @@ def split_dungeon_builder(builder, split_list, builder_info):
|
|||||||
p = next(x for x in world.dungeon_portals[player] if x.door.entrance.parent_region.name == r_name)
|
p = next(x for x in world.dungeon_portals[player] if x.door.entrance.parent_region.name == r_name)
|
||||||
if not p.deadEnd:
|
if not p.deadEnd:
|
||||||
candidates.append(name)
|
candidates.append(name)
|
||||||
merge_keys = random.sample(candidates, 2)
|
merge_keys = random.sample(candidates, 2) if len(candidates) >= 2 else []
|
||||||
for name, split_entrances in split_list.items():
|
for name, split_entrances in split_list.items():
|
||||||
key = builder.name + ' ' + name
|
key = builder.name + ' ' + name
|
||||||
if merge_keys and name in merge_keys:
|
if merge_keys and name in merge_keys:
|
||||||
|
|||||||
@@ -333,7 +333,7 @@ region_starts = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
standard_starts = {
|
standard_starts = {
|
||||||
'Hyrule Castle': ['Hyrule Castle Lobby']
|
'Hyrule Castle': ['Hyrule Castle South']
|
||||||
}
|
}
|
||||||
|
|
||||||
split_region_starts = {
|
split_region_starts = {
|
||||||
|
|||||||
@@ -832,6 +832,13 @@ def available_chest_small_keys_logic(key_counter, world, player, sm_restricted):
|
|||||||
return key_counter.max_chests
|
return key_counter.max_chests
|
||||||
|
|
||||||
|
|
||||||
|
def big_key_drop_available(key_counter):
|
||||||
|
for loc in key_counter.other_locations:
|
||||||
|
if loc.forced_big_key():
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def bk_restricted_rules(rule, door, odd_counter, empty_flag, key_counter, key_layout, world, player):
|
def bk_restricted_rules(rule, door, odd_counter, empty_flag, key_counter, key_layout, world, player):
|
||||||
if key_counter.big_key_opened:
|
if key_counter.big_key_opened:
|
||||||
return
|
return
|
||||||
@@ -1138,8 +1145,9 @@ def check_rules_deep(original_counter, key_layout, world, player):
|
|||||||
bail = 0
|
bail = 0
|
||||||
last_counter = counter
|
last_counter = counter
|
||||||
chest_keys = available_chest_small_keys_logic(counter, world, player, key_logic.sm_restricted)
|
chest_keys = available_chest_small_keys_logic(counter, world, player, key_logic.sm_restricted)
|
||||||
big_avail = counter.big_key_opened
|
bk_drop = big_key_drop_available(counter)
|
||||||
big_maybe_not_found = not counter.big_key_opened
|
big_avail = counter.big_key_opened or bk_drop
|
||||||
|
big_maybe_not_found = not counter.big_key_opened and not bk_drop # better named as big_missing?
|
||||||
if not key_layout.big_key_special and not big_avail:
|
if not key_layout.big_key_special and not big_avail:
|
||||||
if world.bigkeyshuffle[player]:
|
if world.bigkeyshuffle[player]:
|
||||||
big_avail = True
|
big_avail = True
|
||||||
@@ -1150,7 +1158,7 @@ def check_rules_deep(original_counter, key_layout, world, player):
|
|||||||
break
|
break
|
||||||
outstanding_big_locs = {x for x in big_locations if x not in counter.free_locations}
|
outstanding_big_locs = {x for x in big_locations if x not in counter.free_locations}
|
||||||
if big_maybe_not_found:
|
if big_maybe_not_found:
|
||||||
if len(outstanding_big_locs) == 0:
|
if len(outstanding_big_locs) == 0 and not key_layout.big_key_special:
|
||||||
big_maybe_not_found = False
|
big_maybe_not_found = False
|
||||||
big_uses_chest = big_avail and not key_layout.big_key_special
|
big_uses_chest = big_avail and not key_layout.big_key_special
|
||||||
collected_alt = len(counter.key_only_locations) + chest_keys
|
collected_alt = len(counter.key_only_locations) + chest_keys
|
||||||
@@ -1158,7 +1166,7 @@ def check_rules_deep(original_counter, key_layout, world, player):
|
|||||||
chest_keys -= 1
|
chest_keys -= 1
|
||||||
collected = len(counter.key_only_locations) + chest_keys
|
collected = len(counter.key_only_locations) + chest_keys
|
||||||
can_progress = len(counter.child_doors) == 0
|
can_progress = len(counter.child_doors) == 0
|
||||||
smalls_opened = False
|
smalls_opened, big_opened = False, False
|
||||||
small_rules = []
|
small_rules = []
|
||||||
for door in counter.child_doors.keys():
|
for door in counter.child_doors.keys():
|
||||||
can_open = False
|
can_open = False
|
||||||
@@ -1232,6 +1240,15 @@ def set_paired_rules(key_logic, world, player):
|
|||||||
rule.opposite = key_logic.door_rules[door.dest.name]
|
rule.opposite = key_logic.door_rules[door.dest.name]
|
||||||
|
|
||||||
|
|
||||||
|
def check_bk_special(regions, world, player):
|
||||||
|
for r_name in regions:
|
||||||
|
region = world.get_region(r_name, player)
|
||||||
|
for loc in region.locations:
|
||||||
|
if loc.forced_big_key():
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
# Soft lock stuff
|
# Soft lock stuff
|
||||||
def validate_key_layout(key_layout, world, player):
|
def validate_key_layout(key_layout, world, player):
|
||||||
# retro is all good - except for hyrule castle in standard mode
|
# retro is all good - except for hyrule castle in standard mode
|
||||||
@@ -1240,7 +1257,7 @@ def validate_key_layout(key_layout, world, player):
|
|||||||
flat_proposal = key_layout.flat_prop
|
flat_proposal = key_layout.flat_prop
|
||||||
state = ExplorationState(dungeon=key_layout.sector.name)
|
state = ExplorationState(dungeon=key_layout.sector.name)
|
||||||
state.key_locations = key_layout.max_chests
|
state.key_locations = key_layout.max_chests
|
||||||
state.big_key_special = world.get_region('Hyrule Dungeon Cellblock', player) in key_layout.sector.regions
|
state.big_key_special = check_bk_special(key_layout.sector.regions, world, player)
|
||||||
for region in key_layout.start_regions:
|
for region in key_layout.start_regions:
|
||||||
state.visit_region(region, key_checks=True)
|
state.visit_region(region, key_checks=True)
|
||||||
state.add_all_doors_check_keys(region, flat_proposal, world, player)
|
state.add_all_doors_check_keys(region, flat_proposal, world, player)
|
||||||
@@ -1262,7 +1279,10 @@ def validate_key_layout_sub_loop(key_layout, state, checked_states, flat_proposa
|
|||||||
return False
|
return False
|
||||||
# todo: allow more key shuffles - refine placement rules
|
# todo: allow more key shuffles - refine placement rules
|
||||||
# if (not smalls_avail or available_small_locations == 0) and (state.big_key_opened or num_bigs == 0 or available_big_locations == 0):
|
# if (not smalls_avail or available_small_locations == 0) and (state.big_key_opened or num_bigs == 0 or available_big_locations == 0):
|
||||||
if (not smalls_avail or not enough_small_locations(state, available_small_locations)) and (state.big_key_opened or num_bigs == 0 or available_big_locations == 0):
|
found_forced_bk = state.found_forced_bk()
|
||||||
|
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)
|
||||||
|
if smalls_done and bk_done:
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
if smalls_avail and available_small_locations > 0:
|
if smalls_avail and available_small_locations > 0:
|
||||||
@@ -1281,10 +1301,11 @@ def validate_key_layout_sub_loop(key_layout, state, checked_states, flat_proposa
|
|||||||
valid = checked_states[code]
|
valid = checked_states[code]
|
||||||
if not valid:
|
if not valid:
|
||||||
return False
|
return False
|
||||||
if not state.big_key_opened and available_big_locations >= num_bigs > 0:
|
if not state.big_key_opened and (available_big_locations >= num_bigs > 0 or (found_forced_bk and num_bigs > 0)):
|
||||||
state_copy = state.copy()
|
state_copy = state.copy()
|
||||||
open_a_door(state.big_doors[0].door, state_copy, flat_proposal)
|
open_a_door(state.big_doors[0].door, state_copy, flat_proposal)
|
||||||
state_copy.used_locations += 1
|
if not found_forced_bk:
|
||||||
|
state_copy.used_locations += 1
|
||||||
code = state_id(state_copy, flat_proposal)
|
code = state_id(state_copy, flat_proposal)
|
||||||
if code not in checked_states.keys():
|
if code not in checked_states.keys():
|
||||||
valid = validate_key_layout_sub_loop(key_layout, state_copy, checked_states, flat_proposal,
|
valid = validate_key_layout_sub_loop(key_layout, state_copy, checked_states, flat_proposal,
|
||||||
@@ -1350,7 +1371,10 @@ def create_key_counters(key_layout, world, player):
|
|||||||
state.key_locations = len(world.get_dungeon(key_layout.sector.name, player).small_keys)
|
state.key_locations = len(world.get_dungeon(key_layout.sector.name, player).small_keys)
|
||||||
else:
|
else:
|
||||||
state.key_locations = world.dungeon_layouts[player][key_layout.sector.name].key_doors_num
|
state.key_locations = world.dungeon_layouts[player][key_layout.sector.name].key_doors_num
|
||||||
state.big_key_special = world.get_region('Hyrule Dungeon Cellblock', player) in key_layout.sector.regions
|
state.big_key_special, special_region = False, None
|
||||||
|
forced_bk = world.get_region('Hyrule Dungeon Cellblock', player)
|
||||||
|
if forced_bk in key_layout.sector.regions:
|
||||||
|
state.big_key_special, special_region = True, forced_bk
|
||||||
for region in key_layout.start_regions:
|
for region in key_layout.start_regions:
|
||||||
state.visit_region(region, key_checks=True)
|
state.visit_region(region, key_checks=True)
|
||||||
state.add_all_doors_check_keys(region, flat_proposal, world, player)
|
state.add_all_doors_check_keys(region, flat_proposal, world, player)
|
||||||
@@ -1365,7 +1389,7 @@ def create_key_counters(key_layout, world, player):
|
|||||||
if door.bigKey:
|
if door.bigKey:
|
||||||
key_layout.key_logic.bk_doors.add(door)
|
key_layout.key_logic.bk_doors.add(door)
|
||||||
# open the door, if possible
|
# open the door, if possible
|
||||||
if not door.bigKey or not child_state.big_key_special or child_state.big_key_opened:
|
if not door.bigKey or not child_state.big_key_special or child_state.visited(special_region):
|
||||||
open_a_door(door, child_state, flat_proposal)
|
open_a_door(door, child_state, flat_proposal)
|
||||||
expand_key_state(child_state, flat_proposal, world, player)
|
expand_key_state(child_state, flat_proposal, world, player)
|
||||||
code = state_id(child_state, key_layout.flat_prop)
|
code = state_id(child_state, key_layout.flat_prop)
|
||||||
@@ -1393,10 +1417,7 @@ def create_key_counter(state, key_layout, world, player):
|
|||||||
key_counter.other_locations[loc] = None
|
key_counter.other_locations[loc] = None
|
||||||
key_counter.open_doors.update(dict.fromkeys(state.opened_doors))
|
key_counter.open_doors.update(dict.fromkeys(state.opened_doors))
|
||||||
key_counter.used_keys = count_unique_sm_doors(state.opened_doors)
|
key_counter.used_keys = count_unique_sm_doors(state.opened_doors)
|
||||||
if state.big_key_special:
|
key_counter.big_key_opened = state.big_key_opened
|
||||||
key_counter.big_key_opened = state.visited(world.get_region('Hyrule Dungeon Cellblock', player))
|
|
||||||
else:
|
|
||||||
key_counter.big_key_opened = state.big_key_opened
|
|
||||||
return key_counter
|
return key_counter
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
2
Main.py
2
Main.py
@@ -24,7 +24,7 @@ from Fill import distribute_items_cutoff, distribute_items_staleness, distribute
|
|||||||
from ItemList import generate_itempool, difficulties, fill_prizes
|
from ItemList import generate_itempool, difficulties, fill_prizes
|
||||||
from Utils import output_path, parse_player_names
|
from Utils import output_path, parse_player_names
|
||||||
|
|
||||||
__version__ = '0.2.0.0-u'
|
__version__ = '0.2.0.1-u'
|
||||||
|
|
||||||
class EnemizerError(RuntimeError):
|
class EnemizerError(RuntimeError):
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -1,38 +1,16 @@
|
|||||||
# New Features
|
# New Features
|
||||||
|
|
||||||
* Crossed Dungeon generation improvements
|
* Lobby shuffle added as Intensity level 3
|
||||||
* Standard mode generation improvements
|
|
||||||
* Spoiler lists bosses (multiworld compatible)
|
|
||||||
* Bombs escape not valid for Crossed Dungeon
|
|
||||||
* Graph algorithm speed improvement for placements and playthrough
|
|
||||||
* TT Attic Hint tile should have a crystal switch accessible now
|
|
||||||
* Updated to v.31.0.5
|
|
||||||
|
|
||||||
### Experimental features
|
### Experimental features
|
||||||
|
|
||||||
* Moved BK information and total chest keys per dungeon to keysanity menu. The info there requires compass for all info.
|
* Redesign of Keysanity Menu for Crossed Dungeon
|
||||||
* Map still required for on-hud key counter.
|
|
||||||
* Added total counter to keysanity the compass/map screen when you have the compass for the dungeon.
|
|
||||||
* Open "Edge" transitions can now be linked with normal doors
|
|
||||||
* "Straight" staircases (the ones similar to normal doors) can be linked with both normal doors and edges
|
|
||||||
|
|
||||||
#### Couple of temporary debug features added:
|
#### Temporary debug features:
|
||||||
|
|
||||||
* Total item count displays where TFH's goal usually does
|
* Removed the red square in the upper right corner of the hud if the castle gate is closed
|
||||||
* A red square appears in the upper right corner of the hud if the castle gate is closed
|
|
||||||
|
|
||||||
# Bug Fixes
|
# Bug Fixes
|
||||||
|
|
||||||
* Fix for Animated Tiles in crossed dungeon
|
* Fixed a situation where logic did not account properly for Big Key doors in standard Hyrule Castle
|
||||||
* Stonewall hardlock no longer reachable from certain drops (Sewer Drop, some Skull Woods drops) that were previously possible
|
* Fixed a problem ER shuffle generation that did not account for lobbies moving around
|
||||||
* No logic uses less key door logic
|
|
||||||
* Spoiler log encoding
|
|
||||||
* Enemizer settings made consistent with website
|
|
||||||
* Swamp flooded ladders in the basement now requires Flippers
|
|
||||||
* PoD EG Glitch gets killed on transitions (Only when DR is on)
|
|
||||||
* Problem with standard logic fixed wanting you to pass through the tapestry backwards to rescue Zelda
|
|
||||||
* Fixed SRAM corruption issues
|
|
||||||
* Problem with the dungeons requiring you to take Blind through her attic fixed. (Maiden no longer despawns)
|
|
||||||
* Hyrule Castle will not be your DW access in various Entrance Shuffles: simple, restricted, dungeonssimple, dungeonsfull
|
|
||||||
(Also prevents getting stuck in TR opening)
|
|
||||||
* Beatable only (accessibility: none) no longer fails when there are unplaced items
|
|
||||||
2
Rom.py
2
Rom.py
@@ -22,7 +22,7 @@ from EntranceShuffle import door_addresses, exit_ids
|
|||||||
|
|
||||||
|
|
||||||
JAP10HASH = '03a63945398191337e896e5771f77173'
|
JAP10HASH = '03a63945398191337e896e5771f77173'
|
||||||
RANDOMIZERBASEHASH = '7d4881c390855dbe2f9c308bed2e61ef'
|
RANDOMIZERBASEHASH = '094edde26279e8084d525135366fa67c'
|
||||||
|
|
||||||
|
|
||||||
class JsonRom(object):
|
class JsonRom(object):
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
!add = "clc : adc"
|
!add = "clc : adc"
|
||||||
|
!addl = "clc : adc.l"
|
||||||
!sub = "sec : sbc"
|
!sub = "sec : sbc"
|
||||||
!bge = "bcs"
|
!bge = "bcs"
|
||||||
!blt = "bcc"
|
!blt = "bcc"
|
||||||
|
|||||||
@@ -13,11 +13,6 @@ HudAdditions:
|
|||||||
LDX.b $05 : TXA : ORA.w #$2400 : STA !GOAL_DRAW_ADDRESS+10 ; draw 100's digit
|
LDX.b $05 : TXA : ORA.w #$2400 : STA !GOAL_DRAW_ADDRESS+10 ; draw 100's digit
|
||||||
LDX.b $06 : TXA : ORA.w #$2400 : STA !GOAL_DRAW_ADDRESS+12 ; draw 10's digit
|
LDX.b $06 : TXA : ORA.w #$2400 : STA !GOAL_DRAW_ADDRESS+12 ; draw 10's digit
|
||||||
LDX.b $07 : TXA : ORA.w #$2400 : STA !GOAL_DRAW_ADDRESS+14 ; draw 1's digit
|
LDX.b $07 : TXA : ORA.w #$2400 : STA !GOAL_DRAW_ADDRESS+14 ; draw 1's digit
|
||||||
|
|
||||||
lda $7ef29b : and #$0020 : beq +
|
|
||||||
lda #$207f : bra .drawthing
|
|
||||||
+ lda #$345e
|
|
||||||
.drawthing STA !GOAL_DRAW_ADDRESS+16 ; castle gate indicator
|
|
||||||
++
|
++
|
||||||
|
|
||||||
ldx $040c : cpx #$ff : bne + : rts : +
|
ldx $040c : cpx #$ff : bne + : rts : +
|
||||||
@@ -35,35 +30,30 @@ HudAdditions:
|
|||||||
.reminder sta $7ec702
|
.reminder sta $7ec702
|
||||||
+ lda.w DRFlags : and #$0004 : beq .restore
|
+ lda.w DRFlags : and #$0004 : beq .restore
|
||||||
lda $7ef368 : and.l $0098c0, x : beq .restore
|
lda $7ef368 : and.l $0098c0, x : beq .restore
|
||||||
|
|
||||||
; lda #$2811 : sta $7ec740
|
|
||||||
; lda $7ef366 : and.l $0098c0, x : bne .check
|
|
||||||
; lda.w BigKeyStatus, x : bne + ; change this, if bk status changes to one byte
|
|
||||||
; lda #$2574 : bra ++
|
|
||||||
; + cmp #$0002 : bne +
|
|
||||||
; lda #$2420 : bra ++
|
|
||||||
; + lda #$207f : bra ++
|
|
||||||
; .check lda #$2826
|
|
||||||
; ++ sta $7ec742
|
|
||||||
txa : lsr : tax
|
txa : lsr : tax
|
||||||
|
|
||||||
lda $7ef4e0, x : jsr ConvertToDisplay : sta $7ec7a2
|
lda $7ef4e0, x : jsr ConvertToDisplay : sta $7ec7a2
|
||||||
lda #$2830 : sta $7ec7a4
|
lda #$2830 : sta $7ec7a4
|
||||||
lda.w ChestKeys, x : jsr ConvertToDisplay : sta $7ec7a6
|
lda.w ChestKeys, x : jsr ConvertToDisplay : sta $7ec7a6
|
||||||
|
; todo 4b0 no longer in use
|
||||||
; lda #$2871 : sta $7ec780
|
|
||||||
; lda.w TotalKeys, x
|
|
||||||
; sep #$20 : !sub $7ef4b0, x : rep #$20 ; todo 4b0 no longer in use
|
|
||||||
; jsr ConvertToDisplay : sta $7ec782
|
|
||||||
|
|
||||||
.restore
|
.restore
|
||||||
plb : rts
|
plb : rts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
;column distance for BK/Smalls
|
||||||
HudOffsets:
|
HudOffsets:
|
||||||
; none hc east desert aga swamp pod mire skull ice hera tt tr gt
|
; none hc east desert aga swamp pod mire skull ice hera tt tr gt
|
||||||
dw $fffe, $0000, $0006, $0008, $0002, $0010, $000e, $0018, $0012, $0016, $000a, $0014, $001a, $001e
|
dw $fffe, $0000, $0006, $0008, $0002, $0010, $000e, $0018, $0012, $0016, $000a, $0014, $001a, $001e
|
||||||
|
|
||||||
|
; offset from 1644
|
||||||
|
RowOffsets:
|
||||||
|
dw $0000, $0000, $0040, $0080, $0000, $0080, $0040, $0080, $00c0, $0040, $00c0, $0000, $00c0, $0000
|
||||||
|
|
||||||
|
ColumnOffsets:
|
||||||
|
dw $0000, $0000, $0000, $0000, $000a, $000a, $000a, $0014, $000a, $0014, $0000, $0014, $0014, $001e
|
||||||
|
|
||||||
|
|
||||||
DrHudDungeonItemsAdditions:
|
DrHudDungeonItemsAdditions:
|
||||||
{
|
{
|
||||||
jsl DrawHUDDungeonItems
|
jsl DrawHUDDungeonItems
|
||||||
@@ -75,11 +65,16 @@ DrHudDungeonItemsAdditions:
|
|||||||
|
|
||||||
lda !HUD_FLAG : and.w #$0020 : beq + : bra ++ : +
|
lda !HUD_FLAG : and.w #$0020 : beq + : bra ++ : +
|
||||||
lda HUDDungeonItems : and.w #$0003 : bne + : bra ++ : +
|
lda HUDDungeonItems : and.w #$0003 : bne + : bra ++ : +
|
||||||
|
; blank out stuff
|
||||||
|
lda.w #$24f5 : sta $1606 : sta $1610 : sta $161a : sta $1624 : sta $1644
|
||||||
|
sta $164a : sta $1652 : sta $1662
|
||||||
|
ldy #$0000
|
||||||
|
- sta $1706, y : iny #2 : cpy #$001c : bcc -
|
||||||
lda.w #$2810 : sta $1684 ; small keys icon
|
lda.w #$2810 : sta $1684 ; small keys icon
|
||||||
lda.w #$2811 : sta $16c4 ; big key icon
|
lda.w #$2811 : sta $16c4 ; big key icon
|
||||||
lda.w #$2810 : sta $1704 ; small keys icon
|
lda.w #$2810 : sta $1704 ; small keys icon
|
||||||
ldx #$0002
|
ldx #$0002
|
||||||
- lda $7ef364 : and.l $0098c0, x : beq + ; must have compass
|
- lda $7ef368 : and.l $0098c0, x : beq + ; must have map
|
||||||
lda.l HudOffsets, x : tay
|
lda.l HudOffsets, x : tay
|
||||||
jsr BkStatus : sta $16C6, y ; big key status
|
jsr BkStatus : sta $16C6, y ; big key status
|
||||||
phx
|
phx
|
||||||
@@ -88,18 +83,34 @@ DrHudDungeonItemsAdditions:
|
|||||||
plx
|
plx
|
||||||
+ inx #2 : cpx #$001b : bcc -
|
+ inx #2 : cpx #$001b : bcc -
|
||||||
++
|
++
|
||||||
lda !HUD_FLAG : and.w #$0020 : bne + : bra ++ : +
|
lda !HUD_FLAG : and.w #$0020 : bne + : brl ++ : +
|
||||||
lda HUDDungeonItems : and.w #$000c : bne + : bra ++ : +
|
lda HUDDungeonItems : and.w #$000f : bne + : brl ++ : +
|
||||||
lda.w #$24f5 : sta $1704 ; blank
|
; map symbols (do I want these) ; note compass symbol is 2c20
|
||||||
|
lda.w #$2821 : sta $1606 : sta $1610 : sta $161a : sta $1624
|
||||||
|
; blank out a couple thing from old hud
|
||||||
|
lda.w #$24f5 : sta $16e4 : sta $1724
|
||||||
ldx #$0002
|
ldx #$0002
|
||||||
- lda $7ef364 : and.l $0098c0, x : beq + ; must have compass
|
- lda #$0000 ; start of hud area
|
||||||
lda.l HudOffsets, x : tay
|
!addl RowOffsets, x : !addl ColumnOffsets, x : tay
|
||||||
|
lda.l DungeonReminderTable, x : sta $1644, y
|
||||||
|
iny #2
|
||||||
|
lda.w #$24f5 : sta $1644, y ; blank out map spot
|
||||||
|
lda $7ef368 : and.l $0098c0, x : beq + ; must have map
|
||||||
|
lda #$2826 : sta $1644, y ; check mark
|
||||||
|
+ iny #2
|
||||||
|
cpx #$001a : bne +
|
||||||
|
tya : !add #$003c : tay
|
||||||
|
+ lda $7ef364 : and.l $0098c0, x : beq + ; must have compass
|
||||||
phx ; total chest counts
|
phx ; total chest counts
|
||||||
txa : lsr : tax
|
txa : lsr : tax
|
||||||
lda.l TotalLocationsLow, x : jsr ConvertToDisplay2 : sta $1706, y
|
lda.l TotalLocationsHigh, x : jsr ConvertToDisplay2 : sta $1644, y : iny #2
|
||||||
lda.l TotalLocationsHigh, x : jsr ConvertToDisplay2 : sta $16c6, y
|
lda.l TotalLocationsLow, x : jsr ConvertToDisplay2 : sta $1644, y
|
||||||
plx
|
plx
|
||||||
+
|
bra .skipBlanks
|
||||||
|
+ lda.w #$24f5 : sta $1644, y : iny #2 : sta $1644, y
|
||||||
|
.skipBlanks iny #2
|
||||||
|
cpx #$001a : beq +
|
||||||
|
lda.w #$24f5 : sta $1644, y ; blank out spot
|
||||||
+ inx #2 : cpx #$001b : bcc -
|
+ inx #2 : cpx #$001b : bcc -
|
||||||
++
|
++
|
||||||
plp : ply : plx : rtl
|
plp : ply : plx : rtl
|
||||||
@@ -108,7 +119,7 @@ DrHudDungeonItemsAdditions:
|
|||||||
BkStatus:
|
BkStatus:
|
||||||
lda $7ef366 : and.l $0098c0, x : bne +++ ; has the bk already
|
lda $7ef366 : and.l $0098c0, x : bne +++ ; has the bk already
|
||||||
lda.l BigKeyStatus, x : bne ++
|
lda.l BigKeyStatus, x : bne ++
|
||||||
lda #$2482 : rts ; 0/O for no BK
|
lda #$2827 : rts ; 0/O for no BK
|
||||||
++ cmp #$0002 : bne +
|
++ cmp #$0002 : bne +
|
||||||
lda #$2420 : rts ; symbol for BnC
|
lda #$2420 : rts ; symbol for BnC
|
||||||
+ lda #$24f5 : rts ; black otherwise
|
+ lda #$24f5 : rts ; black otherwise
|
||||||
@@ -124,29 +135,7 @@ ConvertToDisplay2:
|
|||||||
cmp #$000a : !blt +
|
cmp #$000a : !blt +
|
||||||
!add #$2553 : rts
|
!add #$2553 : rts
|
||||||
+ !add #$2816 : rts
|
+ !add #$2816 : rts
|
||||||
++ lda #$2483 : rts ; 0/O for 0 or placeholder digit
|
++ lda #$2827 : rts ; 0/O for 0 or placeholder digit ;2483
|
||||||
|
|
||||||
;CountChestKeys:
|
|
||||||
; jsl ItemDowngradeFix
|
|
||||||
; jsr CountChest
|
|
||||||
; rtl
|
|
||||||
|
|
||||||
;CountChest:
|
|
||||||
; lda !MULTIWORLD_ITEM_PLAYER_ID : bne .end
|
|
||||||
; cpy #$24 : beq +
|
|
||||||
; cpy #$a0 : !blt .end
|
|
||||||
; cpy #$ae : !bge .end
|
|
||||||
; pha : phx
|
|
||||||
; tya : and #$0f : bne ++
|
|
||||||
; inc a
|
|
||||||
; ++ tax : bra .count
|
|
||||||
; + pha : phx
|
|
||||||
; lda $040c : lsr : tax
|
|
||||||
; .count
|
|
||||||
; lda $7ef4b0, x : inc : sta $7ef4b0, x
|
|
||||||
; lda $7ef4e0, x : inc : sta $7ef4e0, x
|
|
||||||
; .restore plx : pla
|
|
||||||
; .end rts
|
|
||||||
|
|
||||||
CountAbsorbedKeys:
|
CountAbsorbedKeys:
|
||||||
jsl IncrementSmallKeysNoPrimary : phx
|
jsl IncrementSmallKeysNoPrimary : phx
|
||||||
@@ -155,20 +144,6 @@ CountAbsorbedKeys:
|
|||||||
lda $7ef4b0, x : inc : sta $7ef4b0, x
|
lda $7ef4b0, x : inc : sta $7ef4b0, x
|
||||||
+ plx : rtl
|
+ plx : rtl
|
||||||
|
|
||||||
;CountBonkItem:
|
|
||||||
; jsl GiveBonkItem
|
|
||||||
; lda $a0 ; check room ID - only bonk keys in 2 rooms so we're just checking the lower byte
|
|
||||||
; cmp #115 : bne + ; Desert Bonk Key
|
|
||||||
; lda.l BonkKey_Desert
|
|
||||||
; bra ++
|
|
||||||
; + : cmp #140 : bne + ; GTower Bonk Key
|
|
||||||
; lda.l BonkKey_GTower
|
|
||||||
; bra ++
|
|
||||||
; + lda.b #$24 ; default to small key
|
|
||||||
; ++ cmp #$24 : bne +
|
|
||||||
; phy : tay : jsr CountChest : ply
|
|
||||||
; + rtl
|
|
||||||
|
|
||||||
;================================================================================
|
;================================================================================
|
||||||
; 16-bit A, 8-bit X
|
; 16-bit A, 8-bit X
|
||||||
; in: A(b) - Byte to Convert
|
; in: A(b) - Byte to Convert
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user