From edacc07808164cebb79ac639450bcb4ed4fdfe60 Mon Sep 17 00:00:00 2001 From: Mysteryem Date: Mon, 28 Oct 2024 22:26:08 +0000 Subject: [PATCH] OSRS: Add missing indirect conditions (#4029) All entrances to Cooks_Guild and Crafting_Guild and all entrances using special logic for canoes were missing indirect conditions for the regions that the cooking, crafting and woodcutting skill rules require access to. --- worlds/osrs/__init__.py | 104 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/worlds/osrs/__init__.py b/worlds/osrs/__init__.py index 9ed55f21..58f23a2b 100644 --- a/worlds/osrs/__init__.py +++ b/worlds/osrs/__init__.py @@ -190,12 +190,83 @@ class OSRSWorld(World): cooking_level_rule = self.get_skill_rule("cooking", 32) entrance.access_rule = lambda state: state.has(item_name, self.player) and \ cooking_level_rule(state) + if self.options.brutal_grinds: + cooking_level_32_regions = { + RegionNames.Milk, + RegionNames.Egg, + RegionNames.Shrimp, + RegionNames.Wheat, + RegionNames.Windmill, + } + else: + # Level 15 cooking and higher requires level 20 fishing. + fishing_level_20_regions = { + RegionNames.Shrimp, + RegionNames.Port_Sarim, + } + cooking_level_32_regions = { + RegionNames.Milk, + RegionNames.Egg, + RegionNames.Shrimp, + RegionNames.Wheat, + RegionNames.Windmill, + RegionNames.Fly_Fish, + *fishing_level_20_regions, + } + for region_name in cooking_level_32_regions: + self.multiworld.register_indirect_condition(self.get_region(region_name), entrance) return if outbound_region_name == RegionNames.Crafting_Guild: item_name = self.region_rows_by_name[outbound_region_name].itemReq.replace('*', '') crafting_level_rule = self.get_skill_rule("crafting", 40) entrance.access_rule = lambda state: state.has(item_name, self.player) and \ crafting_level_rule(state) + if self.options.brutal_grinds: + crafting_level_40_regions = { + # can_spin + RegionNames.Sheep, + RegionNames.Spinning_Wheel, + # can_pot + RegionNames.Clay_Rock, + RegionNames.Barbarian_Village, + # can_tan + RegionNames.Milk, + RegionNames.Al_Kharid, + } + else: + mould_access_regions = { + RegionNames.Al_Kharid, + RegionNames.Rimmington, + } + smithing_level_20_regions = { + RegionNames.Bronze_Ores, + RegionNames.Iron_Rock, + RegionNames.Furnace, + RegionNames.Anvil, + } + smithing_level_40_regions = { + *smithing_level_20_regions, + RegionNames.Coal_Rock, + } + crafting_level_40_regions = { + # can_tan + RegionNames.Milk, + RegionNames.Al_Kharid, + # can_silver + RegionNames.Silver_Rock, + RegionNames.Furnace, + *mould_access_regions, + # can_smelt_silver + *smithing_level_20_regions, + # can_gold + RegionNames.Gold_Rock, + RegionNames.Furnace, + *mould_access_regions, + # can_smelt_gold + *smithing_level_40_regions, + } + for region_name in crafting_level_40_regions: + self.multiworld.register_indirect_condition(self.get_region(region_name), entrance) return if outbound_region_name == RegionNames.Corsair_Cove: item_name = self.region_rows_by_name[outbound_region_name].itemReq.replace('*', '') @@ -224,6 +295,20 @@ class OSRSWorld(World): woodcutting_rule_d3 = self.get_skill_rule("woodcutting", 42) woodcutting_rule_all = self.get_skill_rule("woodcutting", 57) + def add_indirect_conditions_for_woodcutting_levels(entrance, *levels: int): + if self.options.brutal_grinds: + # No access to specific regions required. + return + # Currently, each level requirement requires everything from the previous level requirements, so the + # maximum level requirement can be taken. + max_level = max(levels, default=0) + max_level = min(max_level, self.options.max_woodcutting_level.value) + if 15 <= max_level < 30: + self.multiworld.register_indirect_condition(self.get_region(RegionNames.Oak_Tree), entrance) + elif 30 <= max_level: + self.multiworld.register_indirect_condition(self.get_region(RegionNames.Oak_Tree), entrance) + self.multiworld.register_indirect_condition(self.get_region(RegionNames.Willow_Tree), entrance) + if region_row.name == RegionNames.Lumbridge: # Canoe Tree access for the Location if outbound_region_name == RegionNames.Canoe_Tree: @@ -236,6 +321,7 @@ class OSRSWorld(World): and woodcutting_rule_d3(state) and self.options.max_woodcutting_level >= 42) or \ (state.can_reach_region(RegionNames.Wilderness) and woodcutting_rule_all(state) and self.options.max_woodcutting_level >= 57) + add_indirect_conditions_for_woodcutting_levels(entrance, 12, 27, 42, 57) self.multiworld.register_indirect_condition( self.multiworld.get_region(RegionNames.South_Of_Varrock, self.player), entrance) self.multiworld.register_indirect_condition( @@ -249,12 +335,15 @@ class OSRSWorld(World): if outbound_region_name == RegionNames.Barbarian_Village: entrance.access_rule = lambda state: woodcutting_rule_d2(state) \ and self.options.max_woodcutting_level >= 27 + add_indirect_conditions_for_woodcutting_levels(entrance, 27) if outbound_region_name == RegionNames.Edgeville: entrance.access_rule = lambda state: woodcutting_rule_d3(state) \ and self.options.max_woodcutting_level >= 42 + add_indirect_conditions_for_woodcutting_levels(entrance, 42) if outbound_region_name == RegionNames.Wilderness: entrance.access_rule = lambda state: woodcutting_rule_all(state) \ and self.options.max_woodcutting_level >= 57 + add_indirect_conditions_for_woodcutting_levels(entrance, 57) if region_row.name == RegionNames.South_Of_Varrock: if outbound_region_name == RegionNames.Canoe_Tree: @@ -267,6 +356,7 @@ class OSRSWorld(World): and woodcutting_rule_d2(state) and self.options.max_woodcutting_level >= 27) or \ (state.can_reach_region(RegionNames.Wilderness) and woodcutting_rule_d3(state) and self.options.max_woodcutting_level >= 42) + add_indirect_conditions_for_woodcutting_levels(entrance, 12, 27, 42) self.multiworld.register_indirect_condition( self.multiworld.get_region(RegionNames.Lumbridge, self.player), entrance) self.multiworld.register_indirect_condition( @@ -280,12 +370,15 @@ class OSRSWorld(World): if outbound_region_name == RegionNames.Barbarian_Village: entrance.access_rule = lambda state: woodcutting_rule_d1(state) \ and self.options.max_woodcutting_level >= 12 + add_indirect_conditions_for_woodcutting_levels(entrance, 12) if outbound_region_name == RegionNames.Edgeville: entrance.access_rule = lambda state: woodcutting_rule_d3(state) \ and self.options.max_woodcutting_level >= 27 + add_indirect_conditions_for_woodcutting_levels(entrance, 27) if outbound_region_name == RegionNames.Wilderness: entrance.access_rule = lambda state: woodcutting_rule_all(state) \ and self.options.max_woodcutting_level >= 42 + add_indirect_conditions_for_woodcutting_levels(entrance, 42) if region_row.name == RegionNames.Barbarian_Village: if outbound_region_name == RegionNames.Canoe_Tree: entrance.access_rule = \ @@ -297,6 +390,7 @@ class OSRSWorld(World): and woodcutting_rule_d1(state) and self.options.max_woodcutting_level >= 12) or \ (state.can_reach_region(RegionNames.Wilderness) and woodcutting_rule_d2(state) and self.options.max_woodcutting_level >= 27) + add_indirect_conditions_for_woodcutting_levels(entrance, 12, 27) self.multiworld.register_indirect_condition( self.multiworld.get_region(RegionNames.Lumbridge, self.player), entrance) self.multiworld.register_indirect_condition( @@ -309,13 +403,16 @@ class OSRSWorld(World): if outbound_region_name == RegionNames.Lumbridge: entrance.access_rule = lambda state: woodcutting_rule_d2(state) \ and self.options.max_woodcutting_level >= 27 + add_indirect_conditions_for_woodcutting_levels(entrance, 27) if outbound_region_name == RegionNames.South_Of_Varrock: entrance.access_rule = lambda state: woodcutting_rule_d1(state) \ and self.options.max_woodcutting_level >= 12 + add_indirect_conditions_for_woodcutting_levels(entrance, 12) # Edgeville does not need to be checked, because it's already adjacent if outbound_region_name == RegionNames.Wilderness: entrance.access_rule = lambda state: woodcutting_rule_d3(state) \ and self.options.max_woodcutting_level >= 42 + add_indirect_conditions_for_woodcutting_levels(entrance, 42) if region_row.name == RegionNames.Edgeville: if outbound_region_name == RegionNames.Canoe_Tree: entrance.access_rule = \ @@ -327,6 +424,7 @@ class OSRSWorld(World): and woodcutting_rule_d1(state) and self.options.max_woodcutting_level >= 12) or \ (state.can_reach_region(RegionNames.Wilderness) and woodcutting_rule_d1(state) and self.options.max_woodcutting_level >= 12) + add_indirect_conditions_for_woodcutting_levels(entrance, 12, 27, 42) self.multiworld.register_indirect_condition( self.multiworld.get_region(RegionNames.Lumbridge, self.player), entrance) self.multiworld.register_indirect_condition( @@ -339,9 +437,11 @@ class OSRSWorld(World): if outbound_region_name == RegionNames.Lumbridge: entrance.access_rule = lambda state: woodcutting_rule_d3(state) \ and self.options.max_woodcutting_level >= 42 + add_indirect_conditions_for_woodcutting_levels(entrance, 42) if outbound_region_name == RegionNames.South_Of_Varrock: entrance.access_rule = lambda state: woodcutting_rule_d2(state) \ and self.options.max_woodcutting_level >= 27 + add_indirect_conditions_for_woodcutting_levels(entrance, 27) # Barbarian Village does not need to be checked, because it's already adjacent # Wilderness does not need to be checked, because it's already adjacent if region_row.name == RegionNames.Wilderness: @@ -355,6 +455,7 @@ class OSRSWorld(World): and woodcutting_rule_d2(state) and self.options.max_woodcutting_level >= 27) or \ (state.can_reach_region(RegionNames.Edgeville) and woodcutting_rule_d1(state) and self.options.max_woodcutting_level >= 12) + add_indirect_conditions_for_woodcutting_levels(entrance, 12, 27, 42, 57) self.multiworld.register_indirect_condition( self.multiworld.get_region(RegionNames.Lumbridge, self.player), entrance) self.multiworld.register_indirect_condition( @@ -367,12 +468,15 @@ class OSRSWorld(World): if outbound_region_name == RegionNames.Lumbridge: entrance.access_rule = lambda state: woodcutting_rule_all(state) \ and self.options.max_woodcutting_level >= 57 + add_indirect_conditions_for_woodcutting_levels(entrance, 57) if outbound_region_name == RegionNames.South_Of_Varrock: entrance.access_rule = lambda state: woodcutting_rule_d3(state) \ and self.options.max_woodcutting_level >= 42 + add_indirect_conditions_for_woodcutting_levels(entrance, 42) if outbound_region_name == RegionNames.Barbarian_Village: entrance.access_rule = lambda state: woodcutting_rule_d2(state) \ and self.options.max_woodcutting_level >= 27 + add_indirect_conditions_for_woodcutting_levels(entrance, 27) # Edgeville does not need to be checked, because it's already adjacent def roll_locations(self):