diff --git a/worlds/sc2/__init__.py b/worlds/sc2/__init__.py index b5c7b5f0cf..983b329d7d 100644 --- a/worlds/sc2/__init__.py +++ b/worlds/sc2/__init__.py @@ -148,7 +148,6 @@ class SC2World(World): flag_start_inventory(self, item_list) flag_unused_upgrade_types(self, item_list) flag_unreleased_items(item_list) - flag_user_excluded_item_sets(self, item_list) flag_war_council_items(self, item_list) flag_and_add_resource_locations(self, item_list) flag_mission_order_required_items(self, item_list) @@ -394,6 +393,17 @@ def create_and_flag_explicit_item_locks_and_excludes(world: SC2World) -> List[Fi if world.options.exclude_overpowered_items.value == ExcludeOverpoweredItems.option_true: for item_name in item_groups.overpowered_items: auto_excludes[item_name] = 1 + if world.options.vanilla_items_only.value == VanillaItemsOnly.option_true: + for item_name, item_data in item_tables.item_table.items(): + if item_name in item_groups.terran_original_progressive_upgrades: + auto_excludes[item_name] = max(item_data.quantity - 1, auto_excludes.get(item_name, 0)) + elif item_name in item_groups.vanilla_items: + continue + elif item_name in item_groups.nova_equipment: + continue + else: + auto_excludes[item_name] = 0 + result: List[FilterItem] = [] for item_name, item_data in item_tables.item_table.items(): @@ -836,26 +846,6 @@ def flag_unreleased_items(item_list: List[FilterItem]) -> None: item.flags |= ItemFilterFlags.Removed -def flag_user_excluded_item_sets(world: SC2World, item_list: List[FilterItem]) -> None: - """Excludes items based on item set options (`only_vanilla_items`)""" - vanilla_nonprogressive_count = { - item_name: 0 for item_name in item_groups.terran_original_progressive_upgrades - } - if world.options.vanilla_items_only.value == VanillaItemsOnly.option_true: - vanilla_items = item_groups.vanilla_items + item_groups.nova_equipment - for item in item_list: - if ItemFilterFlags.UserExcluded in item.flags: - continue - if item.name not in vanilla_items: - item.flags |= ItemFilterFlags.UserExcluded - if item.name in item_groups.terran_original_progressive_upgrades: - if vanilla_nonprogressive_count[item.name]: - item.flags |= ItemFilterFlags.UserExcluded - vanilla_nonprogressive_count[item.name] += 1 - - excluded_count: Dict[str, int] = dict() - - def flag_war_council_items(world: SC2World, item_list: List[FilterItem]) -> None: """Excludes / start-inventories items based on `nerf_unit_baselines` option. Will skip items that are excluded by other sources.""" diff --git a/worlds/sc2/test/test_generation.py b/worlds/sc2/test/test_generation.py index 61de392c0c..9a95058720 100644 --- a/worlds/sc2/test/test_generation.py +++ b/worlds/sc2/test/test_generation.py @@ -325,6 +325,53 @@ class TestItemFiltering(Sc2SetupTestBase): if item_data.quantity == 0: continue self.assertIn(item_name, item_groups.vanilla_items + item_groups.nova_equipment) + + def test_vanilla_items_only_can_unexclude_items(self) -> None: + world_options = { + # Ensuring an excess of locations so expected items don't get culled + **self.ALL_CAMPAIGNS, + 'mission_order': options.MissionOrder.option_grid, + 'maximum_campaign_size': options.MaximumCampaignSize.range_end, + 'enable_race_swap': options.EnableRaceSwapVariants.option_shuffle_all, + 'selected_races': {SC2Race.TERRAN.get_title()}, + # Options under test + 'vanilla_items_only': True, + 'unexcluded_items': { + item_names.PROGRESSIVE_FIRE_SUPPRESSION_SYSTEM: 0, + item_names.WARHOUND: 1, + item_groups.ItemGroupNames.TERRAN_STIMPACKS: 0, + }, + # Avoid options that lock non-vanilla items for logic + 'required_tactics': options.RequiredTactics.option_any_units, + 'mastery_locations': options.MasteryLocations.option_disabled, + # Move the unit nerf items from the start inventory to the pool, + # else this option could push non-vanilla items past this test + 'war_council_nerfs': True, + } + self.generate_world(world_options) + world_items = [item.name for item in self.multiworld.itempool] + self.assertTrue(world_items) + self.assertNotIn(item_names.MARAUDER_MAGRAIL_MUNITIONS, world_items) + self.assertEqual(world_items.count(item_names.PROGRESSIVE_FIRE_SUPPRESSION_SYSTEM), 2) + self.assertIn(item_names.WARHOUND, world_items) + self.assertIn(item_names.MARAUDER_PROGRESSIVE_STIMPACK, world_items) + self.assertIn(item_names.REAPER_PROGRESSIVE_STIMPACK, world_items) + + def test_vanilla_items_only_and_exclude_op_items_together_allow_one_level_of_regen_biosteel(self) -> None: + world_options = { + # Ensuring an excess of locations so expected items don't get culled + **self.ALL_CAMPAIGNS, + 'mission_order': options.MissionOrder.option_grid, + 'maximum_campaign_size': options.MaximumCampaignSize.range_end, + 'enable_race_swap': options.EnableRaceSwapVariants.option_shuffle_all, + 'selected_races': {SC2Race.TERRAN.get_title()}, + # Options under test + 'vanilla_items_only': True, + 'exclude_overpowered_items': True, + } + self.generate_world(world_options) + world_items = [item.name for item in self.multiworld.itempool] + self.assertEqual(world_items.count(item_names.PROGRESSIVE_REGENERATIVE_BIO_STEEL), 1) def test_evil_awoken_with_vanilla_items_only_generates(self) -> None: world_options = {