Wiki: player-facing rewrite of every layer + add a scenario FAQ, linked from Home
This commit is contained in:
@@ -1,128 +1,116 @@
|
||||
# Compatibility
|
||||
|
||||
*Contraband ships zero Harmony patches. It adds defs, subclasses a work-giver, mutates two duty
|
||||
trees at startup, and polls. That is why it composes instead of colliding.*
|
||||
*Contraband adds its own content and reads from the base game rather than rewriting it. That is why it
|
||||
composes with other mods instead of colliding with them.*
|
||||
|
||||
## Requires: Institution: Core
|
||||
|
||||
Contraband declares a hard `modDependency` on **`flan.institution.core`** and loads after it. This
|
||||
is not optional — after the split, the entire substrate Contraband reads lives in Core:
|
||||
Contraband has a hard dependency on **Institution: Core** and loads after it. This is not optional —
|
||||
after the split, everything Contraband reads lives in Core:
|
||||
|
||||
| Core provides | Contraband uses it for |
|
||||
|---|---|
|
||||
| `SecuredContext` / `SecuredContexts` / `CanConceal` / `IsHeld` | who counts as a concealer; who can be intaken, whittle, or dig |
|
||||
| `Propensity.Would(pawn, base, salt)` | every disposition roll — intake (0.6), improvise (0.10), dig (0.08), all seeded and scaled by nature × nurture |
|
||||
| `CriminalRecord` + `GameComponent_CriminalRecords` | `timesSearched`, `timesCaught`, `escapeAttempts`, `contrabandMade` — written by search and acquisition, read by priority |
|
||||
| Which pawns count as "in custody," and who can hide things | who counts as a concealer; who can be intaken, whittle, or dig |
|
||||
| A pawn's criminal propensity (nature × nurture) | every disposition roll — intake (0.6), improvise (0.10), dig (0.08), all scaled and settled per pawn |
|
||||
| The criminal record | times searched, times caught, escape attempts, contraband made — written by search and acquisition, read by search priority |
|
||||
|
||||
Install Contraband without Core and it will not run. Everything else on this page is optional
|
||||
interplay that degrades gracefully when the other mod is absent.
|
||||
Install Contraband without Core and it will not run. Everything else on this page is optional interplay
|
||||
that degrades gracefully when the other mod is absent.
|
||||
|
||||
## Zero Harmony patches
|
||||
## It plays nicely with other prison mods
|
||||
|
||||
Post-split, the mod's one Harmony patch (the regime that forces Joy for prisoners) moved to
|
||||
**Institution: Justice**, so Contraband is Harmony-free again. Instead of patching, it:
|
||||
Contraband adds its own content rather than rewriting the base game's. It:
|
||||
|
||||
- **Adds a new `WorkGiver`** (`WorkGiver_Warden_Search`) rather than patching a vanilla one.
|
||||
- **Subclasses `WorkGiver_Warden`**, inheriting its behaviour rather than overriding it.
|
||||
- **Mutates two `DutyDef` think trees at startup** via `StaticConstructorOnStartup` (not Harmony) —
|
||||
an XML patch on a duty think tree silently no-ops in 1.6, so it is done in C#, deterministically.
|
||||
- **Polls** every held pawn from a `MapComponent` for intake, improvisation, and tunnels — no hook
|
||||
on the capture event is needed because the tick already visits every held pawn.
|
||||
- **Adds a new warden job** (search) rather than changing an existing one.
|
||||
- **Reuses vanilla warden behaviour** rather than overriding it, so anything that adjusts warden
|
||||
behaviour on the base class flows through to searches for free.
|
||||
- **Extends two escape-related behaviours at startup** so prisoners arm themselves and use what they
|
||||
are hiding when they break — inserted at a specific point, and it logs a warning if that anchor is
|
||||
missing rather than failing silently.
|
||||
- **Runs on a heartbeat** over held pawns for intake, improvisation, and tunnels — no hook on the
|
||||
capture event is needed because the heartbeat already visits every held pawn.
|
||||
|
||||
The net effect: the surfaces other prison mods touch are mostly untouched here, so conflicts are the
|
||||
exception, not the rule.
|
||||
|
||||
## Foul Play — the carboy bridge
|
||||
|
||||
**Foul Play** (the "Piss Nuke" mod) stays its own mod with its own front door, and yet its **carboy
|
||||
is a first-class contraband item.** This is the flagship demonstration of Contraband's *"items are
|
||||
defs, subsystems are classes, mods are audiences"* principle, and it works through two seams:
|
||||
**Foul Play** (the "Piss Nuke" mod) stays its own mod with its own front door, and yet its **carboy is
|
||||
a first-class contraband item.** This is the flagship demonstration of Contraband's *"items are
|
||||
content, subsystems are shared, mods are audiences"* principle, and it works two ways:
|
||||
|
||||
1. **Cross-assembly worker resolution.** `CompProperties_Contraband`'s `useWorker` / `escapeWorker`
|
||||
fields are plain `Type`s, and RimWorld resolves def `Type` fields with
|
||||
`GenTypes.GetTypeInAnyAssembly` — searching **every loaded assembly**. So the carboy declares
|
||||
`CompProperties_Contraband` and points `useWorker` at a class that lives in *Foul Play's* assembly
|
||||
(e.g. a throw-the-carboy worker). Contraband never has to know that class exists.
|
||||
2. **The opaque content tag.** A carboy is not just "a jar" — it is a jar *of* a fermented blend, and
|
||||
that blend has to survive being concealed. Foul Play sets Contraband's two delegates:
|
||||
|
||||
```csharp
|
||||
ContrabandUtility.ContentTagOf = thing => /* serialise the carboy's blend */;
|
||||
ContrabandUtility.ApplyContent = (thing, tag) => /* pour that blend back in on redeem */;
|
||||
```
|
||||
|
||||
When a carboy is intaken or smuggled, Contraband captures the tag blind; on redemption it hands
|
||||
the tag back to Foul Play to restore the contents. **Contraband knows nothing about substances or
|
||||
fermentation** — that framework lives entirely in Foul Play. If Foul Play is absent, both delegates
|
||||
are null, no content is captured, and nothing breaks: a jar is just a jar. See
|
||||
1. **The carboy brings its own behaviour.** The carboy simply declares itself as contraband and points
|
||||
at the throw-the-carboy behaviour that lives in *Foul Play*. Contraband never has to know that
|
||||
behaviour exists — it just runs whatever the item brought with it.
|
||||
2. **A concealed carboy keeps its contents.** A carboy is not just "a jar" — it is a jar *of* a
|
||||
fermented blend, and that blend has to survive being concealed. When a carboy is intaken or
|
||||
smuggled, Contraband captures a label for its contents blindly; on redemption it hands the label
|
||||
back to Foul Play to restore the blend. **Contraband knows nothing about substances or
|
||||
fermentation** — that framework lives entirely in Foul Play. If Foul Play is absent, no content is
|
||||
captured and nothing breaks: a jar is just a jar. See
|
||||
[Concealment and Intake](Concealment-and-Intake.md).
|
||||
|
||||
The dependency runs one way only: Foul Play bridges *to* Contraband (and to Core) if they are
|
||||
present; Contraband takes **no** dependency on Foul Play.
|
||||
The dependency runs one way only: Foul Play bridges *to* Contraband (and to Core) if they are present;
|
||||
Contraband takes **no** dependency on Foul Play.
|
||||
|
||||
## Institution: Justice — the record is the shared bus
|
||||
|
||||
Contraband and **Justice** never call each other. They meet on Core's `CriminalRecord`:
|
||||
Contraband and **Justice** never call each other. They meet on Core's criminal record — Contraband
|
||||
writes to it, Justice reads from it:
|
||||
|
||||
```
|
||||
Contraband writes ──▶ CriminalRecord ──▶ Justice reads
|
||||
timesSearched (in Core) Classification (security grade)
|
||||
timesCaught Deterrence (colony-wide signal)
|
||||
escapeAttempts Discipline / Parole (reform)
|
||||
contrabandMade
|
||||
```
|
||||
| Contraband writes | Justice reads it into |
|
||||
|---|---|
|
||||
| times searched | Classification (security grade) |
|
||||
| times caught | Deterrence (colony-wide signal) |
|
||||
| escape attempts | Discipline / Parole (reform) |
|
||||
| contraband made | |
|
||||
|
||||
- **Catching contraband feeds classification.** A prisoner repeatedly caught with shivs or foiled
|
||||
mid-tunnel accrues `timesCaught` and `escapeAttempts`, which Justice's classification weighs into a
|
||||
higher security grade.
|
||||
- **And it feeds back.** Justice's deterrence signal flows *back* through Core's propensity seam
|
||||
(`Nurture`), nudging every future intake / improvise / dig roll a Contraband pawn makes. A prison
|
||||
that catches and disciplines becomes a prison where fewer prisoners bother trying — without either
|
||||
mod referencing the other. Run Contraband alone and the deterrence factor is a neutral 1.0; the
|
||||
record fields still route the warden.
|
||||
mid-tunnel racks up catches and escape attempts, which Justice's classification weighs into a higher
|
||||
security grade.
|
||||
- **And it feeds back.** Justice's deterrence signal flows *back* through Core's propensity, nudging
|
||||
every future intake / improvise / dig roll a Contraband pawn makes. A prison that catches and
|
||||
disciplines becomes a prison where fewer prisoners bother trying — without either mod referencing the
|
||||
other. Run Contraband alone and deterrence is a neutral 1.0; the record still routes the warden.
|
||||
|
||||
## Institution: Gangs — the contraband economy
|
||||
|
||||
**Gangs** depends on Core, **Contraband**, and Justice, because a gang *is* a contraband economy:
|
||||
|
||||
- Gang smuggling moves contraband through the same public `Conceal` door intake and corruption use.
|
||||
- A gang's outside members are the natural caller for the **reach-in corruption** primitive
|
||||
(`Corruption.Smuggle`) — paying a bent warden to make a delivery. That primitive is exposed in
|
||||
Contraband but has no in-repo trigger; Gangs is what drives it. See [Corruption](Corruption.md).
|
||||
- Gang fights route to Justice's crime record, which then raises search priority here. The loop
|
||||
closes through Core again.
|
||||
- Gang smuggling moves contraband through the same door intake and corruption use.
|
||||
- A gang's outside members are the natural caller for the **reach-in corruption** — paying a bent
|
||||
warden to make a delivery. That ability exists in Contraband but has no in-game trigger of its own;
|
||||
Gangs is what drives it. See [Corruption](Corruption.md).
|
||||
- Gang fights route to Justice's crime record, which then raises search priority here. The loop closes
|
||||
through Core again.
|
||||
|
||||
## Prison mods the suite is tested against
|
||||
|
||||
| Mod | Interaction | Verdict |
|
||||
|---|---|---|
|
||||
| **Prison Commons** | postfixes `WorkGiver_Warden.ShouldSkip` on the **base** class; Contraband's search subclasses it and does not override, so searches respect prison-commons/allowed areas **for free** | works by inheritance |
|
||||
| **Custom Prisoner Interactions** | patches only the *named* vanilla warden givers (`_Chat`, `_Convert`, `_Enslave`, `_ReleasePrisoner`); it cannot see a brand-new giver | no conflict |
|
||||
| **Prisoner Realism** | its escapes are for "mood prisoners" mid-break; a tunnel breakout hands off to vanilla `PrisonBreakUtility.StartPrisonBreak`, which Prisoner Realism layers on. Tunnels **complement** it — they let ward patients and slaves who would never mood-break still, patiently, dig out | complementary |
|
||||
| **Prison Labor** | prisoners working outside the cell are still held pawns and still tracked; Contraband adds no patches to labor jobs. A work assignment is simply another place a disposed prisoner might come by materials | no conflict |
|
||||
| **Prisoner Recreation** | overlaps the *regime* feature — which now lives in **Institution: Justice**, not here, and is written to be idempotent with Prisoner Recreation | not Contraband's concern post-split |
|
||||
| **Prison Commons** | it adjusts warden behaviour on the base class, and Contraband's search inherits that, so searches respect prison-commons/allowed areas **for free** | works by inheritance |
|
||||
| **Custom Prisoner Interactions** | it only touches the *named* vanilla warden jobs (chat, convert, enslave, release); it cannot see a brand-new job | no conflict |
|
||||
| **Prisoner Realism** | its escapes are for "mood prisoners" mid-break; a tunnel breakout hands off to the vanilla prison-break flow, which Prisoner Realism layers on. Tunnels **complement** it — they let ward patients and slaves who would never mood-break still, patiently, dig out | complementary |
|
||||
| **Prison Labor** | prisoners working outside the cell are still held pawns and still tracked; Contraband adds nothing to labor jobs. A work assignment is simply another place a disposed prisoner might come by materials | no conflict |
|
||||
| **Prisoner Recreation** | overlaps the *regime* feature — which now lives in **Institution: Justice**, not here, and is written to coexist with Prisoner Recreation | not Contraband's concern post-split |
|
||||
|
||||
## Load order
|
||||
|
||||
```
|
||||
Ludeon.RimWorld
|
||||
flan.institution.core ← required, loads before Contraband
|
||||
flan.institution.contraband ← this mod
|
||||
(Foul Play / Justice / Gangs — any order after Core; each bridges if present)
|
||||
```
|
||||
1. Base game
|
||||
2. **Institution: Core** — required, loads before Contraband
|
||||
3. **Institution: Contraband** — this mod
|
||||
4. **Foul Play / Justice / Gangs** — any order after Core; each bridges if present
|
||||
|
||||
## The general rule
|
||||
|
||||
If a mod adds prisoner behaviour by **patching vanilla warden givers or the escape duty tree by
|
||||
name**, it will not see Contraband's additions, and Contraband will not see its — they pass each
|
||||
other. If a mod adds a *new* `WorkGiver` or duty node of its own, it stacks. The one place to watch is
|
||||
another mod that *also* rewrites the same two duty think trees (`PrisonerEscape`,
|
||||
`PrisonerAssaultColony`) wholesale; Contraband inserts its nodes at a specific anchor and logs a
|
||||
warning if that anchor is missing, so a load-order or conflict problem is visible in the log rather
|
||||
than silent.
|
||||
If a mod adds prisoner behaviour by **changing vanilla warden jobs or the escape flow by name**, it
|
||||
will not see Contraband's additions, and Contraband will not see its — they pass each other harmlessly.
|
||||
If a mod adds a *new* warden job or escape behaviour of its own, it stacks. The one place to watch is
|
||||
another mod that *also* rewrites the same two escape-related behaviours wholesale; Contraband inserts
|
||||
its part at a specific point and logs a warning if that point is missing, so a load-order or conflict
|
||||
problem is visible in the log rather than silent.
|
||||
|
||||
---
|
||||
|
||||
*Part of the **Institution** suite — Core · Contraband · Justice · Gangs, alongside Foul Play and
|
||||
Ward. Each stands alone; together they interlock.*
|
||||
**
|
||||
|
||||
Reference in New Issue
Block a user