From f4021afac0d3b19627fb35b3fe5eafe1d463f264 Mon Sep 17 00:00:00 2001 From: aerinon Date: Fri, 14 Nov 2025 14:37:46 -0700 Subject: [PATCH] feat: free_lamp_cone as experimental feature --- BaseClasses.py | 3 ++- ItemList.py | 18 ++++++------------ Main.py | 4 ++-- Rom.py | 5 +++-- Rules.py | 2 +- data/base2current.bps | Bin 118196 -> 118191 bytes 6 files changed, 14 insertions(+), 18 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index 6a12f32e..3b06f10b 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -69,7 +69,6 @@ class World(object): self.dynamic_locations = [] self.spoiler_mode = spoiler_mode self.spoiler = Spoiler(self) - self.lamps_needed_for_dark_rooms = 1 self.doors = [] self._door_cache = {} self.paired_doors = {} @@ -123,6 +122,8 @@ class World(object): set_player_attr('bombbag', False) set_player_attr('flute_mode', False) set_player_attr('bow_mode', False) + set_player_attr('free_lamp_cone', False) + set_player_attr('difficulty_requirements', None) set_player_attr('boss_shuffle', 'none') set_player_attr('enemy_shuffle', 'none') diff --git a/ItemList.py b/ItemList.py index 3dce2da3..32da56cc 100644 --- a/ItemList.py +++ b/ItemList.py @@ -266,13 +266,13 @@ def generate_itempool(world, player): # set up item pool skip_pool_adjustments = False if world.customizer and world.customizer.get_item_pool() and player in world.customizer.get_item_pool(): - (pool, placed_items, precollected_items, clock_mode, lamps_needed_for_dark_rooms) = make_customizer_pool(world, player) + (pool, placed_items, precollected_items, clock_mode) = make_customizer_pool(world, player) skip_pool_adjustments = True elif world.custom: - (pool, placed_items, precollected_items, clock_mode, treasure_hunt_count, treasure_hunt_icon, lamps_needed_for_dark_rooms) = 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) + (pool, placed_items, precollected_items, clock_mode, treasure_hunt_count, 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) world.rupoor_cost = min(world.customitemarray[player]["rupoorcost"], 9999) else: - (pool, placed_items, precollected_items, clock_mode, lamps_needed_for_dark_rooms) = 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') + (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') if player in world.pool_adjustment.keys() and not skip_pool_adjustments: amt = world.pool_adjustment[player] @@ -351,8 +351,6 @@ def generate_itempool(world, player): if item.name == 'Bomb Upgrade (+10)' and item.player == player: item.advancement = True - world.lamps_needed_for_dark_rooms = lamps_needed_for_dark_rooms - if clock_mode is not None: world.clock_mode = clock_mode @@ -946,8 +944,6 @@ def get_pool_core(world, player, progressive, shuffle, difficulty, treasure_hunt else: pool.extend(basicgloves) - lamps_needed_for_dark_rooms = 1 - # old insanity shuffle didn't have fake LW/DW logic so this used to be conditional pool.extend(['Magic Mirror', 'Moon Pearl']) @@ -1048,7 +1044,7 @@ def get_pool_core(world, player, progressive, shuffle, difficulty, treasure_hunt pool.extend(['Small Key (Universal)']) else: pool.extend(['Small Key (Universal)']) - return (pool, placed_items, precollected_items, clock_mode, lamps_needed_for_dark_rooms) + return (pool, placed_items, precollected_items, clock_mode) item_alternates = { @@ -1152,8 +1148,6 @@ def make_custom_item_pool(world, player, progressive, shuffle, difficulty, timer diff = difficulties[difficulty] - lamps_needed_for_dark_rooms = 1 - # expert+ difficulties produce the same contents for # all bottles, since only one bottle is available if diff.same_bottle: @@ -1213,7 +1207,7 @@ def make_custom_item_pool(world, player, progressive, shuffle, difficulty, timer pool.remove('Fighter Sword') pool.append('Rupees (50)') - return (pool, placed_items, precollected_items, clock_mode, treasure_hunt_count, treasure_hunt_icon, lamps_needed_for_dark_rooms) + return (pool, placed_items, precollected_items, clock_mode, treasure_hunt_count, treasure_hunt_icon) def make_customizer_pool(world, player): @@ -1357,7 +1351,7 @@ def make_customizer_pool(world, player): pool.remove('Fighter Sword') pool.append('Rupees (50)') - return pool, placed_items, precollected_items, clock_mode, 1 + return pool, placed_items, precollected_items, clock_mode filler_items = { diff --git a/Main.py b/Main.py index 197602e2..5a67ca15 100644 --- a/Main.py +++ b/Main.py @@ -171,7 +171,7 @@ def main(args, seed=None, fish=None): world.finish_init() # custom settings - these haven't been promoted to full settings yet - in_progress_settings = ['force_enemy'] + in_progress_settings = ['force_enemy', 'free_lamp_cone'] for player in range(1, world.players + 1): for setting in in_progress_settings: if world.customizer and world.customizer.has_setting(player, setting): @@ -494,7 +494,6 @@ def copy_world(world): ret.can_take_damage = world.can_take_damage ret.difficulty_requirements = world.difficulty_requirements.copy() ret.fix_fake_world = world.fix_fake_world.copy() - ret.lamps_needed_for_dark_rooms = world.lamps_needed_for_dark_rooms ret.mapshuffle = world.mapshuffle.copy() ret.compassshuffle = world.compassshuffle.copy() ret.keyshuffle = world.keyshuffle.copy() @@ -502,6 +501,7 @@ def copy_world(world): ret.bombbag = world.bombbag.copy() ret.flute_mode = world.flute_mode.copy() ret.bow_mode = world.bow_mode.copy() + ret.free_lamp_cone = world.free_lamp_cone.copy() ret.crystals_needed_for_ganon = world.crystals_needed_for_ganon.copy() ret.crystals_needed_for_gt = world.crystals_needed_for_gt.copy() ret.crystals_ganon_orig = world.crystals_ganon_orig.copy() diff --git a/Rom.py b/Rom.py index 04987530..ec343ee7 100644 --- a/Rom.py +++ b/Rom.py @@ -42,7 +42,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '1e87ad01a54f1c15e2ec16a79a9bcc20' +RANDOMIZERBASEHASH = 'f327962e7f2872c80fd75b35c6f2c985' class JsonRom(object): @@ -811,7 +811,8 @@ def patch_rom(world, rom, player, team, is_mystery=False): rom.write_bytes(0x6D323, [0x00, 0x00, 0xe4, 0xff, 0x08, 0x0E]) # set light cones - rom.write_byte(0x180038, 0x01 if world.sewer_light_cone[player] else 0x00) + lamp_cone_flags = (0x1 if world.sewer_light_cone[player] else 0) | (0x10 if world.free_lamp_cone[player] else 0) + rom.write_byte(0x180038, lamp_cone_flags) GREEN_TWENTY_RUPEES = 0x47 TRIFORCE_PIECE = ItemFactory('Triforce Piece', player).code diff --git a/Rules.py b/Rules.py index 5d059a5c..19dc9922 100644 --- a/Rules.py +++ b/Rules.py @@ -160,7 +160,7 @@ def and_rule(rule1, rule2): def add_lamp_requirement(spot, player): - add_rule(spot, lambda state: state.has('Lamp', player, state.world.lamps_needed_for_dark_rooms)) + add_rule(spot, lambda state: state.has('Lamp', player) or state.world.free_lamp_cone[player]) def forbid_item(location, item, player): diff --git a/data/base2current.bps b/data/base2current.bps index a287a08d9090504aa003b5e346d481fe5fdad888..f2b1f9252dcd8bf45d222cc667e40bebec06f83d 100644 GIT binary patch delta 7371 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 F{{uxx<%0kK