mirror of
https://github.com/ArchipelagoMW/Archipelago.git
synced 2026-03-21 23:23:24 -07:00
* Added Satisfactory to latest master * Fixed hard drive from containing the mam + incremented default value for harddrive progression * Apply cherry pick of 3076259 * Apply cherry pick of 6114a55 * Clarify Point goal behavior (https://github.com/Jarno458/SatisfactoryArchipelagoMod/issues/98) * Update Setup guide and info page * Add links to Gifting and Energy Link compatible games. Add info on Hard Drive behavior * Fix typos * Update hard drive behavior description * Hopefully fixed the mam from getting placed behind harddrives * Add 1 "Bundle: Solid Biofuel" to default starting items (for later chainsaw usage or early power gen) * Add info/warning about save setup failure bug * Add notes about dedicated server setup * Fixes: `TypeError: 'set' object is not subscriptable` random.choice does not work over set objects, cast to a list to allow 'trap_selection_override' * progrees i think * Fixed some bugs * Progress commmit incase my pc crashes * progress i think as test passed * I guess test pass, game still unbeatable tho * its generating * Some refactorings * Fixed generation with different elevator tiers * Remove debug statement * Fix this link. * Implemented abstract base classes + some fixes * Implemented many many new options * Yay more stuff * Fixed renaming of filters * Added 1.1 stuffs * Added options groups and presets * Fixes after variable renmame * Added recipy groups for easyer hinting * Implemented random Tier 0 * Updated slot_data * Latest update for 1.1 * Applied cheaper building costs of assembler and foundry * Implemented exploration cost in slot_data * Fixed exposing option type * Add goal time estimates * Trap info * Added support for Universal Tracker Put more things in the never exclude pool for a more familiar gameplay * Added iron ore to build hub * Added Dark Matter Crystals * Added Single Dark Matter Crystals * Fixed typo in options preset * Update setup directions and info * Options formatting fixes, lower minimum ExplorationCollectableCount, add new Explorer starting inventory items preset * Fixed incorrect description on the options * Reduce Portable Miner and Reinforced Iron Plate quantities in "Skip Tutorial Inspired" starting preset * Fixed options pickling error * Reworked logic to no longer include Single: items as filler Reworked logic for more performance Reworked logic to always put useful equipment in pool * Fixed Itemlinks Removed space elevator parts from fillers Removed more AWESOME shop purchaseables from minimal item pool Added all equipment to minimal item pool Removed non fissile and fertile uranium from minimal item pool Removed portal from minimal item pool Removed Ionized fuel from minimal item pool Removed recipes for Hoverpack and Turbo Rifle Ammo from minimal item pool Lowered the chance for rolling steel on randomized starter recipes * Fixed hub milestone item leaking to into wrong milestones * Fixed unlock cost of geothermal generator * Fixed itemlinks again * Add troubleshooting note about hoverpacks * Add starting inventory bundle delivery info * Added hint generation at generation time Harddrive locations now go from 1-100 rather then 0-99 * Update __init__.py Fixed mistake * Cleaned docs to be better suited to get verified * Update CODEOWNERS Added Satisfactory * Update README.md Added Satisfactory * Restructure and expand setup page to instruct both players and hosts * Add terms entry for Archipelago mod * Fixed generation of traps * Added Robb as code owner * Restore tests to original state * Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Fix additional typos from code review * Implemented fix for itterating enum flags on python 3.10 * Update en_Satisfactory.md * Update setup_en.md * Apply suggestions from code review Co-authored-by: Scipio Wright <scipiowright@gmail.com> * more world > multiworld * Clarify universal tracker behavior * Fix typos * Info on smart hinting system * Move list of additional mods to a page on the mod GitHub * Restore revamped setup guide that other commits overwrote Originally frombe26511205,d8bd1aaf04* Removed bundle of ficsit coupons from the from the item pool added estimated completion times to space elevator option description * Apply suggestions from code review Co-authored-by: Scipio Wright <scipiowright@gmail.com> * Wording * Fix typo * Update with changes from ToBeVerified branch * Update note about gameplay options * Update note about gameplay options * Improved universal tracker handling * Improved universal tracker + modernized code a bit * Fixed bugs that where re-introduced * Added Recipe: Excited Photonic Matter * Removed python 3.9 workaround * Fixed * Apply suggestions from code review Co-authored-by: Scipio Wright <scipiowright@gmail.com> * Streamlined handle craftable logic by using itterable rather then tuple Removed dict.keys as the dict itzelf already enumerates over keys * Updated option description * Fixed typing * More info on goal completion conditions * More info on goal completion conditions (093fe38b6e) * Apply suggestions from code review Co-authored-by: Silvris <58583688+Silvris@users.noreply.github.com> * Implemented review results * PEP8 stuff * More PEP8 * Rename ElevatorTier->ElevatorPhase and related for clarity and consistency. Untested * speedups part1 * speedsups on part rules * Fix formatting * fix `Elevator Tier #` string literals missed in rename * Remove unused/duplicate imports + organize imports, `== None` to `is None` * Fixed after merge * Updated values + removed TODO * PEPed up the code * Small refactorings * Updated name slot data to phase * Fix hint creation * Clarify wording of elevator goal * Review result * Fixed minor typo in option * Update option time estimates --------- Co-authored-by: Rob B <computerguy440+gh@gmail.com> Co-authored-by: ProverbialPennance <36955346+ProverbialPennance@users.noreply.github.com> Co-authored-by: Joe Amenta <airbreather@linux.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Scipio Wright <scipiowright@gmail.com> Co-authored-by: Silvris <58583688+Silvris@users.noreply.github.com> Co-authored-by: NewSoupVi <57900059+NewSoupVi@users.noreply.github.com>
615 lines
23 KiB
Python
615 lines
23 KiB
Python
from dataclasses import dataclass
|
|
from typing import ClassVar, Any, cast
|
|
from enum import IntEnum
|
|
from schema import Schema, And
|
|
from Options import PerGameCommonOptions, DeathLinkMixin, AssembleOptions, OptionGroup
|
|
from Options import Range, NamedRange, Toggle, DefaultOnToggle, OptionSet, StartInventoryPool, Choice
|
|
|
|
|
|
class Placement(IntEnum):
|
|
starting_inventory = 0
|
|
early = 1
|
|
somewhere = 2
|
|
|
|
|
|
class PlacementLogicMeta(AssembleOptions):
|
|
def __new__(mcs, name: str, bases: tuple[type], attrs: dict[Any, Any]) -> "PlacementLogicMeta":
|
|
if "default" in attrs and isinstance(attrs["default"], Placement):
|
|
attrs["default"] = int(attrs["default"])
|
|
|
|
cls = super(PlacementLogicMeta, mcs).__new__(mcs, name, bases, attrs)
|
|
return cast(PlacementLogicMeta, cls)
|
|
|
|
|
|
class PlacementLogic(Choice, metaclass=PlacementLogicMeta):
|
|
option_unlocked_from_start = Placement.starting_inventory.value
|
|
option_early_game = Placement.early.value
|
|
option_somewhere = Placement.somewhere.value
|
|
|
|
|
|
class ChoiceMapMeta(AssembleOptions):
|
|
def __new__(mcs, name: str, bases: tuple[type], attrs: dict[Any, Any]) -> "ChoiceMapMeta":
|
|
if "choices" in attrs:
|
|
for index, choice in enumerate(attrs["choices"]):
|
|
option_name = "option_" + choice.replace(' ', '_')
|
|
attrs[option_name] = index
|
|
|
|
if "default" in attrs and attrs["default"] == choice:
|
|
attrs["default"] = index
|
|
|
|
cls = super(ChoiceMapMeta, mcs).__new__(mcs, name, bases, attrs)
|
|
return cast(ChoiceMapMeta, cls)
|
|
|
|
|
|
class ChoiceMap(Choice, metaclass=ChoiceMapMeta):
|
|
choices: ClassVar[dict[str, list[str]]]
|
|
default: str
|
|
|
|
def get_selected_list(self) -> list[str]:
|
|
for index, choice in enumerate(self.choices):
|
|
if index == self.value:
|
|
return self.choices[choice]
|
|
|
|
raise Exception(f"ChoiceMap: selected choice {self.value} is not valid, valid choices are: {self.choices.keys()}")
|
|
|
|
|
|
class ElevatorPhase(NamedRange):
|
|
"""
|
|
Put the milestones accessible BEFORE this Space Elevator Phase in logic.
|
|
Milestones after the selected Phase are empty and contain nothing.
|
|
If your goal selection contains *Space Elevator Phase* then submitting this Phase's elevator package completes that goal.
|
|
If the goal is not enabled, this setting simply limits the HUB's content.
|
|
|
|
Estimated in-game completion times:
|
|
|
|
- **Phase 1 (Tiers 1-2)**: ~3 Hours
|
|
- **Phase 2 (Tiers 1-4)**: ~8 Hours
|
|
- **Phase 3 (Tiers 1-6)**: ~50 Hours
|
|
- **Phase 4 (Tiers 1-8)**: ~100 Hours
|
|
- **Phase 5 (Tiers 1-9)**: ~150 Hours
|
|
"""
|
|
display_name = "Final Space Elevator Phase in logic"
|
|
default = 2
|
|
range_start = 1
|
|
range_end = 5
|
|
special_range_names = {
|
|
"phase 1 (tiers 1-2)": 1,
|
|
"phase 2 (tiers 1-4)": 2,
|
|
"phase 3 (tiers 1-6)": 3,
|
|
"phase 4 (tiers 1-8)": 4,
|
|
"phase 5 (tiers 1-9)": 5,
|
|
}
|
|
|
|
|
|
class ResourceSinkPointsTotal(NamedRange):
|
|
"""
|
|
Does nothing if *AWESOME Sink Points (total)* goal is not enabled.
|
|
|
|
Sink an amount of items totalling this amount of points to finish.
|
|
This setting is a *point count*, not a *coupon* count!
|
|
|
|
In the base game, it takes 347 coupons to unlock every non-repeatable purchase, or 1895 coupons to purchase every non-producible item.
|
|
|
|
Use the **TFIT - Ficsit Information Tool** mod or the Satisfactory wiki to find out how many points items are worth.
|
|
|
|
If you have *Free Samples* enabled, consider setting this higher so that you can't reach the goal just by sinking your Free Samples.
|
|
"""
|
|
# Coupon data for above comment from https://satisfactory.wiki.gg/wiki/AWESOME_Shop
|
|
display_name = "AWESOME Sink points total"
|
|
default = 2166000
|
|
range_start = 2166000
|
|
range_end = 18436379500
|
|
special_range_names = {
|
|
"50 coupons (~2m points)": 2166000,
|
|
"100 coupons (~18m points)": 17804500,
|
|
"150 coupons (~61m points)": 60787500,
|
|
"200 coupons (~145m points)": 145053500,
|
|
"250 coupons (~284m points)": 284442000,
|
|
"300 coupons (~493m points)": 492825000,
|
|
"350 coupons (~784m points)": 784191000,
|
|
"400 coupons (~1,2b points)": 1172329500,
|
|
"450 coupons (~1,7b points)": 1671112500,
|
|
"500 coupons (~2b points)": 2294578500,
|
|
"550 coupons (~3b points)": 3056467000,
|
|
"600 coupons (~4b points)": 3970650000,
|
|
"650 coupons (~5b points)": 5051216000,
|
|
"700 coupons (~6b points)": 6311854500,
|
|
"750 coupons (~8b points)": 7766437500,
|
|
"800 coupons (~9b points)": 9429103500,
|
|
"850 coupons (~11b points)": 11313492000,
|
|
"900 coupons (~13b points)": 13433475000,
|
|
"950 coupons (~16b points)": 15803241000,
|
|
"1000 coupons (~18b points)": 18436379500
|
|
}
|
|
|
|
|
|
class ResourceSinkPointsPerMinute(NamedRange):
|
|
"""
|
|
Does nothing if *AWESOME Sink Points (per minute)* goal is not enabled.
|
|
|
|
Sink items to maintain a sink points per minute of the chosen amount for 10 minutes to finish.
|
|
This setting is in *points per minute* on the orange track, so DNA Capsules don't count.
|
|
This option's presets are example production thresholds - you don't have to sink exactly those specific items.
|
|
|
|
Use the **TFIT - Ficsit Information Tool** mod or the Satisfactory wiki to find out how many points items are worth.
|
|
"""
|
|
# Coupon data for above comment from https://satisfactory.wiki.gg/wiki/AWESOME_Shop
|
|
display_name = "AWESOME Sink points per minute"
|
|
default = 50000
|
|
range_start = 1000
|
|
range_end = 10000000
|
|
special_range_names = {
|
|
"~500 screw/min": 1000,
|
|
"~100 reinforced iron plate/min": 12000,
|
|
"~100 stator/min": 24000,
|
|
"~100 modular frame/min": 40000,
|
|
"~100 smart plating/min": 50000,
|
|
"~20 crystal oscillator/min": 60000,
|
|
"~50 motor/min": 76000,
|
|
"~10 heavy modular frame/min": 100000,
|
|
"~10 radio control unit/min": 300000,
|
|
"~10 fused modular frame/min": 625000,
|
|
"~10 supercomputer/min": 1000000,
|
|
"~10 pressure conversion cube/min": 2500000,
|
|
"~10 nuclear pasta/min": 5000000,
|
|
"~4 ballistic warp drive/min": 10000000,
|
|
}
|
|
|
|
|
|
class HardDriveProgressionLimit(Range):
|
|
"""
|
|
How many Hard Drives can contain progression items.
|
|
Hard Drives above this count cannot contain progression, but can still be Useful.
|
|
|
|
There are 118 total hard drives in the world and the current implementation supports up to 100 progression hard drives.
|
|
"""
|
|
display_name = "Hard Drive Progression Items"
|
|
default = 20
|
|
range_start = 0
|
|
range_end = 100
|
|
|
|
|
|
class FreeSampleEquipment(Range):
|
|
"""
|
|
How many free sample Equipment items are given when they are unlocked.
|
|
|
|
(ex. Jetpack, Rifle)
|
|
"""
|
|
display_name = "Free Samples: Equipment"
|
|
default = 1
|
|
range_start = 0
|
|
range_end = 10
|
|
|
|
|
|
class FreeSampleBuildings(Range):
|
|
"""
|
|
How many copies of a Building's construction cost are given as a free sample when they are unlocked.
|
|
Space Elevator is always excluded.
|
|
|
|
(ex. Packager, Constructor, Smelter)
|
|
"""
|
|
display_name = "Free Samples: Buildings"
|
|
default = 5
|
|
range_start = 0
|
|
range_end = 10
|
|
|
|
|
|
class FreeSampleParts(NamedRange):
|
|
"""
|
|
How many general crafting component free samples are given when their recipe is unlocked.
|
|
Space Elevator Project Parts are always excluded.
|
|
|
|
Negative numbers mean that fraction of a full stack.
|
|
|
|
(ex. Iron Plate, Packaged Turbofuel, Reinforced Modular Frame)
|
|
"""
|
|
display_name = "Free Samples: Parts"
|
|
default = -2
|
|
range_start = -5
|
|
range_end = 500
|
|
special_range_names = {
|
|
"disabled": 0,
|
|
"half_stack": -2,
|
|
"one_stack": -1,
|
|
"1": 1,
|
|
"50": 50,
|
|
"100": 100,
|
|
"200": 200,
|
|
"500": 500,
|
|
}
|
|
|
|
|
|
class FreeSampleRadioactive(Toggle):
|
|
"""
|
|
Allow free samples to include radioactive parts.
|
|
Remember, they are delivered directly to your player inventory.
|
|
"""
|
|
display_name = "Free Samples: Radioactive"
|
|
|
|
|
|
class TrapChance(Range):
|
|
"""
|
|
Chance of traps in the item pool.
|
|
Traps will only replace filler items such as parts and resources.
|
|
|
|
- **0:** No traps will be present
|
|
- **100:** Every filler item will be a trap.
|
|
"""
|
|
display_name = "Trap Chance"
|
|
range_start = 0
|
|
range_end = 100
|
|
default = 10
|
|
|
|
|
|
_trap_types = {
|
|
"Trap: Doggo with Pulse Nobelisk",
|
|
"Trap: Doggo with Nuke Nobelisk",
|
|
"Trap: Doggo with Gas Nobelisk",
|
|
"Trap: Hog",
|
|
"Trap: Alpha Hog",
|
|
"Trap: Cliff Hog",
|
|
"Trap: Nuclear Hog",
|
|
"Trap: Johnny",
|
|
"Trap: Hatcher",
|
|
"Trap: Elite Hatcher",
|
|
"Trap: Small Stinger",
|
|
"Trap: Stinger",
|
|
"Trap: Gas Stinger",
|
|
"Trap: Spore Flower",
|
|
"Trap: Spitter",
|
|
"Trap: Alpha Spitter",
|
|
"Trap: Not the Bees",
|
|
"Trap: Nuclear Waste Drop",
|
|
"Trap: Plutonium Waste Drop",
|
|
"Trap: Can of Beans",
|
|
"Trap: Fart Cloud",
|
|
|
|
# Radioactive parts delivered via portal
|
|
"Bundle: Uranium",
|
|
"Bundle: Uranium Fuel Rod",
|
|
"Bundle: Uranium Waste",
|
|
"Bundle: Plutonium Fuel Rod",
|
|
"Bundle: Plutonium Pellet",
|
|
"Bundle: Plutonium Waste",
|
|
"Bundle: Non-fissile Uranium",
|
|
"Bundle: Ficsonium",
|
|
"Bundle: Ficsonium Fuel Rod"
|
|
}
|
|
|
|
|
|
class TrapSelectionPreset(ChoiceMap):
|
|
"""
|
|
Themed presets of trap types to enable.
|
|
|
|
If you want more control, use *Trap Override* or visit the Weighted Options page.
|
|
"""
|
|
display_name = "Trap Presets"
|
|
choices = {
|
|
"Gentle": ["Trap: Doggo with Pulse Nobelisk", "Trap: Hog", "Trap: Spitter", "Trap: Can of Beans"],
|
|
"Normal": ["Trap: Doggo with Pulse Nobelisk", "Trap: Doggo with Gas Nobelisk", "Trap: Hog", "Trap: Alpha Hog", "Trap: Hatcher", "Trap: Elite Hatcher", "Trap: Small Stinger", "Trap: Stinger", "Trap: Spitter", "Trap: Alpha Spitter", "Trap: Not the Bees", "Trap: Nuclear Waste Drop", "Bundle: Uranium", "Bundle: Non-fissile Uranium", "Trap: Can of Beans", "Trap: Fart Cloud"],
|
|
"Harder": ["Trap: Doggo with Pulse Nobelisk", "Trap: Doggo with Nuke Nobelisk", "Trap: Doggo with Gas Nobelisk", "Trap: Alpha Hog", "Trap: Cliff Hog", "Trap: Spore Flower", "Trap: Hatcher", "Trap: Elite Hatcher", "Trap: Stinger", "Trap: Alpha Spitter", "Trap: Not the Bees", "Trap: Fart Cloud", "Trap: Nuclear Waste Drop", "Trap: Plutonium Waste Drop", "Bundle: Uranium", "Bundle: Uranium Fuel Rod", "Bundle: Uranium Waste", "Bundle: Plutonium Fuel Rod", "Bundle: Plutonium Pellet", "Bundle: Plutonium Waste", "Bundle: Non-fissile Uranium"],
|
|
"All": list(_trap_types),
|
|
"Ruthless": ["Trap: Doggo with Nuke Nobelisk", "Trap: Nuclear Hog", "Trap: Cliff Hog", "Trap: Elite Hatcher", "Trap: Spore Flower", "Trap: Gas Stinger", "Trap: Nuclear Waste Drop", "Trap: Plutonium Waste Drop", "Bundle: Uranium Fuel Rod", "Bundle: Uranium Waste", "Bundle: Plutonium Fuel Rod", "Bundle: Plutonium Pellet", "Bundle: Plutonium Waste", "Bundle: Non-fissile Uranium", "Bundle: Ficsonium", "Bundle: Ficsonium Fuel Rod"],
|
|
"All Arachnids All the Time": ["Trap: Small Stinger", "Trap: Stinger", "Trap: Gas Stinger"],
|
|
"Whole Hog": ["Trap: Hog", "Trap: Alpha Hog", "Trap: Cliff Hog", "Trap: Nuclear Hog", "Trap: Johnny"],
|
|
"Nicholas Cage": ["Trap: Hatcher", "Trap: Elite Hatcher", "Trap: Not the Bees"],
|
|
"Fallout": ["Trap: Doggo with Nuke Nobelisk", "Trap: Nuclear Hog", "Trap: Nuclear Waste Drop", "Trap: Plutonium Waste Drop", "Bundle: Uranium", "Bundle: Uranium Fuel Rod", "Bundle: Uranium Waste", "Bundle: Plutonium Fuel Rod", "Bundle: Plutonium Waste", "Bundle: Ficsonium", "Bundle: Ficsonium Fuel Rod"],
|
|
}
|
|
default = "Normal"
|
|
|
|
|
|
class TrapSelectionOverride(OptionSet):
|
|
"""
|
|
Precise list of traps that may be in the item pool to find.
|
|
If you select anything with this option it will be used instead of the *Trap Presets* setting.
|
|
"""
|
|
display_name = "Trap Override"
|
|
valid_keys = _trap_types
|
|
|
|
|
|
class EnergyLink(DefaultOnToggle):
|
|
"""
|
|
Allow transferring energy to and from other worlds using the Power Storage building.
|
|
No energy is lost in the transfer on Satisfactory's side, but other worlds may have other settings.
|
|
"""
|
|
display_name = "EnergyLink"
|
|
|
|
|
|
class MamLogic(PlacementLogic):
|
|
"""
|
|
Where to place the MAM building in logic.
|
|
Earlier means it will be more likely that you will need to interact with it for progression purposes.
|
|
"""
|
|
display_name = "MAM Placement"
|
|
default = Placement.early.value
|
|
|
|
|
|
class AwesomeLogic(PlacementLogic):
|
|
"""
|
|
Where to place the AWESOME Shop and Sink buildings in logic.
|
|
Earlier means it will be more likely that you will need to interact with it for progression purposes.
|
|
"""
|
|
display_name = "AWESOME Stuff Placement"
|
|
default = Placement.early.value
|
|
|
|
|
|
class EnergyLinkLogic(PlacementLogic):
|
|
"""
|
|
Where to place the EnergyLink building (or Power Storage if EnergyLink is disabled) in logic.
|
|
Earlier means it will be more likely that you will need to interact with it for progression purposes.
|
|
"""
|
|
display_name = "EnergyLink Placement"
|
|
default = Placement.early.value
|
|
|
|
|
|
class SplitterLogic(PlacementLogic):
|
|
"""
|
|
Where to place the Conveyor Splitter and Merger buildings in logic.
|
|
Earlier means it will be more likely that you will need to interact with it for progression purposes.
|
|
"""
|
|
display_name = "Splitter and Merger Placement"
|
|
default = Placement.starting_inventory.value
|
|
|
|
|
|
_skip_tutorial_starting_items = [
|
|
# https://satisfactory.wiki.gg/wiki/Onboarding
|
|
"Single: Portable Miner",
|
|
"Single: Portable Miner",
|
|
"Single: Portable Miner",
|
|
"Single: Portable Miner",
|
|
"Bundle: Iron Plate",
|
|
"Bundle: Concrete",
|
|
"Bundle: Iron Rod",
|
|
"Bundle: Wire",
|
|
"Single: Reinforced Iron Plate",
|
|
"Single: Reinforced Iron Plate",
|
|
"Single: Reinforced Iron Plate",
|
|
"Single: Reinforced Iron Plate",
|
|
"Single: Reinforced Iron Plate",
|
|
"Single: Reinforced Iron Plate",
|
|
"Single: Reinforced Iron Plate",
|
|
"Single: Reinforced Iron Plate",
|
|
"Single: Reinforced Iron Plate",
|
|
"Single: Reinforced Iron Plate",
|
|
"Bundle: Cable",
|
|
"Bundle: Iron Ore"
|
|
]
|
|
|
|
_default_starting_items = _skip_tutorial_starting_items + [
|
|
"Bundle: Iron Ingot",
|
|
"Bundle: Copper Ingot",
|
|
"Bundle: Concrete",
|
|
"Bundle: Solid Biofuel", # user's choice if they want to hold onto it for chainsaw or burn it right away
|
|
"Building: Blueprint Designer",
|
|
"Expanded Toolbelt",
|
|
"Inflated Pocket Dimension",
|
|
"Building: Personal Storage Box"
|
|
]
|
|
|
|
_default_plus_foundations_starting_items = _default_starting_items + [
|
|
"Building: Foundation",
|
|
"Building: Half Foundation"
|
|
]
|
|
|
|
_explorer_starting_items = _default_plus_foundations_starting_items + [
|
|
"Single: Parachute",
|
|
"Single: Blade Runners",
|
|
"Single: Object Scanner",
|
|
"Single: Boom Box",
|
|
"Expanded Toolbelt",
|
|
"Inflated Pocket Dimension"
|
|
]
|
|
|
|
_foundation_lover_starting_items = _default_plus_foundations_starting_items + [
|
|
"Bundle: Iron Plate", "Bundle: Iron Plate", "Bundle: Iron Plate",
|
|
"Bundle: Concrete", "Bundle: Concrete", "Bundle: Concrete"
|
|
]
|
|
|
|
|
|
class StartingInventoryPreset(ChoiceMap):
|
|
"""
|
|
What resources (and buildings) the player should start with in their inventory.
|
|
If you want more control, visit the Weighted Options page or edit the YAML directly.
|
|
|
|
- **Barebones**: Nothing but the default xeno zapper and buildings.
|
|
- **Skip Tutorial Inspired**: Inspired by the items you would have if you skipped the base game's tutorial.
|
|
- **Archipelago**: The starting items we think will lead to a fun experience.
|
|
- **Foundations**: 'Archipelago' option, but also guaranteeing that you have foundations unlocked at the start.
|
|
- **Foundation Lover**: You really like foundations.
|
|
- **Explorer**: 'Foundations' option plus one set of early exploration equipment (Parachute, Blade Runners, Object Scanner, Boom Box).
|
|
"""
|
|
display_name = "Starting Goodies Presets"
|
|
choices = {
|
|
"Barebones": [], # Nothing but the xeno zapper
|
|
"Skip Tutorial Inspired": _skip_tutorial_starting_items,
|
|
"Archipelago": _default_starting_items,
|
|
"Foundations": _default_plus_foundations_starting_items,
|
|
"Foundation Lover": _foundation_lover_starting_items,
|
|
"Explorer": _explorer_starting_items
|
|
}
|
|
default = "Archipelago"
|
|
|
|
|
|
class ExplorationCollectableCount(Range):
|
|
"""
|
|
Does nothing if *Exploration Collectables* goal is not enabled.
|
|
|
|
Collect this amount of Mercer Spheres, Somersloops, Hard Drives, Paleberries, Beryl Nuts, and Bacon Agarics each to finish.
|
|
|
|
- The amount of **Mercer Spheres** is **2x** the selected amount
|
|
- The amount of **Somersloops** is **the** selected amount
|
|
- The amount of **Hard Drives** is **1/5th** the selected amount
|
|
- The amount of **Paleberries** is **10x** the selected amount
|
|
- The amount of **Beryl Nuts** is **20x** the selected amount
|
|
- The amount of **Bacon Agarics** is **the** selected amount
|
|
"""
|
|
display_name = "Exploration Collectables"
|
|
default = 20
|
|
range_start = 5
|
|
range_end = 100
|
|
|
|
|
|
class MilestoneCostMultiplier(Range):
|
|
"""
|
|
Multiplies the amount of resources needed to unlock a Milestone by this factor.
|
|
|
|
The value is a percentage:
|
|
|
|
- **50** = half cost
|
|
- **100** = normal milestone cost
|
|
- **200** = double the cost
|
|
"""
|
|
display_name = "Milestone cost multiplier %"
|
|
default = 100
|
|
range_start = 1
|
|
range_end = 500
|
|
|
|
|
|
class GoalSelection(OptionSet):
|
|
"""
|
|
What will be your goal(s)?
|
|
Configure them further with other options.
|
|
|
|
Possible values are:
|
|
- **Space Elevator Tier**
|
|
- **AWESOME Sink Points (total)**
|
|
- **AWESOME Sink Points (per minute)**
|
|
- **Exploration Collectables**
|
|
"""
|
|
display_name = "Select your Goals"
|
|
valid_keys = {
|
|
"Space Elevator Phase",
|
|
"AWESOME Sink Points (total)",
|
|
"AWESOME Sink Points (per minute)",
|
|
"Exploration Collectables",
|
|
# "Erect a FICSMAS Tree",
|
|
}
|
|
default = {"Space Elevator Phase"}
|
|
schema = Schema(And(set, len),
|
|
error="yaml does not specify a goal, the Satisfactory option `goal_selection` is empty")
|
|
|
|
|
|
class GoalRequirement(Choice):
|
|
"""
|
|
Of the goals selected in *Select your Goals*, how many must be reached to complete your slot?
|
|
"""
|
|
display_name = "Goal Requirements"
|
|
option_require_any_one_goal = 0
|
|
option_require_all_goals = 1
|
|
default = 0
|
|
|
|
|
|
class RandomizeTier0(DefaultOnToggle):
|
|
"""
|
|
Randomizes what recipes you use to craft the default unlocked parts:
|
|
Iron Ingot, Iron Plate, Iron Rod, Copper Ingot, Wire, Concrete, Screw, Reinforced Iron Plate
|
|
|
|
* Could require usage of Foundries or Assemblers (which get unlocked by default if needed, at reduced build costs)
|
|
* Could require other ores to be mixed in via alt recipes (which will become hand-craftable if needed)
|
|
"""
|
|
display_name = "Randomize Default Part Recipes"
|
|
|
|
|
|
@dataclass
|
|
class SatisfactoryOptions(PerGameCommonOptions, DeathLinkMixin):
|
|
goal_selection: GoalSelection
|
|
goal_requirement: GoalRequirement
|
|
final_elevator_phase: ElevatorPhase
|
|
goal_awesome_sink_points_total: ResourceSinkPointsTotal
|
|
goal_awesome_sink_points_per_minute: ResourceSinkPointsPerMinute
|
|
goal_exploration_collectables_amount: ExplorationCollectableCount
|
|
hard_drive_progression_limit: HardDriveProgressionLimit
|
|
free_sample_equipment: FreeSampleEquipment
|
|
free_sample_buildings: FreeSampleBuildings
|
|
free_sample_parts: FreeSampleParts
|
|
free_sample_radioactive: FreeSampleRadioactive
|
|
starting_inventory_preset: StartingInventoryPreset
|
|
mam_logic_placement: MamLogic
|
|
awesome_logic_placement: AwesomeLogic
|
|
energy_link_logic_placement: EnergyLinkLogic
|
|
splitter_placement: SplitterLogic
|
|
milestone_cost_multiplier: MilestoneCostMultiplier
|
|
trap_chance: TrapChance
|
|
trap_selection_preset: TrapSelectionPreset
|
|
trap_selection_override: TrapSelectionOverride
|
|
energy_link: EnergyLink
|
|
start_inventory_from_pool: StartInventoryPool
|
|
randomize_starter_recipes: RandomizeTier0
|
|
|
|
|
|
option_groups = [
|
|
OptionGroup("Game Scope", [
|
|
ElevatorPhase,
|
|
HardDriveProgressionLimit
|
|
]),
|
|
OptionGroup("Goal Selection", [
|
|
GoalSelection,
|
|
GoalRequirement,
|
|
ResourceSinkPointsTotal,
|
|
ResourceSinkPointsPerMinute,
|
|
ExplorationCollectableCount
|
|
]),
|
|
OptionGroup("Placement logic", [
|
|
StartingInventoryPreset,
|
|
RandomizeTier0,
|
|
MamLogic,
|
|
AwesomeLogic,
|
|
SplitterLogic,
|
|
EnergyLinkLogic
|
|
], start_collapsed=True),
|
|
OptionGroup("Free Samples", [
|
|
FreeSampleEquipment,
|
|
FreeSampleBuildings,
|
|
FreeSampleParts,
|
|
FreeSampleRadioactive
|
|
], start_collapsed=True),
|
|
OptionGroup("Traps", [
|
|
TrapChance,
|
|
TrapSelectionPreset,
|
|
TrapSelectionOverride
|
|
], start_collapsed=True)
|
|
]
|
|
|
|
option_presets: dict[str, dict[str, Any]] = {
|
|
"Short": {
|
|
"final_elevator_phase": 1,
|
|
"goal_selection": {"Space Elevator Phase", "AWESOME Sink Points (total)"},
|
|
"goal_requirement": GoalRequirement.option_require_any_one_goal,
|
|
"goal_awesome_sink_points_total": 17804500, # 100 coupons
|
|
"hard_drive_progression_limit": 20,
|
|
"starting_inventory_preset": 3, # "Foundations"
|
|
"randomize_starter_recipes": False,
|
|
"mam_logic_placement": Placement.starting_inventory.value,
|
|
"awesome_logic_placement": Placement.starting_inventory.value,
|
|
"energy_link_logic_placement": Placement.starting_inventory.value,
|
|
"splitter_placement": Placement.starting_inventory.value,
|
|
"milestone_cost_multiplier": 50,
|
|
"trap_selection_preset": 1 # Gentle
|
|
},
|
|
"Long": {
|
|
"final_elevator_phase": 3,
|
|
"goal_selection": {"Space Elevator Phase", "AWESOME Sink Points (per minute)"},
|
|
"goal_requirement": GoalRequirement.option_require_all_goals,
|
|
"goal_awesome_sink_points_per_minute": 100000, # ~10 heavy modular frame/min
|
|
"hard_drive_progression_limit": 60,
|
|
"mam_logic_placement": Placement.somewhere.value,
|
|
"awesome_logic_placement": Placement.somewhere.value,
|
|
"energy_link_logic_placement": Placement.somewhere.value,
|
|
"splitter_placement": Placement.somewhere.value,
|
|
"trap_selection_preset": 3 # Harder
|
|
},
|
|
"Extra Long": {
|
|
"final_elevator_phase": 5,
|
|
"goal_selection": {"Space Elevator Phase", "AWESOME Sink Points (per minute)"},
|
|
"goal_requirement": GoalRequirement.option_require_all_goals,
|
|
"goal_awesome_sink_points_per_minute": 625000, # ~10 fused modular frame/min
|
|
"hard_drive_progression_limit": 100,
|
|
"mam_logic_placement": Placement.somewhere.value,
|
|
"awesome_logic_placement": Placement.somewhere.value,
|
|
"energy_link_logic_placement": Placement.somewhere.value,
|
|
"splitter_placement": Placement.somewhere.value,
|
|
"milestone_cost_multiplier": 300,
|
|
"trap_selection_preset": 4 # All
|
|
}
|
|
}
|