Skip to content

Commit 6f231f0

Browse files
Berserker66qwint
authored andcommitted
Subnautica: filler items distribution (ArchipelagoMW#3104)
1 parent ccc8929 commit 6f231f0

File tree

3 files changed

+54
-18
lines changed

3 files changed

+54
-18
lines changed

worlds/subnautica/__init__.py

+12-7
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import itertools
55
from typing import List, Dict, Any, cast
66

7-
from BaseClasses import Region, Entrance, Location, Item, Tutorial, ItemClassification
7+
from BaseClasses import Region, Location, Item, Tutorial, ItemClassification
88
from worlds.AutoWorld import World, WebWorld
99
from . import items
1010
from . import locations
@@ -42,14 +42,16 @@ class SubnauticaWorld(World):
4242

4343
item_name_to_id = {data.name: item_id for item_id, data in items.item_table.items()}
4444
location_name_to_id = all_locations
45-
option_definitions = options.option_definitions
46-
45+
options_dataclass = options.SubnauticaOptions
46+
options: options.SubnauticaOptions
4747
data_version = 10
4848
required_client_version = (0, 4, 1)
4949

5050
creatures_to_scan: List[str]
5151

5252
def generate_early(self) -> None:
53+
if not self.options.filler_items_distribution.weights_pair[1][-1]:
54+
raise Exception("Filler Items Distribution needs at least one positive weight.")
5355
if self.options.early_seaglide:
5456
self.multiworld.local_early_items[self.player]["Seaglide Fragment"] = 2
5557

@@ -98,7 +100,7 @@ def create_regions(self):
98100
planet_region
99101
]
100102

101-
# refer to Rules.py
103+
# refer to rules.py
102104
set_rules = set_rules
103105

104106
def create_items(self):
@@ -129,7 +131,7 @@ def create_items(self):
129131
extras -= group_amount
130132

131133
for item_name in self.random.sample(
132-
# list of high-count important fragments as priority filler
134+
# list of high-count important fragments as priority filler
133135
[
134136
"Cyclops Engine Fragment",
135137
"Cyclops Hull Fragment",
@@ -140,7 +142,7 @@ def create_items(self):
140142
"Modification Station Fragment",
141143
"Moonpool Fragment",
142144
"Laser Cutter Fragment",
143-
],
145+
],
144146
k=min(extras, 9)):
145147
item = self.create_item(item_name)
146148
pool.append(item)
@@ -176,7 +178,10 @@ def create_item(self, name: str) -> SubnauticaItem:
176178
item_id, player=self.player)
177179

178180
def get_filler_item_name(self) -> str:
179-
return item_table[self.multiworld.random.choice(items_by_type[ItemType.resource])].name
181+
item_names, cum_item_weights = self.options.filler_items_distribution.weights_pair
182+
return self.random.choices(item_names,
183+
cum_weights=cum_item_weights,
184+
k=1)[0]
180185

181186

182187
class SubnauticaLocation(Location):

worlds/subnautica/items.py

+3
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,9 @@ def make_resource_bundle_data(display_name: str, internal_name: str = "") -> Ite
145145
items_by_type: Dict[ItemType, List[int]] = {item_type: [] for item_type in ItemType}
146146
for item_id, item_data in item_table.items():
147147
items_by_type[item_data.type].append(item_id)
148+
item_names_by_type: Dict[ItemType, List[str]] = {
149+
item_type: sorted(item_table[item_id].name for item_id in item_ids) for item_type, item_ids in items_by_type.items()
150+
}
148151

149152
group_items: Dict[int, Set[int]] = {
150153
35100: {35025, 35047, 35048, 35056, 35057, 35058, 35059, 35060, 35061, 35062, 35063, 35064, 35065, 35067, 35068,

worlds/subnautica/options.py

+39-11
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,20 @@
11
import typing
2+
from dataclasses import dataclass
3+
from functools import cached_property
4+
5+
from Options import (
6+
Choice,
7+
Range,
8+
DeathLink,
9+
Toggle,
10+
DefaultOnToggle,
11+
StartInventoryPool,
12+
ItemDict,
13+
PerGameCommonOptions,
14+
)
215

3-
from Options import Choice, Range, DeathLink, Toggle, DefaultOnToggle, StartInventoryPool
416
from .creatures import all_creatures, Definitions
17+
from .items import ItemType, item_names_by_type
518

619

720
class SwimRule(Choice):
@@ -103,13 +116,28 @@ class SubnauticaDeathLink(DeathLink):
103116
Note: can be toggled via in-game console command "deathlink"."""
104117

105118

106-
option_definitions = {
107-
"swim_rule": SwimRule,
108-
"early_seaglide": EarlySeaglide,
109-
"free_samples": FreeSamples,
110-
"goal": Goal,
111-
"creature_scans": CreatureScans,
112-
"creature_scan_logic": AggressiveScanLogic,
113-
"death_link": SubnauticaDeathLink,
114-
"start_inventory_from_pool": StartInventoryPool,
115-
}
119+
class FillerItemsDistribution(ItemDict):
120+
"""Random chance weights of various filler resources that can be obtained.
121+
Available items: """
122+
__doc__ += ", ".join(f"\"{item_name}\"" for item_name in item_names_by_type[ItemType.resource])
123+
_valid_keys = frozenset(item_names_by_type[ItemType.resource])
124+
default = {item_name: 1 for item_name in item_names_by_type[ItemType.resource]}
125+
display_name = "Filler Items Distribution"
126+
127+
@cached_property
128+
def weights_pair(self) -> typing.Tuple[typing.List[str], typing.List[int]]:
129+
from itertools import accumulate
130+
return list(self.value.keys()), list(accumulate(self.value.values()))
131+
132+
133+
@dataclass
134+
class SubnauticaOptions(PerGameCommonOptions):
135+
swim_rule: SwimRule
136+
early_seaglide: EarlySeaglide
137+
free_samples: FreeSamples
138+
goal: Goal
139+
creature_scans: CreatureScans
140+
creature_scan_logic: AggressiveScanLogic
141+
death_link: SubnauticaDeathLink
142+
start_inventory_from_pool: StartInventoryPool
143+
filler_items_distribution: FillerItemsDistribution

0 commit comments

Comments
 (0)