# Concealment and Intake *How a hidden item exists without existing, how it gets onto a prisoner in the first place, and how it becomes real again.* This is the spine of the whole mod. Everything else — shivs, tunnels, searches, corruption — is a different way to add to, or remove from, the private list this page describes. ## While it is concealed, there is no Thing The single most important rule, and the source states it plainly: > `MapComponent_Contraband` tracks what each pawn is hiding. **Concealed contraband is not a Thing. > It is a secret.** It is not in the gear tab, there is no icon, and the player is told nothing — > because an item you can see in a UI is not contraband, it is inventory, and there would be nothing > for a warden to discover and no reason to ever order a search. Concretely, a concealed item lives as a `ConcealedItem` row in a `List` on the map component. It carries the def, a `progress` value, the material it ended up made of, an optional source it is being harvested from, tunnel state if it is a pick, and an opaque `contentTag`. It holds **no spawned object** anywhere in the world until one of two things happens: | Moment | What happens | Method | |---|---|---| | The prisoner **uses** it | It materialises into their inventory as a real `Thing` | `TryRedeem` | | A warden **finds** it | It is deleted from the list; it never becomes a `Thing` at all | `Confiscate` | A corollary the search page leans on hard: **an empty search must still cost time.** If the `Search` job only ever appeared when there was genuinely something to find, the mere *offer* of the job would be the discovery. You have to be able to toss a clean cell and come up with nothing. ## Where a thing can hide: `ConcealSite` Every contraband def declares where it can be hidden. This is not decoration — it decides **who can ever find it**. ```csharp [Flags] enum ConcealSite { None = 0, OnBody = 1, InCell = 2 } ``` | Site | Holds | Found by | |---|---|---| | `OnBody` | small: a shiv, pills, a phone | searching the **pawn** | | `InCell` | bulky: a rifle, a carboy, a crude pick | tossing the **room** | A warden turning over a prisoner and their cell reaches both (`OnBody | InCell`). The reason the enum is split at all: a **constable** in Justice's now-shipping policing layer, frisking a colonist named in a street crime, reaches only `OnBody`, so whatever is under their floorboards stays there until somebody has grounds to search the *room*. The split between "who may search" and "what a search reaches" is deliberate — see [Warden Search](Warden-Search.md). ## Three sources of contraband, and no list of items At startup, `ContrabandUtility` scans every `ThingDef` and decides whether it is contraband. There is no hardcoded list of item names — there are three recognisers: 1. **Explicit.** Any def carrying `CompProperties_Contraband`. This is the opt-in, and it is how a mod plugs in its own `acquireWorker` / `useWorker` / `escapeWorker` behaviour. 2. **Every drug** (`ThingDef.IsDrug`) — inferred automatically. 3. **Every weapon** (`ThingDef.IsWeapon`) that is not `destroyOnDrop` — inferred from **mass**. The inference (`ContrabandUtility.Infer`) fills in concealability and hiding place so a modder never has to: | Kind | Test | `concealability` | `hideIn` | |---|---|---|---| | Hard drug | `drugCategory == Hard` | **0.75** | `OnBody \| InCell` | | Other drug | any other `IsDrug` | **0.5** | `OnBody \| InCell` | | Light weapon | `Mass ≤ 2.0` | **0.7** | `OnBody \| InCell` | | Heavy weapon | `2.0 < Mass ≤ 10.0` | **0.35** | `InCell` only | | Very heavy weapon | `Mass > 10.0` | — | **not contraband** (a minigun hides nowhere) | `concealability` runs 0..1 where **0 = a warden finds it every time and 1 = never**; higher is harder to find. Drugs and inferred weapons get **no `acquireWorker`** (you cannot synthesise yayo in a bare cell, and you cannot conjure a rifle) and **no `useWorker`** — because vanilla already knows what to do with them. `JobGiver_SatisfyChemicalNeed` takes a drug; an armed prisoner *is* the payload. Getting the item into the cell is the entire problem, and that is all these routes solve. Nothing here mutates another mod's defs. It is a lookup keyed on the def, computed once, held in a dictionary. Modded drugs and weapons are covered without ever being named. ## The poll: no Harmony `MapComponent_Contraband` runs on a heartbeat. Every **250 ticks** (`CheckIntervalTicks`) it visits every pawn who could be concealing something and does all the ongoing work: intake, tunnel progress, and improvisation. If nothing on the map is self-acquirable and there are no escape tools registered, it returns immediately and costs nothing. Polling — rather than patching — is a deliberate architecture choice. **The tick already visits every held pawn**, so intake needs no Harmony hook on the capture event: a pawn who is in custody but not yet in the `intakeProcessed` set is, by definition, one who was newly taken. The whole mod ships zero Harmony patches, and this is a large part of why. ### Who counts as a concealer `ContrabandUtility.Concealers(map)` is **not** just prisoners. It delegates to Core's secured-context predicate and yields every pawn whose belongings are anyone's business — prisoners, slaves, **and free colonists**: > A free colonist forbidden their drug by a drug policy or an ideoligion is precisely the pawn who > keeps a private stash — and vanilla already denies them, with no valve. Whether anyone may *search* a given concealer is a separate question with a separate answer (the warden's authority reaches prisoners; a future cop's reaches colonists). Tracking is pawn-agnostic; authority is not. ## Intake: the moment of capture Vanilla never strips a captive *on capture* — a downed pawn keeps whatever they walked in with, and the warden path just hauls them to a cell. Intake is Contraband's answer to that gap. `RunIntake(pawn)` runs from the poll, on the first pass that sees a newly-held pawn: 1. **Held only.** The pawn must be humanlike and `IsHeld` (prisoner, slave, ward patient). A free colonist is a concealer, but nobody frisks and processes *them* on the way into a cell, so their carried gear is never intaken. 2. **Once.** The pawn's `thingIDNumber` is added to a `HashSet`. The set stores an `int`, not a pawn reference, so it holds no ghost of a captive who has since died. A second pass finds them already processed and does nothing. 3. **Even while downed.** Intake runs *before* the "must be awake" gate. The stash a captive walked in with is hidden the moment they are in custody, not when they wake — everything *after* intake (whittling, digging) needs them awake, but hiding what is already on you does not. 4. **Only what can ride on a body.** `IsIntakeConcealable` accepts a thing only if its contraband props include the `OnBody` flag. A shiv up a sleeve is intaken; a rifle or a suit of armour is too bulky to palm and stays as ordinary strippable gear the player confiscates for free. 5. **Per-item disposition.** For each concealable thing the captive carries, the mod rolls whether *this* pawn would hide *this* item: ``` Propensity.Would(pawn, 0.6, SaltIntake ^ item.thingIDNumber) ``` Base chance 0.6, then scaled by the pawn's nature × nurture (Core's `Propensity`). The roll is **seeded per (pawn, item)** — a fixed fact, not a fresh coin each tick. The frightened cook surrenders the knife; the disposed lifer palms it, and always would have. When a pawn does hide an item, the real `Thing` is **destroyed** (equipment via `DestroyEquipment`, inventory via `Destroy(Vanish)`) and a concealed secret is created in its place, preserving what the item was made of (`stuff`) and — critically — its `contentTag`. ## The content tag: preserving contents without understanding them A concealed vessel is not just "a jar" — it is a jar *of* something (hooch, piss, a fermented blend), and that something has to survive being hidden and come back on redemption. Contraband stores a single opaque string, `contentTag`, and **has no idea what it means**: ```csharp // A bridge mod (Foul Play) fills these in. Null (no bridge) = items have no contents. ContrabandUtility.ContentTagOf; // Func — read on conceal ContrabandUtility.ApplyContent; // Action — applied on redeem ``` On concealment, `ContentTagOf(thing)` captures the tag (e.g. "a jar of a piss+hooch cocktail"). On redemption, `ApplyContent(newThing, tag)` pours that content back into the freshly-made thing. This is the exact seam **Foul Play** uses to keep a smuggled carboy's contents intact. Without a bridge, both delegates are null, no content is captured, and nothing is lost — a shiv is just a shiv. Fermentation itself lives in Foul Play, not here. A concealed vessel materialises **fresh** and ferments afterward like any other, which suits the theme: fresh-brewed piss is weak, and time is what makes it a weapon. (`concealedTick` records how long it was hidden, for any bridge that wants to restore pre-aging — Contraband keeps the number but never acts on it.) See [Compatibility](Compatibility.md). ## Redemption: the secret becomes a Thing `TryRedeem(pawn, def)` is where a secret turns real: 1. Choose the material — the harvested `stuff`, or the def's default if it was made from stuff. 2. `ThingMaker.MakeThing(def, stuff)`. 3. If there was a `contentTag`, call `ApplyContent` to restore the contents. 4. `TryAdd` it to the pawn's inventory. If that fails, the thing is vanished and nothing is lost. 5. Remove the secret from the list. The trigger for redemption is the breakout duty tree. `ThinkTreeInjection` runs once at startup and mutates two duty defs directly (an XML patch on a `DutyDef` think tree silently no-ops in 1.6, so it is done in C#): | Duty | Injected | Where | |---|---|---| | `PrisonerEscape` | `JobGiver_ArmSelf`, then `JobGiver_UseContraband` | **after** `JobGiver_TakeCombatEnhancingDrug` | | `PrisonerAssaultColony` | `JobGiver_ArmSelf`, then `JobGiver_UseContraband` | **before** `JobGiver_AIFightEnemies` | `JobGiver_UseContraband` sits right beside `JobGiver_TakeCombatEnhancingDrug` — the one contraband hook Ludeon wrote and then left reading an always-empty inventory. For each thing a pawn is hiding: - **Inert contraband** (a drug, a stashed rifle — no `useWorker`): just materialise it and get out of the way. Vanilla takes the drug via `JobGiver_SatisfyChemicalNeed`; a weapon in inventory is a weapon. But a stashed **weapon** only comes out for someone who would actually use it (`Disposition.WouldArmSelf`) — the same person who would not stop to pick a rifle off the floor does not become a fighter because the knife was in their sock, and a pawn incapable of violence never does at all. If they qualify, the weapon is moved from inventory into their equipment slot; otherwise it stays hidden and they run. See [Improvised Weapons](Improvised-Weapons.md). - **Active contraband** (a `useWorker` — e.g. Foul Play's throw-the-carboy): materialise it, then hand off to the worker's `TryGiveJob`, which produces the actual use job. ## Confiscation and the door every route comes through `Confiscate(pawn, def)` simply removes the secret. It **never becomes a Thing** — the warden found it, and there is nothing to drop on the floor. (This is why searching is not a way for the colony to *acquire* a prisoner's drugs; it is a way to *deny* them.) At the other end, `Conceal(prisoner, def, ...)` is the public door **every** supply route comes through — intake calls it, a bent warden calls it ([Corruption](Corruption.md)), and a smuggling gangmate ([Institution: Gangs](Compatibility.md)) calls it. It hands a prisoner something already finished and hidden, optionally with a `contentTag`. One door, many keys. ## Persistence `MapComponent_Contraband.ExposeData` deep-saves the secret list, the per-pawn search cooldowns, and the `intakeProcessed` set. On load it prunes any row whose pawn or def failed to resolve — prisoners who died or left take their secrets with them, and a null key would throw on the next tick. ## Quick reference | Constant | Value | Meaning | |---|---|---| | `CheckIntervalTicks` | 250 | poll cadence for intake / tunnels / improvisation | | Intake base chance | 0.60 | per-item, before nature × nurture | | Intake gate | `IsHeld` + `OnBody` | only held pawns, only body-hideable items | | Hard-drug concealability | 0.75 | inferred | | Other-drug concealability | 0.50 | inferred | | Light-weapon concealability | 0.70 | `Mass ≤ 2.0`, hides on body | | Heavy-weapon concealability | 0.35 | `2.0 < Mass ≤ 10.0`, `InCell` only | | Unhideable mass | > 10.0 | not contraband | --- *Part of the **Institution** suite — Core · Contraband · Justice · Gangs, alongside Foul Play and Ward. Each stands alone; together they interlock.* **