Subnautica: filler items distribution (#3104)
This commit is contained in:
parent
7b3727e945
commit
1c14d1107f
|
@ -4,7 +4,7 @@ import logging
|
||||||
import itertools
|
import itertools
|
||||||
from typing import List, Dict, Any, cast
|
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 worlds.AutoWorld import World, WebWorld
|
||||||
from . import items
|
from . import items
|
||||||
from . import locations
|
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()}
|
item_name_to_id = {data.name: item_id for item_id, data in items.item_table.items()}
|
||||||
location_name_to_id = all_locations
|
location_name_to_id = all_locations
|
||||||
option_definitions = options.option_definitions
|
options_dataclass = options.SubnauticaOptions
|
||||||
|
options: options.SubnauticaOptions
|
||||||
data_version = 10
|
data_version = 10
|
||||||
required_client_version = (0, 4, 1)
|
required_client_version = (0, 4, 1)
|
||||||
|
|
||||||
creatures_to_scan: List[str]
|
creatures_to_scan: List[str]
|
||||||
|
|
||||||
def generate_early(self) -> None:
|
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:
|
if self.options.early_seaglide:
|
||||||
self.multiworld.local_early_items[self.player]["Seaglide Fragment"] = 2
|
self.multiworld.local_early_items[self.player]["Seaglide Fragment"] = 2
|
||||||
|
|
||||||
|
@ -98,7 +100,7 @@ class SubnauticaWorld(World):
|
||||||
planet_region
|
planet_region
|
||||||
]
|
]
|
||||||
|
|
||||||
# refer to Rules.py
|
# refer to rules.py
|
||||||
set_rules = set_rules
|
set_rules = set_rules
|
||||||
|
|
||||||
def create_items(self):
|
def create_items(self):
|
||||||
|
@ -129,7 +131,7 @@ class SubnauticaWorld(World):
|
||||||
extras -= group_amount
|
extras -= group_amount
|
||||||
|
|
||||||
for item_name in self.random.sample(
|
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 Engine Fragment",
|
||||||
"Cyclops Hull Fragment",
|
"Cyclops Hull Fragment",
|
||||||
|
@ -140,7 +142,7 @@ class SubnauticaWorld(World):
|
||||||
"Modification Station Fragment",
|
"Modification Station Fragment",
|
||||||
"Moonpool Fragment",
|
"Moonpool Fragment",
|
||||||
"Laser Cutter Fragment",
|
"Laser Cutter Fragment",
|
||||||
],
|
],
|
||||||
k=min(extras, 9)):
|
k=min(extras, 9)):
|
||||||
item = self.create_item(item_name)
|
item = self.create_item(item_name)
|
||||||
pool.append(item)
|
pool.append(item)
|
||||||
|
@ -176,7 +178,10 @@ class SubnauticaWorld(World):
|
||||||
item_id, player=self.player)
|
item_id, player=self.player)
|
||||||
|
|
||||||
def get_filler_item_name(self) -> str:
|
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):
|
class SubnauticaLocation(Location):
|
||||||
|
|
|
@ -145,6 +145,9 @@ item_table: Dict[int, ItemData] = {
|
||||||
items_by_type: Dict[ItemType, List[int]] = {item_type: [] for item_type in ItemType}
|
items_by_type: Dict[ItemType, List[int]] = {item_type: [] for item_type in ItemType}
|
||||||
for item_id, item_data in item_table.items():
|
for item_id, item_data in item_table.items():
|
||||||
items_by_type[item_data.type].append(item_id)
|
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]] = {
|
group_items: Dict[int, Set[int]] = {
|
||||||
35100: {35025, 35047, 35048, 35056, 35057, 35058, 35059, 35060, 35061, 35062, 35063, 35064, 35065, 35067, 35068,
|
35100: {35025, 35047, 35048, 35056, 35057, 35058, 35059, 35060, 35061, 35062, 35063, 35064, 35065, 35067, 35068,
|
||||||
|
|
|
@ -1,7 +1,20 @@
|
||||||
import typing
|
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 .creatures import all_creatures, Definitions
|
||||||
|
from .items import ItemType, item_names_by_type
|
||||||
|
|
||||||
|
|
||||||
class SwimRule(Choice):
|
class SwimRule(Choice):
|
||||||
|
@ -103,13 +116,28 @@ class SubnauticaDeathLink(DeathLink):
|
||||||
Note: can be toggled via in-game console command "deathlink"."""
|
Note: can be toggled via in-game console command "deathlink"."""
|
||||||
|
|
||||||
|
|
||||||
option_definitions = {
|
class FillerItemsDistribution(ItemDict):
|
||||||
"swim_rule": SwimRule,
|
"""Random chance weights of various filler resources that can be obtained.
|
||||||
"early_seaglide": EarlySeaglide,
|
Available items: """
|
||||||
"free_samples": FreeSamples,
|
__doc__ += ", ".join(f"\"{item_name}\"" for item_name in item_names_by_type[ItemType.resource])
|
||||||
"goal": Goal,
|
_valid_keys = frozenset(item_names_by_type[ItemType.resource])
|
||||||
"creature_scans": CreatureScans,
|
default = {item_name: 1 for item_name in item_names_by_type[ItemType.resource]}
|
||||||
"creature_scan_logic": AggressiveScanLogic,
|
display_name = "Filler Items Distribution"
|
||||||
"death_link": SubnauticaDeathLink,
|
|
||||||
"start_inventory_from_pool": StartInventoryPool,
|
@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
|
||||||
|
|
Loading…
Reference in New Issue