Ostranaut Explorer

user story · EXPLORER

User story — HygieneStation Mod

Source mod: test-data/mods/HygieneStation/ Original mod by: Voideka (mod version 1.5, game version 0.14.3.6)


The goal

A modder has watched their crew's hygiene stat degrade on long hauls with no sink. They know the game has a hygiene need, and they know the existing Sink object handles it. They want to create a new installable furniture piece — a sponge-bath station that draws from an internal water reservoir — that crew can use to maintain hygiene when a plumbed sink isn't available.

This is a "add a new thing to the game" mod, not a "tune an existing value" mod. The modder needs to create entries across several folders that didn't exist before.

They know what they want in the game. They do not know how the Sink works in data, or how to build a new installable item from scratch.


The journey

Step 1 — Find how the existing Sink works

The modder searches for Sink (something they know from in-game). They find condowners:ItmSink01. The detail page shows:

From the Sink's incoming refs the modder sees that installables:SinkInstall and installables:SinkUninstall reference it — those define the install/uninstall actions with tool requirements and progress stats.

Explorer outcome: The modder has a working template. A new installable hygiene item needs: a condowner entry (installed + loose variants), an items entry (visual), a conditions_simple entry (new condition), condtrigs (gates), interactions (use chain), loot entries (contents + destroy), and installables (install/uninstall).

Step 2 — Understand the installed vs. loose variant pattern

The Sink has two condowner entries: ItmSink01 (installed, wall-mounted) and ItmSink01Loose (carried in inventory). The explorer's per-prefix explainer ("About installable items") explains this pattern:

Explorer outcome: The modder understands why there are two entries and what differs between them. They can copy this pattern for ItmHygieneStation and ItmHygieneStationLoose.

Step 3 — Understand condition gating via condtrigs

On the Sink's SeekHygieneWater interaction detail page, the CTTestThem field references condtrigs:TIsHygieneWater. The condtrig detail page shows its aReqs: ["IsHygieneSink", "IsWater"] with bAND: false — meaning the target must have IsHygieneSink OR IsWater.

The modder's new station needs a parallel path: TIsHygieneWater should also match when the target has IsHygieneStation — or the mod needs its own TIsHygieneWater override that adds IsHygieneStation to the OR list.

The explorer shows the incoming refs of condtrigs:TIsHygieneWater — which interactions test against it — making it clear that overriding this one condtrig would affect all hygiene interactions.

Explorer outcome: The modder understands that the Hygiene Station mod creates its own new condition (IsHygieneStation) and its own parallel condtrigs (TIsHygieneStation, TIsHygieneStationInstalled, TIsHygieneWater) rather than modifying base-game entries — a safer, non-destructive pattern.

Step 4 — Understand conditions_simple

The modder sees IsHygieneSink referenced in condtrigs but doesn't find it in conditions/. The explorer's folder note explains: simple conditions live in conditions_simple/ as a shorthand format — each row defines a condition by "strName,strNameFriendly,strDesc,nPriority,nLayer,strCategory,bHidden".

Explorer outcome: The modder knows they need one conditions_simple/ entry to register IsHygieneStation before any condtrig or condowner can reference it.

Step 5 — Follow the interaction chain

The SeekHygieneWater interaction on the Sink is the opener (bOpener: true). The aInverse field chains to internal interactions. On the Hygiene Station the chain is:

