Prevent HUD from showing key counter when in the overworld. (Aga 2 doesn't always clear the dungeon indicator)

Fixed key logic regarding certain isolated "important" locations
Fixed a problem with keydropshuffle thinking certain progression items are keys
A couple of inverted rules fixed (from an outstanding ER pull request)
A more accurate count of which locations are blocked by the big key in Ganon's Tower
Updated base rom to 31.0.7 (includes potential hera basement cage fix)
This commit is contained in:
aerinon
2020-11-30 15:54:39 -07:00
parent ef3bc0aee0
commit 1b060f893b
8 changed files with 32 additions and 19 deletions

View File

@@ -169,21 +169,11 @@ class KeyCounter(object):
self.big_key_opened = False self.big_key_opened = False
self.important_location = False self.important_location = False
self.other_locations = {} self.other_locations = {}
self.important_locations = {}
def used_smalls_loc(self, reserve=0): def used_smalls_loc(self, reserve=0):
return max(self.used_keys + reserve - len(self.key_only_locations), 0) return max(self.used_keys + reserve - len(self.key_only_locations), 0)
def copy(self):
ret = KeyCounter(self.max_chests)
ret.free_locations.update(self.free_locations)
ret.key_only_locations.update(self.key_only_locations)
ret.child_doors.update(self.child_doors)
ret.used_keys = self.used_keys
ret.open_doors.update(self.open_doors)
ret.big_key_opened = self.big_key_opened
ret.important_location = self.important_location
return ret
def build_key_layout(builder, start_regions, proposal, world, player): def build_key_layout(builder, start_regions, proposal, world, player):
key_layout = KeyLayout(builder.master_sector, start_regions, proposal) key_layout = KeyLayout(builder.master_sector, start_regions, proposal)
@@ -540,6 +530,9 @@ def relative_empty_counter(odd_counter, key_counter):
return False return False
if len(set(odd_counter.free_locations).difference(key_counter.free_locations)) > 0: if len(set(odd_counter.free_locations).difference(key_counter.free_locations)) > 0:
return False return False
# important only
if len(set(odd_counter.important_locations).difference(key_counter.important_locations)) > 0:
return False
new_child_door = False new_child_door = False
for child in odd_counter.child_doors: for child in odd_counter.child_doors:
if unique_child_door(child, key_counter): if unique_child_door(child, key_counter):
@@ -555,6 +548,9 @@ def relative_empty_counter_2(odd_counter, key_counter):
return False return False
if len(set(odd_counter.free_locations).difference(key_counter.free_locations)) > 0: if len(set(odd_counter.free_locations).difference(key_counter.free_locations)) > 0:
return False return False
# important only
if len(set(odd_counter.important_locations).difference(key_counter.important_locations)) > 0:
return False
for child in odd_counter.child_doors: for child in odd_counter.child_doors:
if unique_child_door_2(child, key_counter): if unique_child_door_2(child, key_counter):
return False return False
@@ -981,11 +977,15 @@ def filter_big_chest(locations):
def count_locations_exclude_logic(locations, key_logic): def count_locations_exclude_logic(locations, key_logic):
cnt = 0 cnt = 0
for loc in locations: for loc in locations:
if loc not in key_logic.bk_restricted and not loc.forced_item and not prize_or_event(loc): if not location_is_bk_locked(loc, key_logic) and not loc.forced_item and not prize_or_event(loc):
cnt += 1 cnt += 1
return cnt return cnt
def location_is_bk_locked(loc, key_logic):
return loc in key_logic.bk_chests or loc in key_logic.bk_locked
def prize_or_event(loc): def prize_or_event(loc):
return loc.name in dungeon_events or '- Prize' in loc.name or loc.name in ['Agahnim 1', 'Agahnim 2'] return loc.name in dungeon_events or '- Prize' in loc.name or loc.name in ['Agahnim 1', 'Agahnim 2']
@@ -1417,6 +1417,7 @@ def create_key_counter(state, key_layout, world, player):
if important_location(loc, world, player): if important_location(loc, world, player):
key_counter.important_location = True key_counter.important_location = True
key_counter.other_locations[loc] = None key_counter.other_locations[loc] = None
key_counter.important_locations[loc] = None
elif loc.forced_item and loc.item.name == key_layout.key_logic.small_key_name: elif loc.forced_item and loc.item.name == key_layout.key_logic.small_key_name:
key_counter.key_only_locations[loc] = None key_counter.key_only_locations[loc] = None
elif loc.forced_item and loc.item.name == key_layout.key_logic.bk_name: elif loc.forced_item and loc.item.name == key_layout.key_logic.bk_name:
@@ -1456,6 +1457,7 @@ def create_odd_key_counter(door, parent_counter, key_layout, world, player):
odd_counter.key_only_locations = dict_difference(next_counter.key_only_locations, parent_counter.key_only_locations) odd_counter.key_only_locations = dict_difference(next_counter.key_only_locations, parent_counter.key_only_locations)
odd_counter.child_doors = dict_difference(next_counter.child_doors, parent_counter.child_doors) odd_counter.child_doors = dict_difference(next_counter.child_doors, parent_counter.child_doors)
odd_counter.other_locations = dict_difference(next_counter.other_locations, parent_counter.other_locations) odd_counter.other_locations = dict_difference(next_counter.other_locations, parent_counter.other_locations)
odd_counter.important_locations = dict_difference(next_counter.important_locations, parent_counter.important_locations)
for loc in odd_counter.other_locations: for loc in odd_counter.other_locations:
if important_location(loc, world, player): if important_location(loc, world, player):
odd_counter.important_location = True odd_counter.important_location = True

View File

@@ -24,7 +24,7 @@ from Fill import distribute_items_cutoff, distribute_items_staleness, distribute
from ItemList import generate_itempool, difficulties, fill_prizes, fill_specific_items from ItemList import generate_itempool, difficulties, fill_prizes, fill_specific_items
from Utils import output_path, parse_player_names from Utils import output_path, parse_player_names
__version__ = '0.2.0.15u' __version__ = '0.2.0.16u'
class EnemizerError(RuntimeError): class EnemizerError(RuntimeError):
pass pass

View File

@@ -92,6 +92,13 @@ testing to verify logic is all good.
# Bug Fixes # Bug Fixes
* 2.0.16u
* Prevent HUD from showing key counter when in the overworld. (Aga 2 doesn't always clear the dungeon indicator)
* Fixed key logic regarding certain isolated "important" locations
* Fixed a problem with keydropshuffle thinking certain progression items are keys
* A couple of inverted rules fixed
* A more accurate count of which locations are blocked by teh big key in Ganon's Tower
* Updated base rom to 31.0.7 (includes potential hera basement cage fix)
* 2.0.15u * 2.0.15u
* Allow Aga Tower lobby door as a a paired keydoor (typo) * Allow Aga Tower lobby door as a a paired keydoor (typo)
* Fix portal check for multi-entrance dungeons * Fix portal check for multi-entrance dungeons

2
Rom.py
View File

@@ -26,7 +26,7 @@ from EntranceShuffle import door_addresses, exit_ids
JAP10HASH = '03a63945398191337e896e5771f77173' JAP10HASH = '03a63945398191337e896e5771f77173'
RANDOMIZERBASEHASH = '55b2f851e5d643e1e72befc631ea3c6d' RANDOMIZERBASEHASH = '185a0f74ab0e2ce8899c8d7d309ca68c'
class JsonRom(object): class JsonRom(object):

View File

@@ -467,7 +467,7 @@ def default_rules(world, player):
set_rule(world.get_entrance('East Dark World Bridge', player), lambda state: state.has_Pearl(player) and state.has('Hammer', player)) set_rule(world.get_entrance('East Dark World Bridge', player), lambda state: state.has_Pearl(player) and state.has('Hammer', player))
set_rule(world.get_entrance('Lake Hylia Island Mirror Spot', player), lambda state: state.has_Pearl(player) and state.has_Mirror(player) and state.has('Flippers', player)) set_rule(world.get_entrance('Lake Hylia Island Mirror Spot', player), lambda state: state.has_Pearl(player) and state.has_Mirror(player) and state.has('Flippers', player))
set_rule(world.get_entrance('Lake Hylia Central Island Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Lake Hylia Central Island Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('East Dark World River Pier', player), lambda state: state.has_Pearl(player) and state.has('Flippers', player)) # ToDo any fake flipper set up? set_rule(world.get_entrance('East Dark World River Pier', player), lambda state: state.has_Pearl(player))
set_rule(world.get_entrance('Graveyard Ledge Mirror Spot', player), lambda state: state.has_Pearl(player) and state.has_Mirror(player)) set_rule(world.get_entrance('Graveyard Ledge Mirror Spot', player), lambda state: state.has_Pearl(player) and state.has_Mirror(player))
set_rule(world.get_entrance('Bumper Cave Entrance Rock', player), lambda state: state.has_Pearl(player) and state.can_lift_rocks(player)) set_rule(world.get_entrance('Bumper Cave Entrance Rock', player), lambda state: state.has_Pearl(player) and state.can_lift_rocks(player))
set_rule(world.get_entrance('Bumper Cave Ledge Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Bumper Cave Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
@@ -513,6 +513,7 @@ def inverted_rules(world, player):
set_rule(world.get_entrance('Castle Ledge S&Q', player), lambda state: state.has_Mirror(player) and state.has('Beat Agahnim 1', player)) set_rule(world.get_entrance('Castle Ledge S&Q', player), lambda state: state.has_Mirror(player) and state.has('Beat Agahnim 1', player))
# overworld requirements # overworld requirements
set_rule(world.get_location('Ice Rod Cave', player), lambda state: state.has_Pearl(player))
set_rule(world.get_location('Maze Race', player), lambda state: state.has_Pearl(player)) set_rule(world.get_location('Maze Race', player), lambda state: state.has_Pearl(player))
set_rule(world.get_entrance('Mini Moldorm Cave', player), lambda state: state.has_Pearl(player)) set_rule(world.get_entrance('Mini Moldorm Cave', player), lambda state: state.has_Pearl(player))
set_rule(world.get_entrance('Light Hype Fairy', player), lambda state: state.has_Pearl(player)) set_rule(world.get_entrance('Light Hype Fairy', player), lambda state: state.has_Pearl(player))
@@ -664,6 +665,7 @@ def no_glitches_rules(world, player):
add_rule(world.get_entrance('Dark Lake Hylia Drop (East)', player), lambda state: state.has_Pearl(player) and state.has('Flippers', player)) add_rule(world.get_entrance('Dark Lake Hylia Drop (East)', player), lambda state: state.has_Pearl(player) and state.has('Flippers', player))
add_rule(world.get_entrance('Dark Lake Hylia Teleporter', player), lambda state: state.has_Pearl(player) and state.has('Flippers', player) and (state.has('Hammer', player) or state.can_lift_rocks(player))) add_rule(world.get_entrance('Dark Lake Hylia Teleporter', player), lambda state: state.has_Pearl(player) and state.has('Flippers', player) and (state.has('Hammer', player) or state.can_lift_rocks(player)))
add_rule(world.get_entrance('Dark Lake Hylia Ledge Drop', player), lambda state: state.has_Pearl(player) and state.has('Flippers', player)) add_rule(world.get_entrance('Dark Lake Hylia Ledge Drop', player), lambda state: state.has_Pearl(player) and state.has('Flippers', player))
add_rule(world.get_entrance('East Dark World River Pier', player), lambda state: state.has('Flippers', player))
else: else:
add_rule(world.get_entrance('Zoras River', player), lambda state: state.has_Pearl(player) and (state.has('Flippers', player) or state.can_lift_rocks(player))) add_rule(world.get_entrance('Zoras River', player), lambda state: state.has_Pearl(player) and (state.has('Flippers', player) or state.can_lift_rocks(player)))
add_rule(world.get_entrance('Lake Hylia Central Island Pier', player), lambda state: state.has_Pearl(player) and state.has('Flippers', player)) # can be fake flippered to add_rule(world.get_entrance('Lake Hylia Central Island Pier', player), lambda state: state.has_Pearl(player) and state.has('Flippers', player)) # can be fake flippered to
@@ -673,6 +675,7 @@ def no_glitches_rules(world, player):
add_rule(world.get_entrance('Dark Lake Hylia Teleporter', player), lambda state: state.has('Flippers', player) and (state.has('Hammer', player) or state.can_lift_rocks(player))) add_rule(world.get_entrance('Dark Lake Hylia Teleporter', player), lambda state: state.has('Flippers', player) and (state.has('Hammer', player) or state.can_lift_rocks(player)))
add_rule(world.get_entrance('Dark Lake Hylia Ledge Drop', player), lambda state: state.has('Flippers', player)) add_rule(world.get_entrance('Dark Lake Hylia Ledge Drop', player), lambda state: state.has('Flippers', player))
add_rule(world.get_entrance('East Dark World Pier', player), lambda state: state.has('Flippers', player)) add_rule(world.get_entrance('East Dark World Pier', player), lambda state: state.has('Flippers', player))
add_rule(world.get_entrance('East Dark World River Pier', player), lambda state: state.has('Flippers', player))
# todo: move some dungeon rules to no glictes logic - see these for examples # todo: move some dungeon rules to no glictes logic - see these for examples
# add_rule(world.get_entrance('Ganons Tower (Hookshot Room)', player), lambda state: state.has('Hookshot', player) or state.has_Boots(player)) # add_rule(world.get_entrance('Ganons Tower (Hookshot Room)', player), lambda state: state.has('Hookshot', player) or state.has_Boots(player))

View File

@@ -15,8 +15,9 @@ HudAdditions:
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
++ ++
ldx $040c : cpx #$ff : bne + : rts : + LDX $1B : BNE + : RTS : + ; Skip if outdoors
lda.l DRMode : bne + : rts : + ldx $040c : cpx #$ff : bne + : rts : + ; Skip if not in dungeon
lda.l DRMode : bne + : rts : + ; Skip if not door rando
phb : phk : plb phb : phk : plb
lda $7ef364 : and.l $0098c0, x : beq + lda $7ef364 : and.l $0098c0, x : beq +
lda.w CompassBossIndicator, x : and #$00ff : cmp $a0 : bne + lda.w CompassBossIndicator, x : and #$00ff : cmp $a0 : bne +

View File

@@ -126,7 +126,7 @@ KeyGet:
lda !MULTIWORLD_ITEM_PLAYER_ID : bne .receive lda !MULTIWORLD_ITEM_PLAYER_ID : bne .receive
phx phx
lda $040c : lsr : tax lda $040c : lsr : tax
lda $00 : cmp KeyTable, x : bne + lda $00 : CMP.l KeyTable, x : bne +
- JSL.l FullInventoryExternal : jsl CountChestKeyLong : plx : pla : rtl - JSL.l FullInventoryExternal : jsl CountChestKeyLong : plx : pla : rtl
+ cmp #$af : beq - ; universal key + cmp #$af : beq - ; universal key
cmp #$24 : beq - ; small key for this dungeon cmp #$24 : beq - ; small key for this dungeon

Binary file not shown.