Subnautica: filler items distribution (#3104)

This commit is contained in:
Fabian Dill 2024-04-14 20:36:25 +02:00 committed by GitHub
parent 7b3727e945
commit 1c14d1107f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 54 additions and 18 deletions

View File

@ -4,7 +4,7 @@ import logging
import itertools
from typing import List, Dict, Any, cast
from BaseClasses import Region, Entrance, Location, Item, Tutorial, ItemClassification
from BaseClasses import Region, Location, Item, Tutorial, ItemClassification
from worlds.AutoWorld import World, WebWorld
from . import items
from . import locations
@ -42,14 +42,16 @@ class SubnauticaWorld(World):
item_name_to_id = {data.name: item_id for item_id, data in items.item_table.items()}
location_name_to_id = all_locations
option_definitions = options.option_definitions
options_dataclass = options.SubnauticaOptions
options: options.SubnauticaOptions
data_version = 10
required_client_version = (0, 4, 1)
creatures_to_scan: List[str]
def generate_early(self) -> None:
if not self.options.filler_items_distribution.weights_pair[1][-1]:
raise Exception("Filler Items Distribution needs at least one positive weight.")
if self.options.early_seaglide:
self.multiworld.local_early_items[self.player]["Seaglide Fragment"] = 2
@ -98,7 +100,7 @@ class SubnauticaWorld(World):
planet_region
]
# refer to Rules.py
# refer to rules.py
set_rules = set_rules
def create_items(self):
@ -129,7 +131,7 @@ class SubnauticaWorld(World):
extras -= group_amount
for item_name in self.random.sample(
# list of high-count important fragments as priority filler
# list of high-count important fragments as priority filler
[
"Cyclops Engine Fragment",
"Cyclops Hull Fragment",
@ -140,7 +142,7 @@ class SubnauticaWorld(World):
"Modification Station Fragment",
"Moonpool Fragment",
"Laser Cutter Fragment",
],
],
k=min(extras, 9)):
item = self.create_item(item_name)
pool.append(item)
@ -176,7 +178,10 @@ class SubnauticaWorld(World):
item_id, player=self.player)
def get_filler_item_name(self) -> str:
return item_table[self.multiworld.random.choice(items_by_type[ItemType.resource])].name
item_names, cum_item_weights = self.options.filler_items_distribution.weights_pair
return self.random.choices(item_names,
cum_weights=cum_item_weights,
k=1)[0]
class SubnauticaLocation(Location):

View File

@ -145,6 +145,9 @@ item_table: Dict[int, ItemData] = {
items_by_type: Dict[ItemType, List[int]] = {item_type: [] for item_type in ItemType}
for item_id, item_data in item_table.items():
items_by_type[item_data.type].append(item_id)
item_names_by_type: Dict[ItemType, List[str]] = {
item_type: sorted(item_table[item_id].name for item_id in item_ids) for item_type, item_ids in items_by_type.items()
}
group_items: Dict[int, Set[int]] = {
35100: {35025, 35047, 35048, 35056, 35057, 35058, 35059, 35060, 35061, 35062, 35063, 35064, 35065, 35067, 35068,

View File

@ -1,7 +1,20 @@
import typing
from dataclasses import dataclass
from functools import cached_property
from Options import (
Choice,
Range,
DeathLink,
Toggle,
DefaultOnToggle,
StartInventoryPool,
ItemDict,
PerGameCommonOptions,
)
from Options import Choice, Range, DeathLink, Toggle, DefaultOnToggle, StartInventoryPool
from .creatures import all_creatures, Definitions
from .items import ItemType, item_names_by_type
class SwimRule(Choice):
@ -103,13 +116,28 @@ class SubnauticaDeathLink(DeathLink):
Note: can be toggled via in-game console command "deathlink"."""
option_definitions = {
"swim_rule": SwimRule,
"early_seaglide": EarlySeaglide,
"free_samples": FreeSamples,
"goal": Goal,
"creature_scans": CreatureScans,
"creature_scan_logic": AggressiveScanLogic,
"death_link": SubnauticaDeathLink,
"start_inventory_from_pool": StartInventoryPool,
}
class FillerItemsDistribution(ItemDict):
"""Random chance weights of various filler resources that can be obtained.
Available items: """
__doc__ += ", ".join(f"\"{item_name}\"" for item_name in item_names_by_type[ItemType.resource])
_valid_keys = frozenset(item_names_by_type[ItemType.resource])
default = {item_name: 1 for item_name in item_names_by_type[ItemType.resource]}
display_name = "Filler Items Distribution"
@cached_property
def weights_pair(self) -> typing.Tuple[typing.List[str], typing.List[int]]:
from itertools import accumulate
return list(self.value.keys()), list(accumulate(self.value.values()))
@dataclass
class SubnauticaOptions(PerGameCommonOptions):
swim_rule: SwimRule
early_seaglide: EarlySeaglide
free_samples: FreeSamples
goal: Goal
creature_scans: CreatureScans
creature_scan_logic: AggressiveScanLogic
death_link: SubnauticaDeathLink
start_inventory_from_pool: StartInventoryPool
filler_items_distribution: FillerItemsDistribution