From 4499672284ba2850b9822d28479101d389f7c834 Mon Sep 17 00:00:00 2001 From: flan Date: Thu, 16 Jul 2026 03:13:22 +0000 Subject: [PATCH] Publish Foul Play wiki (source private) --- Drinking-and-Addiction.md | 114 ++++++++++++++++ Fermentation.md | 126 +++++++++++++++++ Furniture-Vats.md | 109 +++++++++++++++ Home.md | 113 ++++++++++++++++ Mixing-and-Reactions.md | 109 +++++++++++++++ Substance-Catalogue.md | 108 +++++++++++++++ The-Piss-Nuke.md | 275 ++++++++++++++++++++++++++++++++++++++ Vessels-and-Substances.md | 142 ++++++++++++++++++++ 8 files changed, 1096 insertions(+) create mode 100644 Drinking-and-Addiction.md create mode 100644 Fermentation.md create mode 100644 Furniture-Vats.md create mode 100644 Home.md create mode 100644 Mixing-and-Reactions.md create mode 100644 Substance-Catalogue.md create mode 100644 The-Piss-Nuke.md create mode 100644 Vessels-and-Substances.md diff --git a/Drinking-and-Addiction.md b/Drinking-and-Addiction.md new file mode 100644 index 0000000..4f8448a --- /dev/null +++ b/Drinking-and-Addiction.md @@ -0,0 +1,114 @@ +# Drinking and Addiction + +A thrown vessel is only half of what a fluid can do. **Every vessel is also ingestible** — any fluid is +drinkable, with wildly different consequences. Hooch is a buzz, piss is an illness, chemfuel is a +poisoning, milk just feeds you, and liquid luciferium is a death sentence. For several substances the +*drink* is the real weapon and the throw is only humiliation until then. + +--- + +## Vessels are ingestible + +Every vessel carries an `ingestible` block: + +```xml + + Fluid + NeverForNutrition + 240 + Drink {0} + +``` + +`NeverForNutrition` is the important flag: a pawn will **not** wander over and swig their own piss +grenade to fill their belly. Drinking is something you **order** (right-click → *Drink*), or something a +prisoner does with smuggled contraband, or a trick you play by leaving something drinkable where a +desperate pawn will take it. What swallowing does is decided at drink time from the **runtime contents**, +not the def — a "piss jar" that actually holds hooch gets you drunk. + +--- + +## You swallow the whole blend + +`PostIngested` walks the vessel's blend and applies **each constituent's** drink effect, scaled by its +**share** (see **Vessels and Substances**). A cocktail lands every ingredient at once: + +For each substance at fraction *f*: + +| Effect | Rule | +|---|---| +| **Body hediff** | `AdjustSeverity(drinkHediff, drinkHediffSeverity × f)` | +| **Memory** | gain `drinkThought` — but **only if `f ≥ 0.2`** (a single drop is not worth remembering) | +| **Nutrition** | `food += nutrition × f`, clamped to the food bar | +| **Addiction** | rolled — see below | + +A drop of hooch in a jar of piss barely warms you; a jar that is mostly hooch gets you drunk *and* +sick, because you also swallowed the piss. Ratios decide the dose, in both directions. + +### What each drink does (full potency, full jar) + +| Drink | Effect | Notes | +|---|---|---| +| **milk** | +nutrition, no downside | the benign one — it just feeds you | +| **blood** | +nutrition, revulsion memory | food for a sanguophage, "drank something vile" for anyone else | +| **hooch / beer** | alcohol high (0.16) | a buzz that can, sometimes, become a habit | +| **wort** | alcohol high (0.05) | mild — it is unfermented beer | +| **fermented urine** | food poisoning (0.35) + revulsion | an illness and a memory you cannot rinse away | +| **vomit** | food poisoning (0.30) + revulsion | vile and easy to source | +| **chemfuel** | toxic buildup (0.20) + revulsion | a slow poisoning | +| **liquid luciferium** | luciferium high (0.30) + revulsion + near-certain addiction | catastrophic — see below | +| **water / earwax / toenails** | nothing (water) / a revulsion memory only | no body effect | + +--- + +## The addiction roll, scaled by disposition + +Every fluid *can* hook the drinker; the rarity is the point. The per-drink chance is: + +``` +chance = addictionRarity × fraction × Lerp(0.5, 4.0, disposition) +``` + +- **`addictionRarity`** is the substance's base hook chance (see **Substance Catalogue**). Hooch 0.03, + beer 0.025, wort 0.01, **luciferium 1.0**; most fluids 0 (they never hook anyone). +- **`fraction`** is the substance's share of what was drunk — a splash rolls at a splash's odds. +- **`disposition`** is the drinker's 0..1 propensity, and it swings the chance across an **8× range**: a + content pawn multiplies by 0.5, a despairing one by 4.0. **A despairing pawn addicts to what a content + one shrugs off** — the same merged propensity engine that decides who fills a vessel and who throws it. + +If the roll wins and the drinker is not already addicted, the substance's `addictionChemical` is applied +via its real vanilla `addictionHediff` — so a hooch/beer habit *is* a vanilla Alcohol addiction, and +vanilla runs it from there. + +### The odds in practice + +| Drink | Content pawn (disp ≈ 0) | Despairing pawn (disp ≈ 1) | +|---|---:|---:| +| Full jar of **hooch** (0.03) | ~1.5% | ~12% | +| Full jar of **beer** (0.025) | ~1.25% | ~10% | +| Full jar of **wort** (0.01) | ~0.5% | ~4% | +| Full jar of **liquid luciferium** (1.0) | ~50% | **always** (chance ≥ 1) | +| A 20% splash of **luciferium** in a cocktail | ~10% | ~80% | + +**Liquid luciferium is the extreme the model is built to express.** At rarity 1.0 the roll all but always +hooks a full jar, and even a minority share of it in a cocktail is a coin-flip-or-worse. Mapped to the +real Luciferium chemical, that becomes vanilla's permanent, lethal-to-stop dependency: slip a pawn a jar +and you have handed them a life sentence, which is exactly why it is the rarest, worst thing a vessel can +hold. + +--- + +## Playing with the drink axis + +- **Interrogation / persuasion:** a jar of hooch is a cheap way to buy a prisoner's mood — at a small, + disposition-scaled risk of creating an alcoholic you now have to manage. +- **Sabotage:** leave a jar of chemfuel or fermented urine where a raider or a wandering prisoner will + drink it. The poisoning and the food-poisoning land immediately; the memory sticks for days. +- **Cruelty made mechanical:** a jar of luciferium is the single nastiest thing you can do to a pawn + short of killing them — and unlike killing them, it keeps working. +- **Watch the merged disposition.** With **Institution: Contraband** installed, the disposition read is + the suite's full nature × nurture — so *how you treat a prisoner* directly changes how easily the + same drink hooks them. A mistreated, despairing captive is far more addictable than a well-kept one. + +--- +*Foul Play is part of the **Institution** suite — one install with a checkbox per layer (Core, Contraband, Policing, Corrections, Gangs, Ward) about what an institution does to the people inside it. It bridges to the Contraband layer when Institution is installed.* diff --git a/Fermentation.md b/Fermentation.md new file mode 100644 index 0000000..c9603f3 --- /dev/null +++ b/Fermentation.md @@ -0,0 +1,126 @@ +# Fermentation + +Fermenting is what makes a vessel worth having. Fresh urine is nearly sterile and nearly harmless — it +is *weeks* of bacteria breaking urea into ammonia that make it caustic, make it burn eyes, and make it a +disease vector. Pruno is fruit, bread and time. Hooch is sugar and time. In every case the prisoner's +real ingredient is the one thing a cell gives them in abundance — **time** — and the institution's +counter is to take it away by finding the jar. + +Fermentation is **prison chemistry, not a Piss Nuke quirk**, which is why it lives in the framework +(`CompFerment`) and not the flagship. Any substance flagged `ferments` gets it; in the shipped catalogue +that is **urine, hooch and wort**. + +--- + +## Potency: age gives it, and age takes it away + +`CompFerment` tracks one hidden number — **age**, in ticks — and turns it into **potency** (0..1), the +value every downstream system reads to know how strong the batch is. The defaults on the Piss Nuke +family: + +| Property | Default | In days | Meaning | +|---|---:|---:|---| +| `freshPotency` | 0.30 | — | strength of a vessel sealed this instant | +| `ripeTicks` | 900,000 | **15** | ticks to climb from fresh to full | +| `burstAfterTicks` | 1,500,000 | **25** | past this, pressure has built too long → *overdue* | +| `burstMtbDays` | 6 | — | mean days between ruptures once overdue | +| `spoilTicks` | 0 → `ripeTicks×4` | **60** | when it starts turning to vinegar (0 defaults to long after ripe) | +| *(spoil end)* | `spoilStart + ripeTicks` | **75** | fully spoiled — inert sludge | + +Potency is a three-phase curve: + +``` +age ≤ ripe (15d) → Lerp(0.30, 1.0, age/ripe) ripening +ripe < age ≤ 60d → 1.0 ripe and holding +60d < age ≤ 75d → Lerp(1.0, 0.1, t) going off (t across the spoil window) +``` + +So a batch climbs from 30% to full over its first ~15 days, plateaus at full strength for weeks, then — +if it survives that long — **decays** back down to a floor of 0.1 as it turns to vinegar and rot. A +vessel reads `spoiled` (inert, not worth throwing or drinking) once age passes the spoil end. + +> **Why a piss carboy never spoils.** It goes *overdue* at 25 days and then ruptures on an MTB of 6 days +> — so it almost always lets go long before the 60-day spoil window opens. Spoiling is the fate of the +> *stable* ferments (a jar of hooch left in a cold corner and forgotten), not the pressurised ones. + +--- + +## Temperature and seal drive the rate + +Age does **not** accrue one tick per tick. It accrues at a temperature- and seal-scaled rate, exactly +like food rot — cold and a sealed jar are the difference between a season and a fortnight. + +``` +tempFactor = (temp ≤ 0°C) ? 0.05 : Clamp(temp / 20, 0.1, 2.0) +rate = tempFactor × (sealed ? 1.0 : 0.7) +``` + +| Condition | Rate | 15-day ripen becomes | +|---|---:|---| +| Freezer (≤ 0 °C) | 0.05 | ~300 days — nearly halted | +| Cold cell (10 °C) | 0.50 | ~30 days | +| Room temperature (20 °C) | 1.00 | ~15 days (the baseline) | +| Hot cell (≥ 40 °C) | 2.00 (capped) | ~7.5 days — a hot cell races it | +| Open vessel (×0.7) | — | slower: an open bucket breathes and loses to the air | + +Two levers for the player fall straight out of this: **a freezer is a stasis vault** for confiscated +contraband (age it nowhere while you decide what to do), and **a warden who keeps cells cold slows every +batch in the block.** An open bucket ferments at 70% the rate of a sealed one, on top of any temperature +effect — one more reason the open vessels are the weak siblings. + +--- + +## Dilution: topping up keeps a batch young + +Fresh liquid poured into a fermenting vessel **pulls its average age down**. When the volume grows, age +is scaled by the ratio of old volume to new: + +``` +age ← age × (oldVolume / newVolume) +``` + +Pour an equal measure of fresh urine into a fully-aged half-jar and its effective age (and potency) +halves. The design consequence is sharp: + +- **A jar filled once and hidden** ages undisturbed to full potency — the dangerous one. +- **A shared vat everyone keeps using** never gets old: every top-up resets it younger, so a + communal bucket stays a weak, watery batch no matter how long it has existed. + +Which is realistic and which is *balance*: the batch you should fear is the one someone filled and left +alone, not the one the whole block keeps dipping into. + +--- + +## Pressure: a sealed vessel ruptures on its own + +A sealed vessel of fermenting anything builds pressure. Once it is **overdue** (age ≥ `burstAfterTicks`, +25 days by default), each rare tick rolls `MTBEventOccurs` against `burstMtbDays` (6). When it fires, the +vessel: + +1. announces itself with a negative-event message, +2. is destroyed **first** (so it cannot be caught in its own blast and fire twice), and +3. hands off to its **burst worker** — the framework owns the pressure; *what comes out* is the owning + mod's business. A plain vessel just breaks and is gone; the Piss Nuke's carboy runs a **caustic + splash** at the vessel's current potency (see **The Piss Nuke**). + +The lesson for a stockpile manager: **a sealed carboy is a bomb on a timer even if nobody throws it.** +Keep confiscated ones cold, thrown away, or drained — a shelf of aging piss nukes will eventually let go +in your warehouse. + +The inspect pane shows the live state: `Fermentation: NN%`, plus `Overdue — building pressure` or +`Spoiled — turned to vinegar` as it reaches those phases. + +--- + +## Fermentation and identity + +The label reads the ferment state directly, and this is the mechanical root of the mod's central rule. +A fermenting vessel appends its progress (`piss nuke, fermenting 42%`); a spoiled one says so; and only a +vessel at **≥ 95% potency**, undiluted, and pure gets to wear its plain, full-strength name. + +> **A "piss nuke" is only 100%-fermented, undiluted, pure urine in a carboy.** A fresh one, a +> half-fermented one, a diluted one, a spoiled one, or a cocktail is *not* — and the label refuses to +> pretend it is. See **The Piss Nuke** for what that identity buys you. + +--- +*Foul Play is part of the **Institution** suite — one install with a checkbox per layer (Core, Contraband, Policing, Corrections, Gangs, Ward) about what an institution does to the people inside it. It bridges to the Contraband layer when Institution is installed.* diff --git a/Furniture-Vats.md b/Furniture-Vats.md new file mode 100644 index 0000000..1fd36a9 --- /dev/null +++ b/Furniture-Vats.md @@ -0,0 +1,109 @@ +# Furniture Vats + +A carryable vessel holds half a litre to a few litres. A cell, a brewery, or a bathhouse holds *bulk* — +and the bulk lives in furniture. Foul Play lets any liquid-holding fixture act as a large, fixed, +**blended vat** you cannot pick up or tip over: a place to ferment a batch too big for a jar, and a well +to dip jars out of. It is the same weighted-blend model `CompVessel` uses for carryables, applied to +buildings. + +--- + +## What counts as a vat (a capability, not a mod list) + +A building has no `CompVessel`, so its contents live in a map component keyed by the building. Foul Play +recognises a liquid-holding fixture the same way `CompVessel` recognises a container — by capability, so +the feature lights up with any hygiene or brewing mod and depends on none of them. `FermentSite` +counts a fixture as a vat if **any** of these hold: + +1. It is vanilla's **`FermentingBarrel`** (the canonical case). +2. Its `thingClass` is a **`Building_Storage`** — vanilla shelves, LWM/Deep Storage drawers, modded + crates. A drawer has sides and seals well enough for prison chemistry. +3. Its defName or label contains a **liquid-container word**: + + > toilet · latrine · outhouse · urinal · privy · bidet · barrel · keg · cask · vat · still · carboy · + > fermenter · tub · bath · sink · basin · trough · cistern · tank · bucket · drawer · crate · chest · + > locker · cabinet · cupboard · box · container + +With no such furniture anywhere, hooch simply **cannot** be brewed in bulk — which is the correct answer, +not a crash. A bare cell with nothing that holds liquid gives a prisoner nowhere to run a batch. + +Each vat holds a full blend, up to **30,000 ml (30 L)** — well beyond any carryable, so a cell can keep a +bulk batch of fermenting pruno and draw jars off it for a long time. + +--- + +## The two moves: pour in, dip out + +A pawn does exactly two things with a vat, and they are **not** symmetric — because you cannot tip a +bolted-down fixture the way you tip a jar. + +| Move | Direction | Capped by | The only way to… | +|---|---|---|---| +| **Pour in** | carryable → vat | `min(amount, carryable.TotalVolume, vat.headroom)` | empty a jar into the vat | +| **Dip** | vat → carryable | `min(amount, vat.volume, carryable.headroom)` | get liquid **out** of a fixture | + +**Dip is the whole reason the vat is usable at all.** A fixed drawer cannot be tipped, so the only way +liquid leaves it is a pawn dipping a carryable in and lifting a jar's worth out. Pour-in and dip together +let a cell run a bulk vat and decant it: keep 20 L of pruno fermenting in a crate, and dip a Piss Jar's +worth off it whenever you want to throw one. + +Both directions transfer **in the vat's / carryable's current ratios**, and both **resolve reactions** on +arrival: pour water onto a vat of hooch and it douses (see **Mixing and Reactions**); dip from a mixed vat +and your jar reacts too. When a vat is dipped dry it is forgotten entirely. + +### The float-menu UI + +Carry a vessel and right-click a fixture: you are offered **"Pour X into Y"** and, for a fixture, +**"Dip X from Y."** Right-click another vessel on the ground and you get **"Pour X into Y"** only (you +dip from fixtures, not from loose jars). The job walks to the target (`Touch`), works for 120 ticks with +a progress bar, then does the transfer. + +### Amount control + +The transfer functions take an explicit **amount**, so the quantity is the pawn's choice in both +directions — any ratio the physics allows: dip a splash of one thing into a jar of another to mix, or +draw exactly a jar's worth off a bulk vat. The current ordered-job UI uses the two natural extremes — +**pour empties the carried vessel**, **dip fills it to the brim** — while the underlying API supports any +partial measure for finer mixing. + +--- + +## Any pawn fills a vessel — openly + +Filling is Foul Play's business, not the prison's. A disposed **free** pawn — a colonist, a visitor — +will fill a jar from their own body, openly, and keep it. **Disposition decides who bothers, not +imprisonment**, which is the suite's thesis at the mechanics level. Held pawns are excluded here: they +*conceal* what they make (the Contraband route), so the prison lens owns them. + +The autonomous fill is **poll-based** (no Harmony) and deliberately rare: + +| Gate | Value | Effect | +|---|---|---| +| Check interval | every 2,500 ticks (~1 in-game hour) | when the poll runs | +| Eligibility | free, awake, up, humanlike, has an inventory | held/downed/animal pawns skip | +| Disposition gate | **≥ 0.5** | only strongly foul pawns bother at all | +| Body cooldown | shared supply component | their body must have restocked | +| Trigger | `MTB = 8 × (1.2 − disposition)` days | fouler = a shorter fuse, but still now-and-then | + +The jar they make is theirs; whether they ever *throw* it is the spree system's affair (see **The Piss +Nuke**). + +--- + +## The autonomous cocktail: the foulest mix + +An ordinary disposed pawn fills a plain jar of urine. The **foulest do not stop there** — above a +disposition of **0.7**, they **mix**, pouring a second vile substance in to make a cocktail: + +``` +SetContents(urine, capacity × 0.5) // half a jar of piss… +AddContent(feces, capacity) // …topped up with filth → a 50/50 piss-and-filth cocktail +``` + +(The second substance is feces if the pawn has any.) Note the **headroom rule** at work: the pawn +sets the jar to half-full of one substance *first*, then tops it up, so the result is a controlled 50/50 +blend rather than an overflow that spills the excess (see **Mixing and Reactions**). Only the worst +bother — which is exactly why a cocktail jar, when you find one, tells you something about who made it. + +--- +*Foul Play is part of the **Institution** suite — one install with a checkbox per layer (Core, Contraband, Policing, Corrections, Gangs, Ward) about what an institution does to the people inside it. It bridges to the Contraband layer when Institution is installed.* diff --git a/Home.md b/Home.md new file mode 100644 index 0000000..df700fc --- /dev/null +++ b/Home.md @@ -0,0 +1,113 @@ +# Foul Play + +**Fill a container with something off a body, and throw it.** + +Foul Play is a **liquid framework for RimWorld 1.6** — Noita's flasks, rebuilt in a colony sim. +Any container becomes a carryable vessel; any fluid becomes a substance you can pour, mix, ferment, +throw, or drink. What comes out the far end — a firebomb, a plague grenade, a caustic cloud, a jar of +humiliation, or an accidental cocktail that reacted with itself in transit — is decided entirely by +**what is in the vessel right now**, not by what item the def said it was. + +The base game gives you neither half. RimWorld has **no carryable containers at all** — every barrel +and pot is a *building* — and no way to weaponise the filth a body produces. Foul Play adds both, and +ships them as a **framework** rather than a fixed list of items. Its flagship consumer, **Piss Nuke**, +is the proof that the framework works: a whole weapon family built on top with almost no code of its own. + +--- + +## The two ideas everything derives from + +Foul Play is built on exactly two data axes, kept deliberately separate: + +| Axis | What it is | What it decides | +|---|---|---| +| **Vessel** (`CompVessel`) | a container — two numbers: **volume** and whether it is **sealed** | *delivery*: fill time, throw range, spill in transit, blast radius, splash density | +| **Substance** (`SubstanceDef`) | a fluid — pure data: `mlPerDay`, harm, disease, drink effect, addiction | *payload*: what it does when it lands, and what it does when you drink it | + +A **filled vessel is a vessel-of-substance**: a Piss Jar is a *jar* (delivery) *of urine* (payload). +Swap the substance and the same jar is a firebomb; swap the container and the same urine is a carboy- +sized area weapon. Neither axis knows anything about the other, which is what makes "works with every +container and every fluid" honest — there is no per-item special-casing to get wrong. + +The design law that makes this a *system* and not a novelty list: **harm inverts as volume falls.** A +body makes ~1.75 L of urine a day and a smear of earwax a year. The things a body makes least of do no +damage at all — so what they cost is **time**, and what they deliver is **humiliation**. A jar of +toenail clippings is a decade of sentence made physical, and possessing one tells you exactly how long +its owner has been caged. + +--- + +## The flagship: the Piss Nuke + +Foul Play ships **no weapons**. Piss Nuke is the flagship *consumer* — a four-vessel family of fermented +urine that exists only as data on top of the framework: + +| Vessel | Volume | Sealed | Character | +|---|---|---|---| +| Piss Jar | 0.5 L | yes | fills in hours, throws far, palms easily, tight splash | +| Piss Bottle | 0.75 L | yes | ~half a day to fill, still throws clean | +| Piss Bucket | 8 L | **open** | days to fill, throws short, **sloshes over the carrier**, wide and thin | +| **Piss Nuke** | 5 L | yes | the flagship carboy — wide *and* dense | + +Fermented urine is a **non-lethal disease weapon by design**: the splash barely blisters skin, but the +ammoniac infection it carries (piss rot) leaves the afflicted vomiting, half-blind and too shaky to +hold a rifle — the surest way to bring a raider home *breathing*. And an identity emerges only from +runtime state: **a carboy is a "piss nuke" only when it holds 100%-fermented, undiluted, pure urine.** +See **The Piss Nuke**. + +--- + +## Wiki index + +| Page | What it covers | +|---|---| +| **[Vessels and Substances](Vessels-and-Substances.md)** | `CompVessel` as a weighted **blend**, Capacity / Headroom / Fraction, the dominant substance, and how *every* consequence reads runtime contents and scales by share | +| **[Substance Catalogue](Substance-Catalogue.md)** | the full table of all 14 shipped substances — harm, disease, drink effect, addiction, fill rate | +| **[Mixing and Reactions](Mixing-and-Reactions.md)** | pouring substances together, the water-vs-incendiary 1:1 cancel, and the "headroom to receive" rule | +| **[Fermentation](Fermentation.md)** | temperature/seal-driven aging, dilution on top-up, spoiling past ripe, pressure ruptures | +| **[Drinking and Addiction](Drinking-and-Addiction.md)** | vessels are ingestible; per-fluid consequences; the addiction roll scaled by disposition | +| **[Furniture Vats](Furniture-Vats.md)** | sealed furniture as blended vats, dip vs pour physics, any-pawn filling, the autonomous cocktail | +| **[The Piss Nuke](The-Piss-Nuke.md)** | the flagship: what makes a carboy a nuke, throwing and the spree, the disposition-seeded thrower | + +--- + +## Foul Play and the Institution suite + +Foul Play plugs into the **Institution** suite — one install with a checkbox per layer (all on by +default) about what an institution does to the people inside it. The layers interlock around one thesis: + +> **Every pawn has a criminal propensity on a spectrum — nature (traits) × nurture (circumstance, +> mood, treatment) — and the colony can police it.** + +| Layer | What it is | +|---|---| +| **Core** | the propensity engine (nature × nurture), the criminal record, the treatment engine — the engine every layer agrees on | +| **Contraband** | prisoners conceal what they walked in with, whittle shivs from the cell, dig tunnels; wardens search the likeliest first, and a bent one looks away | +| **Policing** | your own colonists offend; witnesses and a constable name the culprit; a weighed arrest ends in a cell or a resisted breakout; order feeds back, riots when it collapses | +| **Corrections** | classification grades every prisoner by what they've done; discipline hardens or reforms; parole frees the reformed; regime gives recreation, yard time, and visits | +| **Gangs** | disposed prisoners band together and move contraband; rival gangs fight, inside the wire or out | +| **Ward** | commit a prisoner for psychiatric treatment instead of punishment — counselling reduces the disorder that broke them, on a recovery track toward discharge | +| **Foul Play** *(this mod)* | the vessel + substance + throw framework; the Piss Nuke flagship | + +**Foul Play has zero hard dependencies** and patches nothing (no Harmony). It stands alone as a +craft-and-throw gross-weapon mod. The one seam it exposes is `Disposition` — "how disposed is this pawn +to foul behaviour?", a single 0..1 number that decides who fills a vessel, who swigs the vile stuff, +and who a drink hooks. + +**When Institution's Contraband layer is enabled**, a small bridge assembly (`Bridge_Contraband/`, +loaded via `LoadFolders` *only* when Contraband is present) does three things: + +1. **Merges the propensity engines.** Foul Play repoints its `Disposition.Source` at the suite's shared + **nature × nurture** engine — surfaced by Contraband, owned by **Institution: Core** — so the two + mods never disagree about the same person. Without Contraband, Foul Play keeps its own light local + read (mood + a couple of traits). +2. **Registers the piss vessels as brewable contraband** — a prisoner can brew a carboy from their own + body in a bare cell, conceal it (a jar palms; a 5 L carboy does not), and be searched for it. +3. **Preserves a vessel's contents through concealment**, so a hidden *jar of hooch* comes back holding + hooch, not whatever the jar's def defaulted to. + +The throwing framework is never chained to the prison framework. See **The Piss Nuke** for the bridge +in full. + +--- +*Foul Play is part of the **Institution** suite — one install with a checkbox per layer (Core, Contraband, Policing, Corrections, Gangs, Ward) about what an institution does to the people inside it. It bridges to the Contraband layer when Institution is installed.* diff --git a/Mixing-and-Reactions.md b/Mixing-and-Reactions.md new file mode 100644 index 0000000..55518be --- /dev/null +++ b/Mixing-and-Reactions.md @@ -0,0 +1,109 @@ +# Mixing and Reactions + +This is the Noita layer. A vessel holds a **weighted blend**, and pouring one fluid into another does +not just stack them — some pairs **react**. Mixing is addition; reactions are chemistry on top of the +addition. Both resolve *in place, by volume*, so ratios decide the outcome. + +If you have not read it yet, **Vessels and Substances** covers the blend model (Capacity, Headroom, +Fraction) this page builds on. + +--- + +## Volumes add; the container decides the ceiling + +Pour a measure of a substance into a vessel and the amounts add: + +``` +250 ml urine + pour in 250 ml hooch → { urine: 250, hooch: 250 } (a 50/50 jar) +``` + +Two rules govern the add: + +1. **You cannot overfill.** Only up to the **headroom** is taken. Pour a full jar of hooch into a + half-full jar of piss and the jar ends up piss-and-hooch, filled to the brim and *no more* — the + excess never enters. A vessel with no headroom takes nothing at all until some is poured out. +2. **The blend re-balances, then reactions resolve.** Amounts add, shares shift, and *then* the reaction + pass runs on the new blend — so **what comes out may not be the sum of what went in.** + +Because every consequence scales by share (see **Vessels and Substances**), changing the ratio changes +the weapon. A jar that is mostly piss with a splash of hooch barely burns; tip the ratio the other way +and it is a firebomb. Nobody re-tags the item — the blend simply *is* the weapon now. + +--- + +## Pouring: the one action pawns take + +The only thing a pawn does with vessels is **pour between containers**. It moves liquid from a source +into a target, capped three ways at once: + +``` +moved = min( requested, source.TotalVolume, target.Headroom ) +``` + +Contents transfer **in their current ratios** — pour half of a 60/40 jar and the destination receives +60/40. The destination then reacts (a hooch jar poured into a water bucket is doused on arrival). The +UI (right-click a vessel-carrier onto another vessel or a liquid fixture) offers **"Pour X into Y"**; a +pour job walks to the target, works for 120 ticks with a progress bar, then empties the carried vessel. + +> **The tipping rule.** You cannot pour *out of* a bolted-down furniture vat — you cannot tip a fixed +> drawer the way you tip a jar. To take liquid *out* of a fixture you **dip** a carryable into it instead. +> See **Furniture Vats**. + +--- + +## The reaction: water douses fire, 1:1 + +The first and most intuitive reaction — and the anchor for the whole reaction layer — is **water versus +an incendiary.** An "incendiary" is any substance whose splash burns (its `damageDef` points at vanilla +`Flame`): in the shipped catalogue that is **hooch** and **chemfuel**. + +When both water and one or more incendiaries share a vessel, they **cancel one another volume-for-volume +until one runs out**: + +``` +doused = min( water_ml, total_incendiary_ml ) +``` + +- Each incendiary is reduced by its share of `doused`; any that hits zero is removed. +- The water is *spent* putting it out — reduced by the same `doused`; if it hits zero it is removed too. +- Whichever runs out first, the other survives with the remainder. + +Ratios are everything: + +| Blend before | Result | +|---|---| +| 100 ml water + 4900 ml chemfuel (carboy) | ~100 ml chemfuel neutralised — barely a dent; still a firebomb | +| 4000 ml water + 500 ml hooch (bucket) | hooch **gone**; ~3500 ml plain water left; inert | +| 250 ml water + 250 ml hooch | both cancel out exactly; an empty-of-either, doused vessel | + +This is genuinely useful in play, not just flavour: + +- **Defuse a firebomb** by pouring water into it before it is thrown. +- **Sabotage** a captured or looted incendiary in storage. +- **Botch a mix**: an autonomous mixer or a careless pour that lands water on hooch quietly destroys the + weapon — the vessel still *reads* full, but its bite is gone. + +Reactions run **everywhere a blend can change**: on pour-in, on dip, and inside a furniture vat. The +resolver is a single local transform on the amount table, so new pairs (acid + base, oil feeding fire, +and so on) slot in beside `WaterDousesFire` without touching anything else. + +--- + +## The headroom rule, restated + +Every mixing interaction routes through the same gate: **a container needs headroom to receive.** + +| Situation | What happens | +|---|---| +| Pour into a full vessel | nothing moves — no headroom | +| Pour more than the target can hold | only the headroom's worth transfers; the rest stays behind | +| Pour more than the source holds | capped at what the source actually has | +| Dip a carryable into a fixture | capped by the fixture's contents *and* the carryable's headroom | + +The consequence for play: to build a *specific* cocktail you often have to **empty first, then mix**. The +autonomous mixers do exactly this — they set the vessel to half its capacity of one substance, *then* +top it up with a second, so the result is a controlled 50/50 rather than an overflow. (See **Furniture +Vats** for the autonomous cocktail.) + +--- +*Foul Play is part of the **Institution** suite — one install with a checkbox per layer (Core, Contraband, Policing, Corrections, Gangs, Ward) about what an institution does to the people inside it. It bridges to the Contraband layer when Institution is installed.* diff --git a/Substance-Catalogue.md b/Substance-Catalogue.md new file mode 100644 index 0000000..1d532fe --- /dev/null +++ b/Substance-Catalogue.md @@ -0,0 +1,108 @@ +# Substance Catalogue + +A **substance** (`SubstanceDef`) is pure data: what a fluid does when a vessel of it lands, and what it +does when someone drinks it. The framework ships the fluids below as neutral data — it attaches none of +them to a weapon itself (that is a *consumer's* job, like Piss Nuke). A vessel can hold any of them, and +any of them can be poured, mixed, fermented, thrown or drunk. + +The organising law is **harm inverts as volume falls** (`mlPerDay`): a body makes a lot of some of these +and almost none of others, and the ones it makes least of do no damage at all. When harm goes to zero, +**time** becomes the weapon — a jar of toenail clippings took years to fill, and that *is* the point. + +--- + +## The fields + +| Field | Meaning | +|---|---| +| `mlPerDay` | how much a body (or the world) produces per day — sets **fill time**; default 1750 | +| `damageDef` | the splash's damage type; null → framework's generic `FP_SubstanceSplash` (a soft bruise) | +| `causticDamage` | splash damage at full potency; **0 = it only humiliates** (no blast, just filth + a memory) | +| `disease` / `diseaseSeverity` | infection applied *in code* so headgear can block it (peak severity at a bare face) | +| `burnsEyes` | concentrated ammonia can blind — only a ripe, fermenting substance | +| `hitThought` | the "someone threw this at me" memory — humiliation is the universal payload | +| `filth` | mess left on the ground; null → generic foul mess | +| `ferments` | does it age (and get worse, and build pressure)? see **Fermentation** | +| `nutrition` | food value if drunk | +| `drinkHediff` / `…Severity` | what swallowing it does to the body | +| `drinkThought` | how they feel about having drunk it | +| `addictionRarity` | base per-drink chance to form a dependency (scaled by the drinker's disposition) | +| `addictionChemical` | the real chemical the dependency maps to (its `addictionHediff` is applied) | + +--- + +## The full catalogue (14 substances) + +Sorted by production rate. **Harm falls as you go down the bodily list; time-to-fill rises.** + +### Throw harm — what a splash does + +| Substance | `mlPerDay` | Flammable? | Caustic | Disease (severity) | Burns eyes | Ferments | Throw memory (mood) | +|---|---:|:---:|---:|---|:---:|:---:|---| +| **milk** (`FP_Milk`) | 11000 | no | 0 | — | no | no | doused in milk (−3) | +| **water** (`FP_Water`) | 2000 | no | 0 | — | no | no | *none* (barely worth remembering) | +| **fermented urine** (`PN_Urine`) | 1750 | no | 6 | piss rot (0.35) | **yes** | **yes** | doused in piss (−14) | +| **chemfuel** (`FP_Chemfuel`) | 800 | **yes** | 26 | — | no | no | firebombed (−10) | +| **hooch** (`FP_Hooch`) | 500 | **yes** | 16 | — | no | **yes** | firebombed (−10) | +| **beer** (`FP_Beer`) | 500 | no | 0 | — | no | no | degraded (−16) | +| **wort** (`FP_Wort`) | 500 | no | 0 | — | no | **yes** | pelted with filth (−12) | +| **vomit** (`FP_Vomit`) | 250 | no | 0 | gut rot (0.25) | no | no | pelted with filth (−12) | +| **feces** (`FP_Feces`) | 150 | no | 0 | gut rot (0.45) | no | no | pelted with filth (−12) | +| **blood** (`FP_Blood`) | 60 | no | 0 | — | no | no | drenched in blood (−14) | +| **liquid luciferium** (`FP_Luciferium`) | 50 | no | 0 | — | no | no | degraded (−16) | +| **earwax** (`FP_Earwax`) | 0.05 | no | 0 | — | no | no | degraded (−16) | +| **toenail clippings** (`FP_Toenails`) | 0.02 | no | 0 | — | no | no | degraded (−16) | + +### Drink payload — what swallowing it does + +Any fluid is drinkable, and for several substances the drink is the *real* weight — thrown, they merely +humiliate, but slipped to a pawn in a drink they land their full effect. See **Drinking and Addiction**. + +| Substance | Nutrition | Drink hediff (severity) | Drink memory | Addiction rarity → chemical | +|---|---:|---|---|---| +| **milk** | +0.05 | — | — | — | +| **blood** | +0.05 | — | drank something vile | — | +| **fermented urine** | 0 | food poisoning (0.35) | drank something vile | — | +| **vomit** | 0 | food poisoning (0.30) | drank something vile | — | +| **chemfuel** | 0 | toxic buildup (0.20) | drank something vile | — | +| **hooch** | 0 | alcohol high (0.16) | — | **0.03** → Alcohol | +| **beer** | 0 | alcohol high (0.16) | — | **0.025** → Alcohol | +| **wort** | 0 | alcohol high (0.05) | — | **0.01** → Alcohol | +| **liquid luciferium** | 0 | luciferium high (0.30) | drank something vile | **1.0** → Luciferium | +| water / earwax / toenails | 0 | — | — | — | + +--- + +## Reading the catalogue + +**The two flammables are the firebombs.** Chemfuel (26 caustic) and hooch (16) point their `damageDef` +at vanilla `Flame`, so their splash rides the framework's `GenExplosion` and **starts fires** with no +special-case code. Chemfuel is the industrial one — hotter and wider; a prisoner who reaches a fuel +stockpile is a serious problem. Hooch is the prison-brewed cousin, and it *ferments*: for hooch, age is +alcohol and alcohol is what burns, so it runs the harm axis the **other** way from the bodily fluids — +worse as it ages, not worse as volume falls. + +**The two disease vectors are feces and vomit** (both carry gut rot, feces at the higher dose) and +**fermented urine** (piss rot). All three are applied *in code*, filtered through headgear — a sealed +helmet is near-total protection. All three infections are **non-lethal by design**: a wing of sick, +wretched, capturable prisoners, not corpses. + +**The benign ones are the joke that makes the rest land.** Milk only annoys (−3, and no filth def exists +for it, so a splash leaves only a memory); a Kind pawn throwing milk is comedy. Water does *nothing* on +impact — it is the **anti-substance**, the key to the reaction layer: it douses fire and washes filth. +See **Mixing and Reactions**. + +**The pure-humiliation tier is the thesis in miniature.** Earwax (0.05) and toenail +clippings (0.02) do zero damage. A jarful of any of them is worthless as a weapon and priceless as a +statement: it is only fillable by someone with *years* of idle time, so possessing one advertises exactly +how long its owner has been inside. All three share the harshest throw memory in the mod (**degraded, +−16**) precisely because there is nothing else to them. + +**The drink specialists** carry almost nothing thrown but everything swallowed. Beer and wort are +smuggled/brewing alcohol; blood feeds a sanguophage and revolts everyone else. **Liquid luciferium is the +catastrophe**: thrown it is a monstrous waste, but drunk it applies vanilla's `LuciferiumHigh` and, at +`addictionRarity 1.0`, the roll all but always hooks — mapped to the real Luciferium chemical, so vanilla +then runs it as the permanent, lethal-to-stop dependency. Slip a pawn a jar and it is a life sentence. + +--- +*Foul Play is part of the **Institution** suite — one install with a checkbox per layer (Core, Contraband, Policing, Corrections, Gangs, Ward) about what an institution does to the people inside it. It bridges to the Contraband layer when Institution is installed.* diff --git a/The-Piss-Nuke.md b/The-Piss-Nuke.md new file mode 100644 index 0000000..33a57c3 --- /dev/null +++ b/The-Piss-Nuke.md @@ -0,0 +1,275 @@ +# The Piss Nuke + +The Piss Nuke is Foul Play's **flagship consumer** — a whole weapon family built on the framework with +almost no code of its own. Everything a piss nuke *is* comes from two data axes the framework already +provides: a **carboy** (a 5 L sealed vessel) holding **fermented urine** (a caustic, disease-carrying, +fermenting substance). The framework knows nothing about piss; the piss knows nothing about throwing. +That separation is the entire proof-of-concept. + +> *"A contemptible weapon. It is also the surest way to bring a raider home breathing."* + +--- + +## The vessel family + +Four containers of the same fermented urine. Everything that separates them falls out of the two vessel +dials — **volume** and **seal** (see **Vessels and Substances**): + +| Vessel | Volume | Sealed | Mass | Cooldown | Work | Cost | Character | +|---|---:|:---:|---:|---:|---:|---|---| +| **Piss Jar** | 500 ml | yes | 0.6 | 2.2 | 600 | 3 cloth | fills in ~7 h, throws far, palms easily, tight splash | +| **Piss Bottle** | 750 ml | yes | 0.9 | 2.6 | 900 | 5 cloth | ~10 h to fill, still throws clean | +| **Piss Bucket** | 8000 ml | **no** | 3.0 | 3.8 | 500 | 5 steel | days to fill, throws short, **sloshes over the carrier**, wide and thin | +| **Piss Nuke** | 5000 ml | yes | 2.2 | 3.2 | 3500 | 4 steel + 15 cloth | the flagship carboy — wide *and* dense | + +All four throw as the framework's one projectile (`FP_Proj_Substance`), with a base verb range of **10.9** +and a **1.8 s** warm-up. The blast footprint each produces is derived from its two numbers, not authored: + +| | Blast radius | Dose density | Filth | +|---|---:|---:|---:| +| Jar | ~2.1 | 1.0 | 2 | +| Bottle | ~2.4 | 1.0 | 2 | +| Bucket | ~7.1 | 0.55 (open) | 5 | +| Nuke | ~4.5 | 1.0 | 4 | + +The bucket lands widest but thinnest and throws shortest; the carboy is the only one that is **both wide +and dense** — which is why it, and not the bucket, is the flagship. + +--- + +## What makes a carboy a *nuke* + +A carboy is not automatically a piss nuke. Identity is **emergent from runtime state**, enforced by the +contents-aware label (see **Fermentation**): + +> **A "piss nuke" is only 100%-fermented (≥ 95% potency), undiluted, pure urine in a carboy.** + +Any of the following demotes it, and the label refuses to pretend otherwise: + +| State | Label | Why it is not a nuke | +|---|---|---| +| Fresh / mid-ferment | `piss nuke, fermenting 42%` | fresh urine is nearly sterile — potency is the weapon | +| Diluted (topped up) | lower potency | fresh liquid pulled the average age down | +| A cocktail | `piss nuke (urine 60%, feces 40%)` | it is a blend, and each part splashes at its own share | +| Spoiled (> ~75 days) | `piss nuke, spoiled` | it turned to inert vinegar | + +Full strength is worth waiting for because **the harm scales with potency at every step** — the caustic +damage, the infection dose, and the eye burn all read it live at the moment of impact. + +--- + +## Fermented urine, the substance + +Urine (`PN_Urine`) is the harm profile the flagship attaches to its carboys — pure data on top of the +framework: + +| Field | Value | Meaning | +|---|---|---| +| `mlPerDay` | 1750 | a jar fills in ~7 h, a carboy in ~3 days | +| `causticDamage` | 6 (via `PN_Caustic`) | the splash blisters skin — little more | +| `disease` / severity | piss rot / 0.35 | the real payload, applied in code, filtered by headgear | +| `burnsEyes` | true | concentrated ammonia can blind a bare face | +| `ferments` | true | fresh it is nearly harmless; weeks make it caustic | +| `drinkHediff` | food poisoning (0.35) | swallowing it is an illness and a memory | + +Fresh urine is nearly sterile. It is **weeks of bacteria turning urea into ammonia** that make it +caustic, make it burn eyes, and make it a disease vector — which is why potency, not volume, is what you +are cultivating. + +--- + +## Piss rot: non-lethal by design + +The disease is the whole point, and it is deliberately **not a killer**. `PN_PissRot` is a real +immunizable infection built like vanilla flu, with one departure: `lethalSeverity = -1`, so however high +severity climbs, **it cannot kill**, and no stage is life-threatening. + +| Stage | From severity | What it does | +|---|---:|---| +| **mild** | 0 | Moving/Manipulation/Sight −0.08, Breathing −0.04; occasional vomiting | +| **acute** | 0.35 | Moving/Manipulation/Sight −0.25, Eating −0.20, Consciousness −0.10, Breathing −0.12 | +| **wretched** | 0.70 | Moving/Manipulation −0.50, Sight −0.45, Eating −0.35, Breathing −0.22 — *the capture window* | + +Even at `wretched`, breathing is held short of lethal on purpose: drive breathing to zero and the pawn +dies, which would quietly destroy the entire point of the weapon. The afflicted vomit, shake, go +half-blind and cannot hold a rifle straight — **capturable, not killable.** + +The immunity race is what happens *afterward*: severity climbs fast but immunity outruns it (full +immunity in roughly **three days** for a healthy pawn), and tending flips severity from climbing to +falling. Two consequences worth knowing: + +- **Tending and care genuinely matter** — a treated colonist shrugs it off in a day or two; an untreated + raider in the mud stays wretched for the better part of three days. +- **Immunity persists** (fading over ~10 days), so **piss-nuking the same faction twice in one week works + noticeably less well.** That is emergent, and it is a feature. + +### Headgear is the counter + +The infection route is the face (eyes, nose, mouth), so the single most effective thing a colonist can do +about any of this is **put a helmet on.** The dose is applied in C# precisely so it can read what a pawn +is wearing — something `DamageDef.additionalHediffs` cannot do: + +| Worn on face | Protection | +|---|---:| +| Full-head covering (sealed helmet, gas mask) | **0.90** — near-total | +| Upper-head only (simple helmet) | 0.30 | +| Bare face | 0.00 | + +On top of headgear, the pawn's Toxic Resistance further cuts the dose. A sealed helmet plus a constitution +of iron can shrug off a direct hit entirely. + +### The eye burn + +Only a *ripe, fermenting* substance burns corneas — a property of long fermentation. It requires potency +**≥ 0.75** and near-bare-face exposure (**≥ 0.9**); the chance scales with ripeness above that threshold +(`0.22 × (potency − 0.75) / 0.25`), and a hit takes 5–11 burn damage to an eye. A fresh carboy never does +it; a fully-ripe one thrown at an unhelmeted raider sometimes blinds. + +--- + +## Throwing + +When a pawn on a spree throws a carboy (`JobDriver_ThrowPissNuke`), the throw is deliberately *not* the +weapon's normal verb — the projectile is launched directly so the pawn never has to drop what they were +holding, and the carboy is **consumed** by the throw (it shatters, and having to brew another paces the +spree). The throw: + +1. **Winds up** for 90 ticks. +2. **Reads potency** off the carboy's ferment comp — a vessel filled this morning is a bad smell; one + sitting since last season is a weapon. +3. **Hands the whole blend to the projectile** with per-substance shares, so a thrown cocktail lands every + constituent in its ratios (see **Vessels and Substances**). +4. **Scatters**: a psychotic throw is wild — it lands within ~2.6 cells of the aim point. +5. **Splashes back on the thrower**: you cannot heave an open-necked vessel of this without wearing some + of it. Self-splash chance is **0.18 for a sealed carboy, 0.54 for an open bucket** (×3), from whatever + substance they mostly slopped on themselves. + +On impact the projectile runs the framework splash: the caustic blast (`6 × potency × doseDensity`), the +filth footprint, and the per-pawn infection dose with falloff toward the edge of the radius. + +--- + +## Who throws it: the seeded disposition model + +The mistake worth not making is treating imprisonment as the *cause*. It is not. Prisons hold thousands +and produce, every so often, **one** person notorious for this — notorious precisely because it is rare. +So the model is **disposition × circumstance, multiplied**, never a pile of added percentages +(`PissNukeSpreeUtility.WouldFoulPeople`): + +- **Disposition** is a rare property of the person: `0.05` for the disinhibited (psychopath, bloodlust, + abrasive, cannibal), `0.004` for everyone else — effectively nobody. +- **Circumstance** decides whether a disposed person acts: tiers, not stacking bonuses. + +| Circumstance | ×factor | +|---|---:| +| Free, well | 1.0 | +| Free, at the mood floor (< 0.20) | 3.0 | +| Prisoner, well kept | 2.5 | +| Prisoner, badly kept (mood < 0.35) | 6.0 | +| Prisoner, at the mood floor | 12.0 | + +The resulting odds (capped at **60%**): + +| Pawn | Chance | +|---|---:| +| Ordinary colonist | 0.4% | +| Ordinary colonist at the mood floor | 1.2% | +| Ordinary prisoner, well kept | 1.0% | +| Ordinary prisoner, badly kept | 2.4% | +| Ordinary prisoner, at the mood floor | 4.8% | +| Psychopath colonist | 5.0% | +| Psychopath prisoner, well kept | 12.5% | +| Psychopath prisoner, badly kept | 30.0% | +| Psychopath prisoner, at the mood floor | **60.0%** (capped) | + +It therefore takes **both a rare individual and a badly run prison**. A well-run prison full of ordinary +captives essentially never sees this, which is exactly right. + +**The roll is seeded on the pawn** (`thingIDNumber ^ 0x5E17`), so *"would they?"* is a fixed fact about +that person — the same pawn always answers the same way, which is what makes them a character the whole +block tells stories about rather than a dice roll re-thrown every tick. + +### How the spree runs + +The behaviour hangs off the existing psychotic/confused mental states via a think-tree patch — no new +mental break enters the roll table. A deranged pawn who *would* foul people: + +1. **already carrying a carboy** → find any target in line of sight within ~22 cells and throw; +2. else **finds one lying about** within ~40 cells → fetch it (saves brewing); +3. else **brews one** — *if their body has anything left to give.* + +That last limit is the **supply cooldown** (`MapComponent_PissNukeSupply`). Without it a spree brews and +throws on a ~4,500-tick cycle, which over 70k–90k ticks of psychotic wandering is sixteen to twenty +carboys — several dozen litres out of one person, a physiological impossibility. The body restocks on a +**25,000–35,000 tick** (~half-day) cooldown, so a spree yields two or three carboys, not twenty. + +Note what the cooldown deliberately does **not** limit: throwing carboys **someone else made**. A pawn who +reaches a stockpile can empty it as fast as they can throw — a very good reason **not to keep the piss-nuke +stockpile near the people most likely to lose their minds.** + +--- + +## Aftermath: residue and stink + +The mess a carboy leaves is not just cosmetic. + +**The residue is a fomite.** `MapComponent_PissResidue` spreads piss rot the way a contaminated person +really spreads it — by carrying it on themselves and leaving it on what they touch, **not** on the wind. +A pawn who wades through fouled ground is `contaminated` for ~half a day; while contaminated they have a +small chance each cycle to **track fresh filth** into wherever they walk (so the dining room becomes a +problem) and to **infect anyone adjacent** by direct contact. Nobody catches it from across the room — +but a fouled corridor walked into a mess hall is how these things move through a crowded building. Ground +residue reaches feet and hands, not eyes (kept below the eye-burn threshold on purpose). + +**It reeks.** `ThoughtWorker_PissStink` gives a mood penalty for standing in or near fouled ground — +mild near a tile or two, and a distinct *"it's all I can smell"* penalty near six or more tiles of it +within a 4-cell radius. Cleaning up after a piss-nuke fight is not optional busywork; it is disease +control and mood management at once. + +--- + +## Pressure: the carboy that goes off by itself + +A sealed carboy of fermenting urine builds pressure. Once **overdue** (25 days) it rolls to rupture on an +MTB of 6 days, and when it does, `BurstWorker_Caustic` fires the same caustic splash at the carboy's +current potency — with nobody throwing it. A shelf of aging piss nukes is a rack of timed bombs. Keep +confiscated ones **cold** (a freezer nearly halts fermentation), drained, or destroyed. See +**Fermentation**. + +--- + +## With Institution: Contraband — the prison layer + +Foul Play stands alone as a craft-and-throw gross-weapon mod and patches nothing. When **Institution: +Contraband** is installed, a small bridge assembly (`Bridge_Contraband/`, loaded via `LoadFolders` *only* +when Contraband is present) turns the piss nuke into prison contraband — a prisoner brews a carboy from +their **own body** in a bare cell, conceals it, and gets searched for it. The bridge does three things: + +1. **Registers the vessels as brewable contraband**, with concealability tracking size — a jar palms; a + five-litre carboy does not: + + | Vessel | Concealability | Hides in | + |---|---:|---| + | Piss Jar | 0.70 | on body, in cell | + | Piss Bottle | 0.55 | on body, in cell | + | Piss Bucket | 0.20 | in cell only | + | Piss Nuke | 0.35 | in cell only | + + Whether a prisoner *would* brew one uses the same `WouldFoulPeople` model above — a rare disposition + **and** a badly-run prison, multiplied. How you treat them decides how much of this you get. + +2. **Merges the propensity engines.** The bridge repoints Foul Play's `Disposition.Source` at the suite's + full **nature × nurture** engine (surfaced by Contraband, owned by **Institution: Core**), flattened to + the 0..1 Foul Play wants: `Clamp01(nature × Clamp(nurture, 0.4, 3) × 0.6)`. From then on, *who fills a + vessel* and *who a drink hooks* read the same disposition Contraband uses for crime and policing — the + two mods never disagree about the same person. Without Contraband, Foul Play keeps its own local read. + +3. **Preserves contents through concealment.** Contraband stores a blind content tag; the bridge gives it + meaning by wiring it to `CompVessel.SerializeContents` / `DeserializeContents`, so a hidden *jar of + hooch* comes back holding hooch, not whatever the jar's def defaulted to. + +The throwing framework is never chained to the prison framework — the spree brews and throws on its own, +and concealment is a bonus the prison layer adds. + +--- +*Foul Play is part of the **Institution** suite — one install with a checkbox per layer (Core, Contraband, Policing, Corrections, Gangs, Ward) about what an institution does to the people inside it. It bridges to the Contraband layer when Institution is installed.* diff --git a/Vessels-and-Substances.md b/Vessels-and-Substances.md new file mode 100644 index 0000000..284aeca --- /dev/null +++ b/Vessels-and-Substances.md @@ -0,0 +1,142 @@ +# Vessels and Substances + +Foul Play splits every throwable into two axes that never touch: + +- **The vessel** (`CompVessel`) is the *container* — how it is delivered. +- **The substance** (`SubstanceDef`) is the *fluid* — what it does when it lands. + +A "piss jar" is the intersection: a jar (vessel) of urine (substance). This page is about how the two +combine at runtime, and the single most important fact about the whole framework: **a vessel holds a +weighted blend, and every consequence reads that blend, not the def.** + +--- + +## A vessel is two numbers + +RimWorld has no carryable containers of its own, so Foul Play ships a capability instead of a family. +Any `ThingDef` becomes a throwable vessel just by carrying `CompProperties_Vessel`, which declares two +things and lets everything else derive: + +```xml +
  • + 500 + true + PN_Urine +
  • +``` + +Everything physical about the weapon is a function of those two numbers, derived once in `VesselProfile` +so the derivation is consistent across our vessels and any modded one. The reference point is a **5 L +carboy** (`RefVolumeMl = 5000`); `VolumeFraction = Clamp(volumeMl / 5000, 0.05, 4)`. + +| Derived property | Formula | Sealed → | Open → | Consumed by | +|---|---|---|---|---| +| **Blast radius** | `4.5 × VolumeFraction^(1/3)` | ×1.0 | ×1.35 (slops wider) | the splash | +| **Dose density** | constant | 1.0 | 0.55 (lost some in transit) | splash damage + infection dose | +| **Filth count** | `max(2, round(4 × √VolumeFraction))` | — | — | how much mess it leaves | +| **Spill per cell** | constant | 0.0 | 0.06 | *(design model; see below)* | +| **Throw range factor** | `Lerp(1.3, 0.6, InverseLerp(0.1, 1.6, VF))` | ×1.0 | ×0.65 | *(design model; see below)* | +| **Fill ticks** | `round((volumeMl / mlPerDay) × 60000)` | — | — | how long a body takes to fill it | + +Blast is a **cube-root** of volume because a splash is a volume spreading over an *area* — doubling the +litres does not double the radius. A sealed vessel bursts concentrated; an open one has already lost +liquid down the carrier's leg and spreads the rest thin. + +> **Honesty note.** Blast radius, dose density and filth count are read live by the splash. Spill-per-cell +> and throw-range-factor are part of the same single-source derivation model but are not yet wired into +> a live per-cell spill or a range multiplier; the open vessel's "wears it on the way" character is +> currently expressed at throw time as a **tripled self-splash chance** (0.18 → 0.54). The model is +> the design contract; the splash is where it currently bites. + +### The four starter vessels, derived + +Concrete numbers for the Piss Nuke family, all falling straight out of the two dials: + +| Vessel | Vol | Sealed | Blast radius | Dose density | Filth | Fill time (urine, 1750 ml/day) | +|---|---:|:---:|---:|---:|---:|---| +| Piss Jar | 500 ml | yes | ~2.1 | 1.0 | 2 | ~7 in-game hours | +| Piss Bottle | 750 ml | yes | ~2.4 | 1.0 | 2 | ~10 in-game hours | +| Piss Bucket | 8000 ml | **no** | ~7.1 | 0.55 | 5 | ~4.6 days | +| Piss Nuke | 5000 ml | yes | ~4.5 | 1.0 | 4 | ~2.9 days | + +The bucket holds sixteen times the jar but throws *shorter*, lands *wider*, and arrives *thinner* — the +whole personality of an open container, none of it hand-authored. + +--- + +## A vessel holds a *blend*, not a substance + +Here is the part that turns four items into a system. `CompVessel` does not store "the substance." It +stores a **weighted blend** — a dictionary of *how much of each substance is present, by volume in ml*: + +``` +amounts = { FP_Urine: 250, FP_Feces: 250 } // a half-and-half cocktail in a 500 ml jar +``` + +A single substance is just a blend of one. A never-touched vessel reports `null` and behaves as a full +vessel of its def's substance until you pour something in — at which point the amounts materialise and +can be mutated. + +### The four measurements + +Every downstream system asks the blend the same handful of questions: + +| Property | Meaning | +|---|---| +| **`Capacity`** | how much it holds full, in ml (= `volumeMl`) | +| **`TotalVolume`** | how much liquid is in it right now (a never-touched vessel = full of its def) | +| **`Headroom`** | `Capacity − TotalVolume` — room left to pour *more* in | +| **`FractionOf(sub)`** | that substance's **share** of the blend, `amount / total`, in 0..1 | + +`IsFull` is `Headroom ≤ 0.001`. `Headroom` is the gatekeeper of mixing: **you cannot pour into a vessel +with no headroom.** (See **Mixing and Reactions**.) + +### The dominant substance + +`Substance` (singular) returns the biggest share — the substance a mostly-piss cocktail "is." It is used +for the label, for self-splash on a throw ("whatever they mostly slopped on themselves"), and anywhere a +single answer is needed. Setting it *replaces* the whole blend with a full vessel of that one substance. + +--- + +## Everything scales by share + +This is the payoff, and it is uniform across the entire mod. No consequence looks at the def's declared +substance; each looks at the runtime blend and **scales by each substance's fraction.** A drop of hooch +in a jar of piss barely warms you; a jar that is mostly hooch is a firebomb. Ratios decide the dose. + +| System | How the share is applied | +|---|---| +| **Throwing / splash** | the projectile carries the whole blend; each constituent lands its own splash at `potency × fraction`. A thrown cocktail applies *every* substance in its ratios. | +| **Drinking** | `PostIngested` walks the blend and applies each substance's drink effect (hediff, thought, nutrition, addiction) scaled by its fraction. A memory below a **0.2** share is not even worth remembering. | +| **Addiction** | `addictionRarity × fraction × dispositionMultiplier` — a splash of luciferium in a jar rolls at a fraction of a full jar's odds. | +| **Reactions** | water douses fire volume-for-volume; a splash of water in a carboy of chemfuel barely dents it, a cup of hooch in a bucket of water is simply gone. | +| **Label** | a real cocktail relabels itself with the shares: `piss jar (urine 60%, hooch 40%)`. | + +### Contents-aware labels + +Because contents are runtime, a "piss jar" the def shipped may actually hold a vile cocktail. `CompVessel` +tells the truth in the label: + +- A **cocktail** shows the shares, dominant first: `piss jar (feces 50%, urine 50%)`. +- A **single substance that is not the def's own**: `piss jar (hooch)`. +- A **fermenting or spoiled** vessel appends its state: `piss nuke, fermenting 42%` / `piss nuke, spoiled`. + Only a full-strength (≥95% potency), undiluted, pure vessel gets to wear its plain name — which is the + mechanical root of "a carboy is only a *piss nuke* when it is 100% ripe pure urine." (See **The Piss Nuke**.) + +--- + +## For modders + +Add a throwable container to any mod in three lines of XML: give a `ThingDef` a `CompProperties_Vessel` +with `volumeMl`, `sealed_`, and a default `substance`. You inherit correct fill time, blast, spill, +splash shape, mixing, fermentation-readiness, drink behaviour and contents labels for free — no +per-container code. Attach a new `SubstanceDef` (see **Substance Catalogue**) and any vessel can now hold +it. The two axes are orthogonal by construction: *N* vessels × *M* substances is *N×M* weapons from +*N+M* defs. + +The contents blend is exposed as a flat string via `SerializeContents()` / `DeserializeContents()` so a +content-agnostic layer (like Contraband's concealment) can store a cocktail blind and hand it back whole. + +--- +*Foul Play is part of the **Institution** suite — one install with a checkbox per layer (Core, Contraband, Policing, Corrections, Gangs, Ward) about what an institution does to the people inside it. It bridges to the Contraband layer when Institution is installed.*