diff --git a/worlds/subnautica/Items.py b/worlds/subnautica/Items.py index cf1f8ed2..600e1d19 100644 --- a/worlds/subnautica/Items.py +++ b/worlds/subnautica/Items.py @@ -40,8 +40,8 @@ item_table: Dict[int, ItemDict] = { 'tech_type': 'CyclopsThermalReactorModule'}, 35007: {'classification': ItemClassification.filler, 'count': 1, - 'name': 'Stillsuit', - 'tech_type': 'WaterFiltrationSuitFragment'}, + 'name': 'Water Filtration Suit', + 'tech_type': 'WaterFiltrationSuit'}, 35008: {'classification': ItemClassification.progression, 'count': 1, 'name': 'Alien Containment', @@ -359,6 +359,18 @@ item_table: Dict[int, ItemDict] = { 'count': 0, 'name': 'Partition Door', 'tech_type': 'BasePartitionDoor'}, + # new items that the mod implements + + # Awards all furniture as a bundle + 35100: {'classification': ItemClassification.filler, + 'count': 0, + 'name': 'Furniture', + 'tech_type': 'Furniture'}, + # Awards all farming blueprints as a bundle + 35101: {'classification': ItemClassification.filler, + 'count': 0, + 'name': 'Farming', + 'tech_type': 'Farming'}, } advancement_item_names: Set[str] = set() @@ -371,8 +383,15 @@ for item_id, item_data in item_table.items(): else: non_advancement_item_names.add(item_name) +group_items: Dict[int, Set[int]] = { + 35100: {35025, 35047, 35048, 35056, 35057, 35058, 35059, 35060, 35061, 35062, 35063, 35064, 35065, 35067, 35068, + 35069, 35070, 35073, 35074}, + 35101: {35049, 35050, 35051, 35071, 35072, 35074} +} + if False: # turn to True to export for Subnautica mod from .Locations import location_table + from NetUtils import encode itemcount = sum(item_data["count"] for item_data in item_table.values()) assert itemcount == len(location_table), f"{itemcount} != {len(location_table)}" payload = {item_id: item_data["tech_type"] for item_id, item_data in item_table.items()} @@ -380,3 +399,5 @@ if False: # turn to True to export for Subnautica mod with open("items.json", "w") as f: json.dump(payload, f) + with open("group_items.json", "w") as f: + f.write(encode(group_items)) diff --git a/worlds/subnautica/Options.py b/worlds/subnautica/Options.py index 03834cdb..91c48661 100644 --- a/worlds/subnautica/Options.py +++ b/worlds/subnautica/Options.py @@ -35,14 +35,6 @@ class EarlySeaglide(DefaultOnToggle): display_name = "Early Seaglide" -class ItemPool(Choice): - """Valuable item pool leaves all filler items in their vanilla locations and - creates random duplicates of important items into freed spots.""" - display_name = "Item Pool" - option_standard = 0 - option_valuable = 1 - - class Goal(Choice): """Goal to complete. Launch: Leave the planet. @@ -108,7 +100,6 @@ class SubnauticaDeathLink(DeathLink): options = { "swim_rule": SwimRule, "early_seaglide": EarlySeaglide, - "item_pool": ItemPool, "goal": Goal, "creature_scans": CreatureScans, "creature_scan_logic": AggressiveScanLogic, diff --git a/worlds/subnautica/__init__.py b/worlds/subnautica/__init__.py index b786bcc4..bc1e4f69 100644 --- a/worlds/subnautica/__init__.py +++ b/worlds/subnautica/__init__.py @@ -1,4 +1,7 @@ +from __future__ import annotations + import logging +import itertools from typing import List, Dict, Any from BaseClasses import Region, Entrance, Location, Item, Tutorial, ItemClassification @@ -7,7 +10,7 @@ from . import Items from . import Locations from . import Creatures from . import Options -from .Items import item_table +from .Items import item_table, group_items from .Rules import set_rules logger = logging.getLogger("Subnautica") @@ -84,37 +87,41 @@ class SubnauticaWorld(World): def create_items(self): # Generate item pool - pool = [] + pool: List[SubnauticaItem] = [] extras = self.multiworld.creature_scans[self.player].value - valuable = self.multiworld.item_pool[self.player] == Options.ItemPool.option_valuable - for item in item_table.values(): - for i in range(item["count"]): - subnautica_item = self.create_item(item["name"]) - if item["name"] == "Neptune Launch Platform": - self.multiworld.get_location("Aurora - Captain Data Terminal", self.player).place_locked_item( - subnautica_item) - elif valuable and ItemClassification.filler == item["classification"]: - extras += 1 - else: - pool.append(subnautica_item) - for item_name in self.multiworld.random.choices(sorted(Items.advancement_item_names - {"Neptune Launch Platform"}), - k=extras): + grouped = set(itertools.chain.from_iterable(group_items.values())) + + for item_id, item in item_table.items(): + if item_id in grouped: + extras += item["count"] + else: + for i in range(item["count"]): + subnautica_item = self.create_item(item["name"]) + if item["name"] == "Neptune Launch Platform": + self.multiworld.get_location("Aurora - Captain Data Terminal", self.player).place_locked_item( + subnautica_item) + else: + pool.append(subnautica_item) + + group_amount: int = 3 + assert len(group_items) * group_amount <= extras + for name in ("Furniture", "Farming"): + for _ in range(group_amount): + pool.append(self.create_item(name)) + extras -= group_amount + + for item_name in self.multiworld.random.choices( + sorted(Items.advancement_item_names - {"Neptune Launch Platform"}), k=extras): item = self.create_item(item_name) - item.classification = ItemClassification.filler # as it's an extra, just fast-fill it somewhere pool.append(item) self.multiworld.itempool += pool def fill_slot_data(self) -> Dict[str, Any]: goal: Options.Goal = self.multiworld.goal[self.player] - item_pool: Options.ItemPool = self.multiworld.item_pool[self.player] swim_rule: Options.SwimRule = self.multiworld.swim_rule[self.player] vanilla_tech: List[str] = [] - if item_pool == Options.ItemPool.option_valuable: - for item in Items.item_table.values(): - if item["classification"] == ItemClassification.filler: - vanilla_tech.append(item["tech_type"]) slot_data: Dict[str, Any] = { "goal": goal.current_key, @@ -126,7 +133,7 @@ class SubnauticaWorld(World): return slot_data - def create_item(self, name: str) -> Item: + def create_item(self, name: str) -> SubnauticaItem: item_id: int = self.item_name_to_id[name] return SubnauticaItem(name,