SeekHygieneWater  (opener, CTTestThem: TIsHygieneWater)
  → SeekHygieneHygieneStation  (seeks an installed station)
  → ACTSeekHygieneWater         (seeks loose water in the station's container)
  → ACTSeekHygieneDeny          (deny fallback)

SeekHygieneHygieneStation
  → ACTSeekHygieneStationDenyWater   (station has no water → wander)
  → ACTSeekHygieneAllowHygieneStation (station has water → sit, begin cleanse)

ACTSeekHygieneAllowHygieneStation
  → ACTSeekHygieneAllowHygieneStationCleanse  (consume water, apply hygiene conditions)
  → ACTSeekHygieneAllowHygieneStationDone     (finish, done-using)

The explorer's outgoing refs panel with DSL primer popovers on aInverse entries makes this chain readable. Each step's LootCTsUs / LootCTsThem fields grant/remove conditions as the action progresses.

Explorer outcome: The modder can trace the full state machine without reading raw JSON. They understand aInverse as a prioritized fallback list, LootCTsUs/LootCTsThem as condition grants, and CTTestUs/CTTestThem as the gates that select which branch fires.

Step 6 — Understand loot entries for contents and destruction

The aUpdateCommands entry Destructable,StatDamage,ACTHygieneStationDmg,StatDamageMax,1.0 references loot:ACTHygieneStationDmg with strType: interaction. The loot entry's aCOs grant MSDestroyDefault=1.0x1 — the standard destroy condition.

The station also has loot entries for salvage contents (ItmHygieneStationSalvageContents, ItmHygieneStationStationContents) defining what drops when the station is looted or dismantled, and ItmHygieneStationNew (bNested: true, bSuppress: true) for initial spawn contents.

Explorer outcome: The modder understands that loot entries serve multiple roles: initial contents (bNested), salvage payouts, and interaction delegates (strType: interaction used by aUpdateCommands).

Step 7 — Understand installables

The installables:HygieneStationInstall entry shows:

Explorer outcome: The modder can write their own installable entry by following this template. The strInteractionTemplate reference to interactions:ACTInstallTEMP is visible as an outgoing ref link — clicking through shows what the template looks like.


Files in the mod's implementation

FileWhat it does
data/conditions_simple/conditions_simple.jsonRegisters IsHygieneStation — the marker condition that identifies this item type. Must exist before any condtrig or condowner references it.
data/condtrigs/condtrigs.jsonDefines TIsHygieneStation, TIsHygieneStationInstalled, TIsHygieneStationUninstalled, TIsHygieneWater (matches either IsHygieneStation OR IsWater), TIsDirty, and TCanDoHygiene. These are the gates used in interaction CTTestUs/CTTestThem fields.
data/condowners/condowners.jsonDefines the installed (ItmHygieneStation) and loose (ItmHygieneStationLoose) condowner variants. Core fields: aStartingConds for initial state, aInteractions for available actions, mapPoints for use/sit point coordinates, strItemDef for the visual, aUpdateCommands for destruction wiring, strContainerCT/nContainerHeight/nContainerWidth for the internal water reservoir.
data/items/items.jsonDefines ItmHygieneStation and ItmHygieneStationLoose visual entries — sprite name, normal map, tile socket rules (aSocketAdds, aSocketForbids, aSocketReqs), scale. Referenced by condowner strItemDef.
data/interactions/interactions.jsonThe full use-interaction state machine: SeekHygieneWater (opener), SeekHygieneHygieneStation (navigate to station), ACTSeekHygieneWater (consume water path), ACTSeekHygieneAllowHygieneStation (sit and cleanse), ACTSeekHygieneAllowHygieneStationCleanse (consume water, apply conditions), ACTSeekHygieneAllowHygieneStationDone (finish), deny stubs.
data/loot/loot.jsonDefines ACTHygieneStationDmg (destroy delegate, strType: interaction), ItmHygieneStationSalvageContents (loot-on-salvage), ItmHygieneStationStationContents (water contents range), ItmHygieneStationNew (spawn contents, bNested: true, bSuppress: true).
data/loot/loot_components.jsonDefines ItmHygieneStationComponents (damaged-salvage parts) and ItmHygieneStationDismantle (full-dismantle parts yield).
data/loot/Furnishings_Kiosk.jsonAdds the Hygiene Station to whatever furniture purchase loot table makes it available to buy in-station.
data/installables/installables.jsonDefines HygieneStationInstall and HygieneStationUninstall — tool requirements (Mortorq), progress stats, condtrig gates, input/output condowners.
data/installables/installables_dismantle.jsonDefines the dismantle action (salvage-recovery path, different from uninstall).
data/installables/installables_undamage.jsonDefines the repair-in-place action when the station is damaged but not destroyed.
mod_info.jsonLoader identification.

What the explorer needs to show for this story to succeed