Consolidate the suite into one installable Institution mod with toggles
This repo is now the single player-facing mod. It bundles the whole engine and all three feature layers into one folder -- Core, Contraband, Justice, and Gangs DLLs plus Contraband's Defs -- with one About.xml and a settings shim that turns each layer on or off from a checkbox (all on by default). A player installs one mod (this) and Harmony; no separate Core dependency. - Source/Institution: the only new code, a settings shim (InstitutionMod + InstitutionModSettings) that writes the player's choices into Core's shared InstitutionSettings. It owns no gameplay. - Tools/package.sh: rebuilds the sibling DLLs clean and vendors them + Contraband's content in here, so the repo stays a complete drop-in. - Assemblies/, Defs/, Textures/, Languages/: the vendored, assembled mod. Still fully modular and splittable: the feature code stays in its own repos and DLLs (their About.xml files remain), so breaking this back into separate mods is just shipping them individually -- no code change.
@@ -0,0 +1,6 @@
|
||||
obj/
|
||||
bin/
|
||||
*.user
|
||||
|
||||
# The assembled drop-in ships from this repo: the vendored Assemblies/ and Defs/ are committed so
|
||||
# the repo IS a complete, installable mod. Re-sync them with Tools/package.sh after changing a layer.
|
||||
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ModMetaData>
|
||||
<packageId>flan.institution</packageId>
|
||||
<name>Institution</name>
|
||||
<author>flan</author>
|
||||
<supportedVersions>
|
||||
<li>1.6</li>
|
||||
</supportedVersions>
|
||||
<description>Prison Architect in RimWorld: every pawn has a criminal propensity on a spectrum -- nature (traits) x nurture (mood, mistreatment, treatment) -- and the colony can police it.
|
||||
|
||||
This is the Institution suite in one install, with a checkbox per layer in the mod settings (all ON by default):
|
||||
|
||||
- Contraband -- the physical smuggling loop. Prisoners conceal what they walk in with, whittle shivs from their cell's own furniture, and dig Prison-Architect tunnels under the wall. Wardens search the right prisoner first, by the record -- and a bent warden looks the other way, or smuggles for them.
|
||||
|
||||
- Justice -- the corrections layer. Classification grades every held pawn by what they have actually done. A colony has a climate of order that crime erodes and visible justice restores, and it feeds back into everyone's disposition. Discipline hardens or reforms; parole lets the reformed out; regime gives prisoners the recreation vanilla denies them.
|
||||
|
||||
- Gangs -- the social layer. Disposed pawns band together along the lines they already share and move contraband among themselves; rival gangs fight, inside the wire or out, and the fight is a crime. A healthy, well-run colony grows few gangs, if any.
|
||||
|
||||
Turn any layer off in Options -> Mod Settings and it goes inert immediately.
|
||||
|
||||
Requires Harmony (for the recreation feature). The suite's shared Core engine ships inside this mod, so there is no separate dependency to install. Pairs with the standalone Institution: Ward (psychiatric commitment) and Foul Play (the vessel/substance framework, which bridges in).
|
||||
|
||||
Part of the Institution suite.
|
||||
|
||||
AI disclosure: developed with substantial assistance from Claude (Anthropic).
|
||||
</description>
|
||||
<modDependencies>
|
||||
<li>
|
||||
<packageId>brrainz.harmony</packageId>
|
||||
<displayName>Harmony</displayName>
|
||||
<steamWorkshopUrl>steam://url/CommunityFilePage/2009463077</steamWorkshopUrl>
|
||||
</li>
|
||||
</modDependencies>
|
||||
<loadAfter>
|
||||
<li>Ludeon.RimWorld</li>
|
||||
<li>brrainz.harmony</li>
|
||||
</loadAfter>
|
||||
</ModMetaData>
|
||||
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<Defs>
|
||||
|
||||
<JobDef>
|
||||
<defName>Contraband_SearchPawn</defName>
|
||||
<driverClass>Contraband.JobDriver_SearchPawn</driverClass>
|
||||
<reportString>searching TargetA.</reportString>
|
||||
</JobDef>
|
||||
|
||||
<!--
|
||||
A NEW WorkGiver class, not a patch on a vanilla one. That is what keeps this mod out of a
|
||||
fight with the rest of the prison ecosystem:
|
||||
|
||||
- Custom Prisoner Interactions patches the NAMED vanilla warden givers (_Chat, _Convert,
|
||||
_Enslave, _ReleasePrisoner). It cannot see this one.
|
||||
- Prison Commons postfixes WorkGiver_Warden.ShouldSkip on the BASE class, which this
|
||||
inherits and does not override, so searches respect prison-commons areas for free.
|
||||
|
||||
Priority sits below feeding: a starving prisoner matters more than a hidden shiv.
|
||||
-->
|
||||
<WorkGiverDef>
|
||||
<defName>Contraband_WardenSearch</defName>
|
||||
<label>search prisoners for contraband</label>
|
||||
<giverClass>Contraband.WorkGiver_Warden_Search</giverClass>
|
||||
<workType>Warden</workType>
|
||||
<verb>search</verb>
|
||||
<gerund>searching</gerund>
|
||||
<priorityInType>40</priorityInType>
|
||||
<requiredCapacities>
|
||||
<li>Manipulation</li>
|
||||
<li>Sight</li>
|
||||
</requiredCapacities>
|
||||
</WorkGiverDef>
|
||||
|
||||
</Defs>
|
||||
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<Defs>
|
||||
|
||||
<!--
|
||||
A crude pick, filed the same way a shiv is: off the cell's own furniture, over quiet days, the
|
||||
damage to the source the visible tell. Where the shiv is a weapon, this is a way OUT: its whole
|
||||
purpose is the tunnel (escapeWorker), so it carries no weapon stats and is never equipped.
|
||||
|
||||
A finished pick starts a Prison-Architect dig: the holder tunnels under the ground and everything
|
||||
on it toward the nearest wilderness, surfacing beyond the perimeter wall or fence. The dig itself
|
||||
is a second secret; a warden's cell search can turn it up, and the deeper the shaft the harder it
|
||||
is to miss. It works for any held pawn (prisoner, ward patient, slave) because the disposition
|
||||
to dig, not a prison-only mental break, is what drives it.
|
||||
-->
|
||||
<ThingDef ParentName="ResourceBase">
|
||||
<defName>CB_DiggingTool</defName>
|
||||
<label>crude pick</label>
|
||||
<description>A stubby digging pick filed off a bed frame, its point hardened in a cell wall. Useless as a weapon and useless above ground -- but pointed downward, patiently, it is a way out that no lock and no guard can see.</description>
|
||||
<techLevel>Neolithic</techLevel>
|
||||
<graphicData>
|
||||
<texPath>Things/Item/Contraband/CrudePick</texPath>
|
||||
<graphicClass>Graphic_Single</graphicClass>
|
||||
</graphicData>
|
||||
<statBases>
|
||||
<MaxHitPoints>60</MaxHitPoints>
|
||||
<Mass>1.2</Mass>
|
||||
<Beauty>-4</Beauty>
|
||||
<DeteriorationRate>2.0</DeteriorationRate>
|
||||
</statBases>
|
||||
<stackLimit>1</stackLimit>
|
||||
<comps>
|
||||
<li Class="Contraband.CompProperties_Contraband">
|
||||
<concealability>0.5</concealability>
|
||||
<hideIn>InCell</hideIn>
|
||||
<acquireWorker>Contraband.AcquireWorker_Improvise</acquireWorker>
|
||||
<escapeWorker>Contraband.EscapeTunnelWorker</escapeWorker>
|
||||
</li>
|
||||
</comps>
|
||||
</ThingDef>
|
||||
|
||||
</Defs>
|
||||
@@ -0,0 +1,59 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<Defs>
|
||||
|
||||
<!--
|
||||
A crude shiv, whittled from whatever the cell was furnished with. Stuffable, so its stats come
|
||||
from the harvested material for free: a wood shiv is feeble, a plasteel one is vicious. This is
|
||||
the whole point of the harvest-by-damage mechanic: the prison's own construction materials
|
||||
become the weapon materials, and a luxury block is a worse idea than it looks.
|
||||
|
||||
Registered as brewable contraband: a held pawn improvises it (AcquireWorker_Improvise), and the
|
||||
generic use-during-a-break path equips it (no useWorker; an armed prisoner IS the payload,
|
||||
and JobGiver_UseContraband only lets the disposed pick it up).
|
||||
-->
|
||||
<ThingDef ParentName="BaseMeleeWeapon_Sharp">
|
||||
<defName>CB_Shiv</defName>
|
||||
<label>shiv</label>
|
||||
<description>A blade filed off a bed frame and wrapped in cloth for a grip. Barely a weapon -- but a barely-a-weapon in a cell you thought was empty is a dead guard.</description>
|
||||
<techLevel>Neolithic</techLevel>
|
||||
<graphicData>
|
||||
<texPath>Things/Item/Contraband/Shiv</texPath> <!-- light greys: stuffable, so the material tint reads -->
|
||||
<graphicClass>Graphic_Single</graphicClass>
|
||||
</graphicData>
|
||||
<stuffCategories>
|
||||
<li>Metallic</li>
|
||||
<li>Woody</li>
|
||||
<li>Stony</li>
|
||||
</stuffCategories>
|
||||
<costStuffCount>15</costStuffCount>
|
||||
<statBases>
|
||||
<WorkToMake>1500</WorkToMake>
|
||||
<Mass>0.4</Mass>
|
||||
</statBases>
|
||||
<weaponClasses>
|
||||
<li>Melee</li>
|
||||
</weaponClasses>
|
||||
<comps>
|
||||
<li Class="Contraband.CompProperties_Contraband">
|
||||
<concealability>0.75</concealability>
|
||||
<hideIn>OnBody, InCell</hideIn>
|
||||
<acquireWorker>Contraband.AcquireWorker_Improvise</acquireWorker>
|
||||
</li>
|
||||
</comps>
|
||||
<tools>
|
||||
<li>
|
||||
<label>point</label>
|
||||
<capacities><li>Stab</li></capacities>
|
||||
<power>7</power>
|
||||
<cooldownTime>1.5</cooldownTime>
|
||||
</li>
|
||||
<li>
|
||||
<label>handle</label>
|
||||
<capacities><li>Blunt</li></capacities>
|
||||
<power>5</power>
|
||||
<cooldownTime>1.6</cooldownTime>
|
||||
</li>
|
||||
</tools>
|
||||
</ThingDef>
|
||||
|
||||
</Defs>
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<LanguageData>
|
||||
|
||||
<Contraband_Found>{0} searched {1} and found hidden {2}.</Contraband_Found>
|
||||
<Contraband_TunnelFound>{0} searched {1} and uncovered a tunnel dug with a hidden {2}.</Contraband_TunnelFound>
|
||||
<Contraband_TunnelBreached>{0} has tunnelled out under the perimeter and escaped.</Contraband_TunnelBreached>
|
||||
|
||||
<Contraband_VesselBurst>A {0} has burst under its own pressure.</Contraband_VesselBurst>
|
||||
<Contraband_Fermentation>Fermentation: {0}%</Contraband_Fermentation>
|
||||
<Contraband_FermentOverdue>Overdue. The pressure has to go somewhere.</Contraband_FermentOverdue>
|
||||
|
||||
</LanguageData>
|
||||
@@ -0,0 +1,29 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net472</TargetFramework>
|
||||
<AssemblyName>Institution</AssemblyName>
|
||||
<RootNamespace>InstitutionSuite</RootNamespace>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>disable</Nullable>
|
||||
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<GenerateDependencyFile>false</GenerateDependencyFile>
|
||||
<DebugType>none</DebugType>
|
||||
<OutputPath>..\..\Assemblies\</OutputPath>
|
||||
<CopyLocalLockFileAssemblies>false</CopyLocalLockFileAssemblies>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- The aggregate mod's only own code: a settings shim that writes the player's checkboxes into
|
||||
Core's shared InstitutionSettings. The feature DLLs (Contraband/Justice/Gangs) are vendored in
|
||||
at package time, not referenced here. Core holds the flags, so this references only Core. -->
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.3" PrivateAssets="all" />
|
||||
<PackageReference Include="Krafs.Rimworld.Ref" Version="1.6.4871" ExcludeAssets="runtime" />
|
||||
<Reference Include="InstitutionCore">
|
||||
<HintPath>$(MSBuildThisFileDirectory)..\..\..\rimworld-core\Assemblies\InstitutionCore.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,72 @@
|
||||
using UnityEngine;
|
||||
using Verse;
|
||||
|
||||
namespace InstitutionSuite
|
||||
{
|
||||
/// <summary>
|
||||
/// The single player-facing mod. It bundles the Institution feature layers -- Contraband,
|
||||
/// Justice, Gangs -- into one install with a checkbox per layer, and it owns NO gameplay code of
|
||||
/// its own. All it does is read the player's choices and write them into Core's shared
|
||||
/// <see cref="Contraband.InstitutionSettings"/>, which the feature assemblies (shipped alongside
|
||||
/// in this same mod) read at their entry points.
|
||||
///
|
||||
/// This is the whole "merge": a thin settings shim on top of the unchanged, still-separate feature
|
||||
/// DLLs. Everything defaults ON, so a fresh install is the full experience and the player opts out
|
||||
/// of pieces they don't want. Pull this mod apart into its layers again and nothing here is missed
|
||||
/// -- the features default their flags to true on their own.
|
||||
/// </summary>
|
||||
public class InstitutionMod : Mod
|
||||
{
|
||||
private readonly InstitutionModSettings settings;
|
||||
|
||||
public InstitutionMod(ModContentPack content) : base(content)
|
||||
{
|
||||
settings = GetSettings<InstitutionModSettings>();
|
||||
settings.Apply(); // push the loaded choices into Core before the features' static ctors run
|
||||
}
|
||||
|
||||
public override string SettingsCategory() => "Institution";
|
||||
|
||||
public override void DoSettingsWindowContents(Rect inRect)
|
||||
{
|
||||
Listing_Standard l = new Listing_Standard();
|
||||
l.Begin(inRect);
|
||||
l.CheckboxLabeled("Contraband",
|
||||
ref settings.contraband,
|
||||
"Concealment and intake, improvised shivs, Prison-Architect tunnels, warden search, and warden corruption.");
|
||||
l.Gap();
|
||||
l.CheckboxLabeled("Justice",
|
||||
ref settings.justice,
|
||||
"Classification, the deterrence feedback loop, discipline and reform, parole, and prisoner recreation (Regime).");
|
||||
l.Gap();
|
||||
l.CheckboxLabeled("Gangs",
|
||||
ref settings.gangs,
|
||||
"Gangs as contraband economies: joining by disposition, smuggling networks, rivalry, and fights-as-crime. Leans on Contraband and Justice.");
|
||||
l.End();
|
||||
settings.Apply(); // live: a toggle takes effect immediately for the gated behaviour
|
||||
}
|
||||
}
|
||||
|
||||
public class InstitutionModSettings : ModSettings
|
||||
{
|
||||
public bool contraband = true;
|
||||
public bool justice = true;
|
||||
public bool gangs = true;
|
||||
|
||||
/// <summary>Mirror the choices into Core's shared flags that every feature reads.</summary>
|
||||
public void Apply()
|
||||
{
|
||||
Contraband.InstitutionSettings.contraband = contraband;
|
||||
Contraband.InstitutionSettings.justice = justice;
|
||||
Contraband.InstitutionSettings.gangs = gangs;
|
||||
}
|
||||
|
||||
public override void ExposeData()
|
||||
{
|
||||
Scribe_Values.Look(ref contraband, "contraband", true);
|
||||
Scribe_Values.Look(ref justice, "justice", true);
|
||||
Scribe_Values.Look(ref gangs, "gangs", true);
|
||||
base.ExposeData();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 5.5 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
@@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env bash
|
||||
# Assemble the shippable, drop-in "Institution" mod into this repo.
|
||||
#
|
||||
# The Institution suite's code lives in SEPARATE sibling repos (rimworld-core, -contraband, -justice,
|
||||
# -gangs) as independent projects/DLLs -- that is what keeps it modular and splittable. For DISTRIBUTION
|
||||
# they are vendored into ONE mod folder (this repo) with one About.xml and a settings shim that toggles
|
||||
# each layer. This script rebuilds the sibling DLLs clean (no self-test) and copies them + Contraband's
|
||||
# Defs in here, so the repo is a complete installable mod.
|
||||
#
|
||||
# To split back into separate mods later: stop running this, and ship each sibling repo as its own mod
|
||||
# (their About.xml files still exist). Nothing in the code changes.
|
||||
#
|
||||
# Usage: Tools/package.sh (assumes siblings at ../rimworld-<name>)
|
||||
set -euo pipefail
|
||||
|
||||
HERE="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
SIB="$(dirname "$HERE")"
|
||||
CORE="$SIB/rimworld-core"
|
||||
CB="$SIB/rimworld-contraband"
|
||||
JUST="$SIB/rimworld-justice"
|
||||
GANGS="$SIB/rimworld-gangs"
|
||||
|
||||
command -v dotnet >/dev/null || { echo "dotnet not on PATH" >&2; exit 1; }
|
||||
|
||||
echo "==> building the engine + feature DLLs (clean, no self-test)"
|
||||
dotnet build "$CORE/Source/Core/Core.csproj" -c Release -v q --nologo
|
||||
dotnet build "$JUST/Source/Justice/Justice.csproj" -c Release -v q --nologo
|
||||
dotnet build "$CB/Source/Contraband/Contraband.csproj" -c Release -v q --nologo
|
||||
dotnet build "$GANGS/Source/Gangs/Gangs.csproj" -c Release -v q --nologo
|
||||
|
||||
echo "==> vendoring DLLs into Assemblies/"
|
||||
mkdir -p "$HERE/Assemblies"
|
||||
rm -f "$HERE/Assemblies/"*.dll # clear old layout
|
||||
dotnet build "$HERE/Source/Institution/Institution.csproj" -c Release -v q --nologo # (re-)emit Institution.dll here
|
||||
cp "$CORE/Assemblies/InstitutionCore.dll" "$HERE/Assemblies/"
|
||||
cp "$CB/Assemblies/Contraband.dll" "$HERE/Assemblies/"
|
||||
cp "$JUST/Assemblies/InstitutionJustice.dll" "$HERE/Assemblies/"
|
||||
cp "$GANGS/Assemblies/InstitutionGangs.dll" "$HERE/Assemblies/"
|
||||
|
||||
echo "==> vendoring Contraband's content"
|
||||
for d in Defs Patches Languages Textures; do
|
||||
rm -rf "$HERE/$d"
|
||||
[[ -e "$CB/$d" ]] && cp -r "$CB/$d" "$HERE/$d"
|
||||
done
|
||||
|
||||
echo "==> done. Assemblies:"
|
||||
ls -1 "$HERE/Assemblies/" | sed 's/^/ /'
|
||||
echo "The repo is now a complete drop-in Institution mod (Core bundled). Requires only Harmony."
|
||||