2022-08-22 23:02:29 +00:00
|
|
|
import typing
|
2024-04-14 18:36:25 +00:00
|
|
|
from dataclasses import dataclass
|
|
|
|
from functools import cached_property
|
|
|
|
|
|
|
|
from Options import (
|
|
|
|
Choice,
|
|
|
|
Range,
|
|
|
|
DeathLink,
|
|
|
|
Toggle,
|
|
|
|
DefaultOnToggle,
|
|
|
|
StartInventoryPool,
|
|
|
|
ItemDict,
|
|
|
|
PerGameCommonOptions,
|
|
|
|
)
|
2022-08-22 23:02:29 +00:00
|
|
|
|
2023-10-15 02:51:52 +00:00
|
|
|
from .creatures import all_creatures, Definitions
|
2024-04-14 18:36:25 +00:00
|
|
|
from .items import ItemType, item_names_by_type
|
2021-09-17 02:32:36 +00:00
|
|
|
|
|
|
|
|
2022-11-28 06:43:04 +00:00
|
|
|
class SwimRule(Choice):
|
|
|
|
"""What logic considers ok swimming distances.
|
|
|
|
Easy: +200 depth from any max vehicle depth.
|
|
|
|
Normal: +400 depth from any max vehicle depth.
|
|
|
|
Warning: Normal can expect you to death run to a location (No viable return trip).
|
|
|
|
Hard: +600 depth from any max vehicle depth.
|
|
|
|
Warning: Hard may require bases, deaths, glitches, multi-tank inventory or other depth extending means.
|
|
|
|
Items: Expected depth is extended by items like seaglide, ultra glide fins and capacity tanks.
|
|
|
|
"""
|
|
|
|
display_name = "Swim Rule"
|
|
|
|
option_easy = 0
|
|
|
|
option_normal = 1
|
|
|
|
option_hard = 2
|
|
|
|
option_items_easy = 3
|
|
|
|
option_items_normal = 4
|
|
|
|
option_items_hard = 5
|
|
|
|
|
|
|
|
@property
|
|
|
|
def base_depth(self) -> int:
|
|
|
|
return [200, 400, 600][self.value % 3]
|
|
|
|
|
|
|
|
@property
|
|
|
|
def consider_items(self) -> bool:
|
|
|
|
return self.value > 2
|
|
|
|
|
|
|
|
|
2022-11-28 06:03:09 +00:00
|
|
|
class EarlySeaglide(DefaultOnToggle):
|
|
|
|
"""Make sure 2 of the Seaglide Fragments are available in or near the Safe Shallows (Sphere 1 Locations)."""
|
2022-12-21 15:54:43 +00:00
|
|
|
display_name = "Early Seaglide"
|
2022-11-28 06:03:09 +00:00
|
|
|
|
|
|
|
|
2023-04-24 13:49:19 +00:00
|
|
|
class FreeSamples(Toggle):
|
|
|
|
"""Get free items with your blueprints.
|
|
|
|
Items that can go into your inventory are awarded when you unlock their blueprint through Archipelago."""
|
|
|
|
display_name = "Free Samples"
|
|
|
|
|
|
|
|
|
2022-07-15 15:41:53 +00:00
|
|
|
class Goal(Choice):
|
|
|
|
"""Goal to complete.
|
|
|
|
Launch: Leave the planet.
|
|
|
|
Free: Disable quarantine.
|
|
|
|
Infected: Reach maximum infection level.
|
|
|
|
Drive: Repair the Aurora's Drive Core"""
|
|
|
|
auto_display_name = True
|
|
|
|
display_name = "Goal"
|
|
|
|
option_launch = 0
|
|
|
|
option_free = 1
|
|
|
|
option_infected = 2
|
|
|
|
option_drive = 3
|
|
|
|
|
|
|
|
def get_event_name(self) -> str:
|
|
|
|
return {
|
|
|
|
self.option_launch: "Neptune Launch",
|
|
|
|
self.option_infected: "Full Infection",
|
|
|
|
self.option_free: "Disable Quarantine",
|
|
|
|
self.option_drive: "Repair Aurora Drive"
|
|
|
|
}[self.value]
|
|
|
|
|
|
|
|
|
2022-07-16 14:45:40 +00:00
|
|
|
class CreatureScans(Range):
|
2022-08-22 21:35:41 +00:00
|
|
|
"""Place items on specific, randomly chosen, creature scans.
|
2022-07-16 14:45:40 +00:00
|
|
|
Warning: Includes aggressive Leviathans."""
|
|
|
|
display_name = "Creature Scans"
|
|
|
|
range_end = len(all_creatures)
|
|
|
|
|
|
|
|
|
2022-08-22 23:02:29 +00:00
|
|
|
class AggressiveScanLogic(Choice):
|
2022-08-22 21:35:41 +00:00
|
|
|
"""By default (Stasis), aggressive Creature Scans are logically expected only with a Stasis Rifle.
|
|
|
|
Containment: Removes Stasis Rifle as expected solution and expects Alien Containment instead.
|
|
|
|
Either: Creatures may be expected to be scanned via Stasis Rifle or Containment, whichever is found first.
|
|
|
|
None: Aggressive Creatures are assumed to not need any tools to scan.
|
2022-08-30 15:14:34 +00:00
|
|
|
Removed: No Creatures needing Stasis or Containment will be in the pool at all.
|
2022-08-22 21:35:41 +00:00
|
|
|
|
|
|
|
Note: Containment, Either and None adds Cuddlefish as an option for scans.
|
2022-08-30 15:14:34 +00:00
|
|
|
Note: Stasis, Either and None adds unhatchable aggressive species, such as Warper.
|
2022-08-22 21:35:41 +00:00
|
|
|
Note: This is purely a logic expectation, and does not affect gameplay, only placement."""
|
|
|
|
display_name = "Aggressive Creature Scan Logic"
|
|
|
|
option_stasis = 0
|
|
|
|
option_containment = 1
|
|
|
|
option_either = 2
|
|
|
|
option_none = 3
|
2022-08-30 15:14:34 +00:00
|
|
|
option_removed = 4
|
|
|
|
|
|
|
|
def get_pool(self) -> typing.List[str]:
|
|
|
|
if self == self.option_removed:
|
2022-11-03 02:05:58 +00:00
|
|
|
return Definitions.all_creatures_presorted_without_aggressive_and_containment
|
2022-08-30 15:14:34 +00:00
|
|
|
elif self == self.option_stasis:
|
|
|
|
return Definitions.all_creatures_presorted_without_containment
|
|
|
|
elif self == self.option_containment:
|
|
|
|
return Definitions.all_creatures_presorted_without_stasis
|
|
|
|
else:
|
|
|
|
return Definitions.all_creatures_presorted
|
2022-08-22 21:35:41 +00:00
|
|
|
|
|
|
|
|
2022-07-21 13:39:34 +00:00
|
|
|
class SubnauticaDeathLink(DeathLink):
|
2024-11-16 23:55:18 +00:00
|
|
|
__doc__ = DeathLink.__doc__ + "\n\n Note: can be toggled via in-game console command \"deathlink\"."
|
2022-07-21 13:39:34 +00:00
|
|
|
|
|
|
|
|
2024-04-14 18:36:25 +00:00
|
|
|
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])
|
2024-05-20 04:20:01 +00:00
|
|
|
valid_keys = sorted(item_names_by_type[ItemType.resource])
|
2024-04-14 18:36:25 +00:00
|
|
|
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
|