diff --git a/worlds/alttp/ItemPool.py b/worlds/alttp/ItemPool.py index 69ecadc79d07..125475561bb2 100644 --- a/worlds/alttp/ItemPool.py +++ b/worlds/alttp/ItemPool.py @@ -276,13 +276,14 @@ def generate_itempool(world): # set up item pool additional_triforce_pieces = 0 + treasure_hunt_total = 0 if multiworld.custom: - pool, placed_items, precollected_items, clock_mode, treasure_hunt_count = ( + pool, placed_items, precollected_items, clock_mode, treasure_hunt_required = ( make_custom_item_pool(multiworld, player)) multiworld.rupoor_cost = min(multiworld.customitemarray[67], 9999) else: - pool, placed_items, precollected_items, clock_mode, treasure_hunt_count, additional_triforce_pieces = ( - get_pool_core(multiworld, player)) + (pool, placed_items, precollected_items, clock_mode, treasure_hunt_required, treasure_hunt_total, + additional_triforce_pieces) = get_pool_core(multiworld, player) for item in precollected_items: multiworld.push_precollected(item_factory(item, world)) @@ -337,7 +338,8 @@ def generate_itempool(world): if clock_mode: world.clock_mode = clock_mode - multiworld.worlds[player].treasure_hunt_count = treasure_hunt_count % 999 + multiworld.worlds[player].treasure_hunt_required = treasure_hunt_required % 999 + multiworld.worlds[player].treasure_hunt_total = treasure_hunt_total dungeon_items = [item for item in get_dungeon_item_pool_player(world) if item.name not in multiworld.worlds[player].dungeon_local_item_names] @@ -590,7 +592,8 @@ def get_pool_core(world, player: int): placed_items = {} precollected_items = [] clock_mode: str = "" - treasure_hunt_count: int = 1 + treasure_hunt_required: int = 0 + treasure_hunt_total: int = 0 diff = difficulties[difficulty] pool.extend(diff.alwaysitems) @@ -679,20 +682,21 @@ def place_item(loc, item): if 'triforce_hunt' in goal: if world.triforce_pieces_mode[player].value == TriforcePiecesMode.option_extra: - triforce_pieces = world.triforce_pieces_available[player].value + world.triforce_pieces_extra[player].value + treasure_hunt_total = (world.triforce_pieces_available[player].value + + world.triforce_pieces_extra[player].value) elif world.triforce_pieces_mode[player].value == TriforcePiecesMode.option_percentage: percentage = float(world.triforce_pieces_percentage[player].value) / 100 - triforce_pieces = int(round(world.triforce_pieces_required[player].value * percentage, 0)) + treasure_hunt_total = int(round(world.triforce_pieces_required[player].value * percentage, 0)) else: # available - triforce_pieces = world.triforce_pieces_available[player].value + treasure_hunt_total = world.triforce_pieces_available[player].value - triforce_pieces = min(90, max(triforce_pieces, world.triforce_pieces_required[player].value)) + triforce_pieces = min(90, max(treasure_hunt_total, world.triforce_pieces_required[player].value)) pieces_in_core = min(extraitems, triforce_pieces) additional_pieces_to_place = triforce_pieces - pieces_in_core pool.extend(["Triforce Piece"] * pieces_in_core) extraitems -= pieces_in_core - treasure_hunt_count = world.triforce_pieces_required[player].value + treasure_hunt_required = world.triforce_pieces_required[player].value for extra in diff.extras: if extraitems >= len(extra): @@ -733,7 +737,7 @@ def place_item(loc, item): place_item(key_location, "Small Key (Universal)") pool = pool[:-3] - return (pool, placed_items, precollected_items, clock_mode, treasure_hunt_count, + return (pool, placed_items, precollected_items, clock_mode, treasure_hunt_required, treasure_hunt_total, additional_pieces_to_place) @@ -749,7 +753,8 @@ def make_custom_item_pool(world, player): placed_items = {} precollected_items = [] clock_mode: str = "" - treasure_hunt_count: int = 1 + treasure_hunt_required: int = 0 + treasure_hunt_total: int = 0 def place_item(loc, item): assert loc not in placed_items, "cannot place item twice" @@ -844,7 +849,7 @@ def place_item(loc, item): if "triforce" in world.goal[player]: pool.extend(["Triforce Piece"] * world.triforce_pieces_available[player]) itemtotal += world.triforce_pieces_available[player] - treasure_hunt_count = world.triforce_pieces_required[player] + treasure_hunt_required = world.triforce_pieces_required[player] if timer in ['display', 'timed', 'timed_countdown']: clock_mode = 'countdown' if timer == 'timed_countdown' else 'stopwatch' @@ -889,4 +894,4 @@ def place_item(loc, item): pool.extend(['Nothing'] * (total_items_to_place - itemtotal)) logging.warning(f"Pool was filled up with {total_items_to_place - itemtotal} Nothing's for player {player}") - return (pool, placed_items, precollected_items, clock_mode, treasure_hunt_count) + return (pool, placed_items, precollected_items, clock_mode, treasure_hunt_required) diff --git a/worlds/alttp/Rom.py b/worlds/alttp/Rom.py index 7c3c87683a37..05460e0f9b8c 100644 --- a/worlds/alttp/Rom.py +++ b/worlds/alttp/Rom.py @@ -433,7 +433,7 @@ def patch_enemizer(world, rom: LocalRom, enemizercli, output_directory): if multiworld.key_drop_shuffle[player]: key_drop_enemies = { 0x4DA20, 0x4DA5C, 0x4DB7F, 0x4DD73, 0x4DDC3, 0x4DE07, 0x4E201, - 0x4E20A, 0x4E326, 0x4E4F7, 0x4E686, 0x4E70C, 0x4E7C8, 0x4E7FA + 0x4E20A, 0x4E326, 0x4E4F7, 0x4E687, 0x4E70C, 0x4E7C8, 0x4E7FA } for enemy in key_drop_enemies: if rom.read_byte(enemy) == 0x12: @@ -1269,7 +1269,7 @@ def chunk(l, n): rom.write_int32(0x18020C, 0) # starting time (in frames, sint32) # set up goals for treasure hunt - rom.write_int16(0x180163, local_world.treasure_hunt_count) + rom.write_int16(0x180163, local_world.treasure_hunt_required) rom.write_bytes(0x180165, [0x0E, 0x28]) # Triforce Piece Sprite rom.write_byte(0x180194, 1) # Must turn in triforced pieces (instant win not enabled) @@ -2482,16 +2482,16 @@ def hint_text(dest, ped_hint=False): tt['sign_ganon'] = 'Go find the Triforce pieces with your friends... Ganon is invincible!' else: tt['sign_ganon'] = 'Go find the Triforce pieces... Ganon is invincible!' - if w.treasure_hunt_count > 1: + if w.treasure_hunt_required > 1: tt['murahdahla'] = "Hello @. I\nam Murahdahla, brother of\nSahasrahla and Aginah. Behold the power of\n" \ "invisibility.\n\n\n\n… … …\n\nWait! you can see me? I knew I should have\n" \ "hidden in a hollow tree. If you bring\n%d Triforce pieces out of %d, I can reassemble it." % \ - (w.treasure_hunt_count, world.triforce_pieces_available[player]) + (w.treasure_hunt_required, w.treasure_hunt_total) else: tt['murahdahla'] = "Hello @. I\nam Murahdahla, brother of\nSahasrahla and Aginah. Behold the power of\n" \ "invisibility.\n\n\n\n… … …\n\nWait! you can see me? I knew I should have\n" \ "hidden in a hollow tree. If you bring\n%d Triforce piece out of %d, I can reassemble it." % \ - (w.treasure_hunt_count, world.triforce_pieces_available[player]) + (w.treasure_hunt_required, w.treasure_hunt_total) elif world.goal[player] in ['pedestal']: tt['ganon_fall_in_alt'] = 'Why are you even here?\n You can\'t even hurt me! Your goal is at the pedestal.' tt['ganon_phase_3_alt'] = 'Seriously? Go Away, I will not Die.' @@ -2500,20 +2500,20 @@ def hint_text(dest, ped_hint=False): tt['ganon_fall_in'] = Ganon1_texts[local_random.randint(0, len(Ganon1_texts) - 1)] tt['ganon_fall_in_alt'] = 'You cannot defeat me until you finish your goal!' tt['ganon_phase_3_alt'] = 'Got wax in\nyour ears?\nI can not die!' - if w.treasure_hunt_count > 1: + if w.treasure_hunt_required > 1: if world.goal[player] == 'ganon_triforce_hunt' and world.players > 1: tt['sign_ganon'] = 'You need to find %d Triforce pieces out of %d with your friends to defeat Ganon.' % \ - (w.treasure_hunt_count, world.triforce_pieces_available[player]) + (w.treasure_hunt_required, w.treasure_hunt_total) elif world.goal[player] in ['ganon_triforce_hunt', 'local_ganon_triforce_hunt']: tt['sign_ganon'] = 'You need to find %d Triforce pieces out of %d to defeat Ganon.' % \ - (w.treasure_hunt_count, world.triforce_pieces_available[player]) + (w.treasure_hunt_required, w.treasure_hunt_total) else: if world.goal[player] == 'ganon_triforce_hunt' and world.players > 1: tt['sign_ganon'] = 'You need to find %d Triforce piece out of %d with your friends to defeat Ganon.' % \ - (w.treasure_hunt_count, world.triforce_pieces_available[player]) + (w.treasure_hunt_required, w.treasure_hunt_total) elif world.goal[player] in ['ganon_triforce_hunt', 'local_ganon_triforce_hunt']: tt['sign_ganon'] = 'You need to find %d Triforce piece out of %d to defeat Ganon.' % \ - (w.treasure_hunt_count, world.triforce_pieces_available[player]) + (w.treasure_hunt_required, w.treasure_hunt_total) tt['kakariko_tavern_fisherman'] = TavernMan_texts[local_random.randint(0, len(TavernMan_texts) - 1)] diff --git a/worlds/alttp/Rules.py b/worlds/alttp/Rules.py index 5e4635fa2754..e13f0914f93b 100644 --- a/worlds/alttp/Rules.py +++ b/worlds/alttp/Rules.py @@ -554,8 +554,8 @@ def global_rules(multiworld: MultiWorld, player: int): set_rule(multiworld.get_location('Ganons Tower - Firesnake Room', player), lambda state: state._lttp_has_key('Small Key (Ganons Tower)', player, 7) or ((item_name_in_location_names(state, 'Big Key (Ganons Tower)', player, zip(randomizer_room_chests, [player] * len(randomizer_room_chests))) or item_name_in_location_names(state, 'Small Key (Ganons Tower)', player, [('Ganons Tower - Firesnake Room', player)])) and state._lttp_has_key('Small Key (Ganons Tower)', player, 5))) for location in randomizer_room_chests: - set_rule(multiworld.get_location(location, player), lambda state: state._lttp_has_key('Small Key (Ganons Tower)', player, 8) or ( - item_name_in_location_names(state, 'Big Key (Ganons Tower)', player, zip(randomizer_room_chests, [player] * len(randomizer_room_chests))) and state._lttp_has_key('Small Key (Ganons Tower)', player, 6))) + set_rule(multiworld.get_location(location, player), lambda state: can_use_bombs(state, player) and (state._lttp_has_key('Small Key (Ganons Tower)', player, 8) or ( + item_name_in_location_names(state, 'Big Key (Ganons Tower)', player, zip(randomizer_room_chests, [player] * len(randomizer_room_chests))) and state._lttp_has_key('Small Key (Ganons Tower)', player, 6)))) # Once again it is possible to need more than 7 keys... set_rule(multiworld.get_entrance('Ganons Tower (Tile Room) Key Door', player), lambda state: state.has('Fire Rod', player) and (state._lttp_has_key('Small Key (Ganons Tower)', player, 7) or ( diff --git a/worlds/alttp/StateHelpers.py b/worlds/alttp/StateHelpers.py index fe3a43ee0f55..964a77fefbaf 100644 --- a/worlds/alttp/StateHelpers.py +++ b/worlds/alttp/StateHelpers.py @@ -30,7 +30,7 @@ def can_shoot_arrows(state: CollectionState, player: int) -> bool: def has_triforce_pieces(state: CollectionState, player: int) -> bool: - count = state.multiworld.worlds[player].treasure_hunt_count + count = state.multiworld.worlds[player].treasure_hunt_required return state.count('Triforce Piece', player) + state.count('Power Star', player) >= count diff --git a/worlds/alttp/__init__.py b/worlds/alttp/__init__.py index f4a374ce0201..ae3dfe9e3b1a 100644 --- a/worlds/alttp/__init__.py +++ b/worlds/alttp/__init__.py @@ -261,7 +261,8 @@ def enemizer_path(self) -> str: fix_fake_world: bool = True clock_mode: str = "" - treasure_hunt_count: int = 1 + treasure_hunt_required: int = 0 + treasure_hunt_total: int = 0 def __init__(self, *args, **kwargs): self.dungeon_local_item_names = set() diff --git a/worlds/alttp/test/dungeons/TestDungeon.py b/worlds/alttp/test/dungeons/TestDungeon.py index a31ddd68b2e1..91fc462c4ecc 100644 --- a/worlds/alttp/test/dungeons/TestDungeon.py +++ b/worlds/alttp/test/dungeons/TestDungeon.py @@ -15,7 +15,7 @@ def setUp(self): self.remove_exits = [] # Block dungeon exits self.multiworld.worlds[1].difficulty_requirements = difficulties['normal'] self.multiworld.bombless_start[1].value = True - self.multiworld.shuffle_capacity_upgrades[1].value = True + self.multiworld.shuffle_capacity_upgrades[1].value = 2 create_regions(self.multiworld, 1) self.multiworld.worlds[1].create_dungeons() create_shops(self.multiworld, 1) diff --git a/worlds/alttp/test/dungeons/TestGanonsTower.py b/worlds/alttp/test/dungeons/TestGanonsTower.py index 1e70f580de4e..08274d0fe7d9 100644 --- a/worlds/alttp/test/dungeons/TestGanonsTower.py +++ b/worlds/alttp/test/dungeons/TestGanonsTower.py @@ -33,22 +33,26 @@ def testGanonsTower(self): ["Ganons Tower - Randomizer Room - Top Left", False, []], ["Ganons Tower - Randomizer Room - Top Left", False, [], ['Hammer']], ["Ganons Tower - Randomizer Room - Top Left", False, [], ['Hookshot']], - ["Ganons Tower - Randomizer Room - Top Left", True, ['Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Hookshot', 'Hammer']], + ["Ganons Tower - Randomizer Room - Top Left", False, [], ['Bomb Upgrade (50)']], + ["Ganons Tower - Randomizer Room - Top Left", True, ['Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Hookshot', 'Hammer', 'Bomb Upgrade (50)']], ["Ganons Tower - Randomizer Room - Top Right", False, []], ["Ganons Tower - Randomizer Room - Top Right", False, [], ['Hammer']], ["Ganons Tower - Randomizer Room - Top Right", False, [], ['Hookshot']], - ["Ganons Tower - Randomizer Room - Top Right", True, ['Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Hookshot', 'Hammer']], + ["Ganons Tower - Randomizer Room - Top Right", False, [], ['Bomb Upgrade (50)']], + ["Ganons Tower - Randomizer Room - Top Right", True, ['Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Hookshot', 'Hammer', 'Bomb Upgrade (50)']], ["Ganons Tower - Randomizer Room - Bottom Left", False, []], ["Ganons Tower - Randomizer Room - Bottom Left", False, [], ['Hammer']], ["Ganons Tower - Randomizer Room - Bottom Left", False, [], ['Hookshot']], - ["Ganons Tower - Randomizer Room - Bottom Left", True, ['Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Hookshot', 'Hammer']], + ["Ganons Tower - Randomizer Room - Bottom Left", False, [], ['Bomb Upgrade (50)']], + ["Ganons Tower - Randomizer Room - Bottom Left", True, ['Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Hookshot', 'Hammer', 'Bomb Upgrade (50)']], ["Ganons Tower - Randomizer Room - Bottom Right", False, []], ["Ganons Tower - Randomizer Room - Bottom Right", False, [], ['Hammer']], ["Ganons Tower - Randomizer Room - Bottom Right", False, [], ['Hookshot']], - ["Ganons Tower - Randomizer Room - Bottom Right", True, ['Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Hookshot', 'Hammer']], + ["Ganons Tower - Randomizer Room - Bottom Right", False, [], ['Bomb Upgrade (50)']], + ["Ganons Tower - Randomizer Room - Bottom Right", True, ['Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Small Key (Ganons Tower)', 'Hookshot', 'Hammer', 'Bomb Upgrade (50)']], ["Ganons Tower - Firesnake Room", False, []], ["Ganons Tower - Firesnake Room", False, [], ['Hammer']], diff --git a/worlds/alttp/test/inverted/TestInverted.py b/worlds/alttp/test/inverted/TestInverted.py index 59a3d7f5f4fa..0a2aa7a18653 100644 --- a/worlds/alttp/test/inverted/TestInverted.py +++ b/worlds/alttp/test/inverted/TestInverted.py @@ -16,7 +16,7 @@ def setUp(self): self.multiworld.worlds[1].difficulty_requirements = difficulties['normal'] self.multiworld.mode[1].value = 2 self.multiworld.bombless_start[1].value = True - self.multiworld.shuffle_capacity_upgrades[1].value = True + self.multiworld.shuffle_capacity_upgrades[1].value = 2 create_inverted_regions(self.multiworld, 1) self.world.create_dungeons() create_shops(self.multiworld, 1) diff --git a/worlds/alttp/test/inverted_minor_glitches/TestInvertedMinor.py b/worlds/alttp/test/inverted_minor_glitches/TestInvertedMinor.py index 029de39bc232..a8fa5c808c3b 100644 --- a/worlds/alttp/test/inverted_minor_glitches/TestInvertedMinor.py +++ b/worlds/alttp/test/inverted_minor_glitches/TestInvertedMinor.py @@ -17,7 +17,7 @@ def setUp(self): self.multiworld.mode[1].value = 2 self.multiworld.glitches_required[1] = GlitchesRequired.from_any("minor_glitches") self.multiworld.bombless_start[1].value = True - self.multiworld.shuffle_capacity_upgrades[1].value = True + self.multiworld.shuffle_capacity_upgrades[1].value = 2 self.multiworld.worlds[1].difficulty_requirements = difficulties['normal'] create_inverted_regions(self.multiworld, 1) self.world.create_dungeons() diff --git a/worlds/alttp/test/inverted_owg/TestInvertedOWG.py b/worlds/alttp/test/inverted_owg/TestInvertedOWG.py index 86afae3e2a67..bbdf0f792444 100644 --- a/worlds/alttp/test/inverted_owg/TestInvertedOWG.py +++ b/worlds/alttp/test/inverted_owg/TestInvertedOWG.py @@ -17,7 +17,7 @@ def setUp(self): self.multiworld.glitches_required[1] = GlitchesRequired.from_any("overworld_glitches") self.multiworld.mode[1].value = 2 self.multiworld.bombless_start[1].value = True - self.multiworld.shuffle_capacity_upgrades[1].value = True + self.multiworld.shuffle_capacity_upgrades[1].value = 2 self.multiworld.worlds[1].difficulty_requirements = difficulties['normal'] create_inverted_regions(self.multiworld, 1) self.world.create_dungeons() diff --git a/worlds/alttp/test/minor_glitches/TestMinor.py b/worlds/alttp/test/minor_glitches/TestMinor.py index 55fef61ebf99..8432028bf007 100644 --- a/worlds/alttp/test/minor_glitches/TestMinor.py +++ b/worlds/alttp/test/minor_glitches/TestMinor.py @@ -13,7 +13,7 @@ def setUp(self): self.world_setup() self.multiworld.glitches_required[1] = GlitchesRequired.from_any("minor_glitches") self.multiworld.bombless_start[1].value = True - self.multiworld.shuffle_capacity_upgrades[1].value = True + self.multiworld.shuffle_capacity_upgrades[1].value = 2 self.multiworld.worlds[1].difficulty_requirements = difficulties['normal'] self.world.er_seed = 0 self.world.create_regions() diff --git a/worlds/alttp/test/owg/TestVanillaOWG.py b/worlds/alttp/test/owg/TestVanillaOWG.py index 61b528f6fb91..67156eb97275 100644 --- a/worlds/alttp/test/owg/TestVanillaOWG.py +++ b/worlds/alttp/test/owg/TestVanillaOWG.py @@ -14,7 +14,7 @@ def setUp(self): self.multiworld.worlds[1].difficulty_requirements = difficulties['normal'] self.multiworld.glitches_required[1] = GlitchesRequired.from_any("overworld_glitches") self.multiworld.bombless_start[1].value = True - self.multiworld.shuffle_capacity_upgrades[1].value = True + self.multiworld.shuffle_capacity_upgrades[1].value = 2 self.multiworld.worlds[1].er_seed = 0 self.multiworld.worlds[1].create_regions() self.multiworld.worlds[1].create_items() diff --git a/worlds/alttp/test/vanilla/TestVanilla.py b/worlds/alttp/test/vanilla/TestVanilla.py index 496b2ba0f9ac..7eebc349d43f 100644 --- a/worlds/alttp/test/vanilla/TestVanilla.py +++ b/worlds/alttp/test/vanilla/TestVanilla.py @@ -13,7 +13,7 @@ def setUp(self): self.multiworld.glitches_required[1] = GlitchesRequired.from_any("no_glitches") self.multiworld.worlds[1].difficulty_requirements = difficulties['normal'] self.multiworld.bombless_start[1].value = True - self.multiworld.shuffle_capacity_upgrades[1].value = True + self.multiworld.shuffle_capacity_upgrades[1].value = 2 self.multiworld.worlds[1].er_seed = 0 self.multiworld.worlds[1].create_regions() self.multiworld.worlds[1].create_items()