From 7b5c6e52a52471e5a1a4a44be7d5c39a989bf9ac Mon Sep 17 00:00:00 2001 From: Kara Alexandra Date: Sun, 14 Dec 2025 10:00:06 -0600 Subject: [PATCH] Pseudoflute --- BaseClasses.py | 4 ++-- InitialSram.py | 10 +++++++++- ItemList.py | 6 +++--- Main.py | 4 ++-- Rom.py | 2 +- Rules.py | 2 +- resources/app/cli/args.json | 1 + 7 files changed, 19 insertions(+), 10 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index 02b8a2b1..f75617e9 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -151,7 +151,7 @@ class World(object): set_player_attr('prizeshuffle', 'none') set_player_attr('restrict_boss_items', 'none') set_player_attr('bombbag', False) - set_player_attr('flute_mode', False) + set_player_attr('flute_mode', 'normal') set_player_attr('bow_mode', False) set_player_attr('free_lamp_cone', False) @@ -3792,7 +3792,7 @@ orcrossed_mode = {"none": 0, "polar": 1, "grouped": 2, "unrestricted": 4} flutespot_mode = {"vanilla": 0, "balanced": 1, "random": 2} # byte 13: FBBB TTPP (flute_mode, bow_mode, take_any, prize shuffle) -flute_mode = {'normal': 0, 'active': 1} +flute_mode = {'normal': 0, 'active': 1, 'pseudo': 1} bow_mode = {'progressive': 0, 'silvers': 1, 'retro': 2, 'retro_silvers': 3} # reserved 8 modes? take_any_mode = {'none': 0, 'random': 1, 'fixed': 2} prizeshuffle_mode = {'none': 0, 'dungeon': 1, 'nearby': 2, 'wild': 3} diff --git a/InitialSram.py b/InitialSram.py index 3d26c505..ef285b83 100644 --- a/InitialSram.py +++ b/InitialSram.py @@ -71,6 +71,11 @@ class InitialSram: starting_arrows = 0 starting_magic = 0 + if world.flute_mode[player] == 'pseudo': + self._initial_sram_bytes[0x3C2] = 0x00 + equip[0x34C] = 0x03 + equip[0x38C] = 0x01 + startingstate = CollectionState(world) if startingstate.has('Bow', player): @@ -114,6 +119,9 @@ class InitialSram: equip[0x37B] = 1 starting_magic = 0x80 + if startingstate.has('Ocarina (Activated)', player) or startingstate.has('Ocarina', player): + self._initial_sram_bytes[0x3C2] = 0xFF + if world.mode[player] == 'standard' and world.logic[player] not in ['noglitches', 'minorglitches']: if startingstate.has('Ocarina (Activated)', player): self.pre_set_overworld_flag(0x18, 0x20) @@ -252,7 +260,7 @@ class InitialSram: if not startingstate.has('Magic Mirror', player) and (world.doorShuffle[player] != 'vanilla' or world.mirrorscroll[player]): equip[0x353] = 1 - + # Assertion and copy equip to initial_sram_bytes assert equip[:0x340] == [0] * 0x340 self._initial_sram_bytes[0x340:0x38F] = equip[0x340:0x38F] diff --git a/ItemList.py b/ItemList.py index 2ddc0d8f..44d1dde9 100644 --- a/ItemList.py +++ b/ItemList.py @@ -255,7 +255,7 @@ def generate_itempool(world, player): loc.locked = True loc.forced_item = loc.item - if (world.flute_mode[player] != 'active' and not world.is_tile_swapped(0x18, player) + if (world.flute_mode[player] not in ['active', 'pseudo'] and not world.is_tile_swapped(0x18, player) and 'Ocarina (Activated)' not in list(map(str, [i for i in world.precollected_items if i.player == player]))): region = world.get_region('Kakariko Village',player) @@ -290,7 +290,7 @@ def generate_itempool(world, player): (pool, placed_items, precollected_items, clock_mode, treasure_hunt_count, treasure_hunt_total, treasure_hunt_icon) = make_custom_item_pool(world, player, world.progressive, world.shuffle[player], world.difficulty[player], world.timer, world.goal[player], world.mode[player], world.swords[player], world.bombbag[player], world.customitemarray[player]) world.rupoor_cost = min(world.customitemarray[player]["rupoorcost"], 9999) else: - (pool, placed_items, precollected_items, clock_mode) = get_pool_core(world, player, world.progressive, world.shuffle[player], world.difficulty[player], world.treasure_hunt_total[player], world.timer, world.goal[player], world.mode[player], world.swords[player], world.bombbag[player], world.doorShuffle[player], world.logic[player], world.flute_mode[player] == 'active' or world.is_tile_swapped(0x18, player)) + (pool, placed_items, precollected_items, clock_mode) = get_pool_core(world, player, world.progressive, world.shuffle[player], world.difficulty[player], world.treasure_hunt_total[player], world.timer, world.goal[player], world.mode[player], world.swords[player], world.bombbag[player], world.doorShuffle[player], world.logic[player], world.flute_mode[player] in ['active', 'pseudo'] or world.is_tile_swapped(0x18, player)) if player in world.pool_adjustment.keys() and not skip_pool_adjustments: amt = world.pool_adjustment[player] @@ -1497,7 +1497,7 @@ def make_customizer_pool(world, player): world.get_location('Master Sword Pedestal', player).locked = True guaranteed_items = alwaysitems + ['Magic Mirror', 'Moon Pearl'] - if world.is_tile_swapped(0x18, player) or world.flute_mode[player] == 'active': + if world.is_tile_swapped(0x18, player) or world.flute_mode[player] in ['active', 'pseudo']: guaranteed_items.remove('Ocarina') guaranteed_items.append('Ocarina (Activated)') missing_items = [] diff --git a/Main.py b/Main.py index f9c03012..3548a399 100644 --- a/Main.py +++ b/Main.py @@ -721,7 +721,7 @@ def set_starting_inventory(world, args): if args.usestartinventory[player]: for tok in filter(None, args.startinventory[player].replace("_", " ").split(',')): name = tok.strip() - name = name if name != 'Ocarina' or world.flute_mode[player] != 'active' else 'Ocarina (Activated)' + name = name if name != 'Ocarina' or world.flute_mode[player] not in ['active', 'pseudo'] else 'Ocarina (Activated)' item = ItemFactory(name, player) if item: world.push_precollected(item) @@ -745,7 +745,7 @@ def set_starting_inventory(world, args): world.push_precollected(item) elif inv_item == 'RandomFollower': name = random.choice([f for f in follower_pickups if f != 'Zelda Herself' or world.mode[p] == 'standard']) - name = name if name != 'Ocarina' or world.flute_mode[p] != 'active' else 'Ocarina (Activated)' + name = name if name != 'Ocarina' or world.flute_mode[p] not in ['active', 'pseudo'] else 'Ocarina (Activated)' if name in follower_pickups: if not world.shuffle_followers[p] or follower_added: continue diff --git a/Rom.py b/Rom.py index b9561dee..74f99802 100644 --- a/Rom.py +++ b/Rom.py @@ -2447,7 +2447,7 @@ def write_strings(rom, world, player, team): # of how many exist. This supports many settings well. items_to_hint = RelevantItems.copy() flute_item = 'Ocarina' - if world.is_tile_swapped(0x18, player) or world.flute_mode[player] == 'active': + if world.is_tile_swapped(0x18, player) or world.flute_mode[player] in ['active', 'pseudo']: items_to_hint.remove(flute_item) flute_item = 'Ocarina (Activated)' if world.owShuffle[player] != 'vanilla' or world.owMixed[player]: diff --git a/Rules.py b/Rules.py index ea14bab8..91637cce 100644 --- a/Rules.py +++ b/Rules.py @@ -91,7 +91,7 @@ def set_rules(world, player): else: add_rule(location, lambda state: state.item_count('Triforce Piece', player) + state.item_count('Power Star', player) >= int(state.world.treasure_hunt_count[player])) - if (world.flute_mode[player] != 'active' and not world.is_tile_swapped(0x18, player) + if (world.flute_mode[player] not in ['active', 'pseudo'] and not world.is_tile_swapped(0x18, player) and 'Ocarina (Activated)' not in list(map(str, [i for i in world.precollected_items if i.player == player]))): # Commented out below, this would be needed for rando implementations where Inverted requires flute activation in bunny territory # kak_region = self.world.get_region('Kakariko Village', player) diff --git a/resources/app/cli/args.json b/resources/app/cli/args.json index e792268d..9b26e24f 100644 --- a/resources/app/cli/args.json +++ b/resources/app/cli/args.json @@ -50,6 +50,7 @@ }, "flute_mode": { "choices": [ + "pseudo", "normal", "active" ]