You are viewing a potentially older version of this package. View all versions.
CeruleanCutlass-DonorKit-0.1.1 icon

DonorKit

The donor-scene harvest engine for Outward BepInEx mods: additively load any area, clone a live creature into a dormant template, and unload cleanly. Library dependency, installed automatically when another mod (SpawnKit, CompanionKit) needs it.

Date uploaded a day ago
Version 0.1.1
Download link CeruleanCutlass-DonorKit-0.1.1.zip
Downloads 32
Dependency string CeruleanCutlass-DonorKit-0.1.1

This mod requires the following mods to function

BepInEx-BepInExPack_Outward-5.4.19 icon
BepInEx-BepInExPack_Outward

BepInEx pack for Outward.

Preferred version: 5.4.19
CeruleanCutlass-ForgeKit-0.4.0 icon
CeruleanCutlass-ForgeKit

Dependency-free dev-tooling for Outward BepInEx mods: file-driven dev command loop, self-test harness, on-screen toasts, player-ready lifecycle wait, embedded/override table loaders, and a shared dev-verb pack (movement/combat/skill/status probes).

Preferred version: 0.4.0
CeruleanCutlass-NetKit-0.2.1 icon
CeruleanCutlass-NetKit

Shared Photon co-op transport layer for Outward BepInEx mods: channels over one relay, a hello/peer ledger, per-channel counters/heartbeat, PUN diagnostics, and a replicated-record store for consumer state mirroring.

Preferred version: 0.2.1

README

DonorKit

📖 Full documentation: DonorKit wiki page

The donor-scene harvest engine — "get me a live body for species X, from anywhere in the game". Extracted from CompanionKit on 2026-07-26 (static-analysis wave, lane 5E) so SpawnKit no longer has to depend on the pet library for its creature supply.

What it owns

  • DonorHarvest — the guarded cycle: additive load → freeze at sceneLoaded → payload → unload → repair. Generic Func<Character, object> / Func<Scene, object> payloads, so one load can stock many species (light-probe cycles are the scarce resource).
  • DonorSceneTable (+ the embedded DonorScenes.txt) — the species→scene roster, pins, identity resolution, and build-scene name matching. DonorScenes.txt is generated by bwspecies build; see tools/BwSpeciesTool/Paths.cs.
  • DonorCreatureFinder — exact-then-substring live-donor lookup within a loaded scene.
  • The guards, each of which exists because the un-guarded version broke a real session: DonorPhotonGuard (view-id collisions), DonorSaveGuard (mid-harvest saves, deferred via the game's own SetSaveRequired re-arm), DonorSingletonRestore (the four Instance-hijack restores), AmbienceGuard + DonorAudioRegistry (the persistent audio registries), SoulSpotGuard (duplicate-UID throw mid-Awake), DonorDisplayRepair (skybox / display chain), TerrainGuard (LOD render holes), DonorNetworkInitGuard (guest replica conversion).
  • SkeletonRig / RagdollRig — the rig surgery a dormant clone needs to render and ragdoll.
  • The expedition tier (lane 5E-2, 2026-07-26 — moved here from CompanionKit): ExpeditionHarvest (the vanilla-loader round-trip state machine for region/town scenes too large to load additively), ExpeditionOrchestrator (the expedition verb body, batch capture payload, in-place capture, once-per-launch boot auto-warm), ExpeditionManifest (ck_expeditions.txt — the historical filename is kept so existing installs keep their record), StorySense (the prologue/first-visit story-safety reads). Config: [Expedition] in cobalt.donorkit.cfg. The expedition/ templateclear/expeditionreset/templateprobe verbs stay on CONSUMER channels (ck_cmd.txt + BW twins) — templateclear's full reset must also re-arm CompanionKit's effigy gate, which only the consumer can reach.
  • The K2 template store (TemplateStore + BodyTemplateStore, lane 5E-2): ONE store with per-consumer KINDS. The companion-body kind (BodyTemplateStore) carries identity + captured stats, eager-prunes, refuses substitutes on identity lookups, keeps unhealthy rigs; the spawn kind (SpawnKit's SpawnTemplates layers on it) holds bare normalized GameObjects with opt-in LRU cap eviction and rejects unrepairable rigs. The kinds share only the FABRIC (holder/registry/recency/ orphan-proof clear) — unifying the policies would change behavior, so they stay at their call sites. E3 seams for third mods: TemplateStore.RegisterSpecies(key, scenes) (runtime donor-table row) and TemplateStore.RegisterTemplate(key, dormantBody) (parks a body in the spawn kind through SpawnKit's own normalization seam).

What it deliberately does NOT own

  • Puppet-shaped code (the 5E permanent-shim rule — a DonorKit→CompanionKit edge is forbidden): BodyTemplateCache.PuppetFrom (template → CompanionBody via BodyFactory.BuildPuppet), ClearAllAndForgetMisses (also resets the effigy harvest gate), and the stat capture itself — the store calls back through BodyTemplateStore.StatCapturer, which CompanionKit wires to AttributeCapture.From in its Awake.
  • The pure donor logic — DonorTable, DonorChain, RigSurgery, TerrainMaintenance, the Expedition* planners — which stays in core/CompanionKit.Core. DonorTable cannot be split from SpeciesTable/Species/Regions, and its file-mates SpeciesFloats/SpeciesYaw are consumed by Beastwhispering.Core. DonorKit references that game-ref-free COMPUTE assembly, never the CompanionKit plugin.

Dev verbs (BepInEx/config/DonorKit_cmd.txt)

photondump · audiodump · audioprune · terraindump · terrainfix · scenedump · selftest

Consumers also register the first five on their own channel via DonorVerbs.RegisterAll(registry).

Config

BepInEx/config/cobalt.donorkit.cfg — [Rig] RepairSkinnedBones (default true). Moved here from cobalt.companionkit.cfg with SkeletonRig, its only reader.

API sketch

[BepInDependency("cobalt.donorkit", BepInDependency.DependencyFlags.HardDependency)]

if (DonorHarvest.TryGetDonorScenes("Pearlbird", out var scenes, out var term))
    StartCoroutine(DonorHarvest.HarvestChain(scenes, term,
        use:      src => Object.Instantiate(src.gameObject, MyHolder().transform),
        onResult: r  => UseOrFailLoudly(r as GameObject)));

The payload runs while the donor is loaded and frozen, must be synchronous, and must not keep references into the donor scene. Use DonorHarvest.IdentityFor(key, src) rather than src.Name — a pinned row's frozen donor reports its serialized base-prefab name.

CHANGELOG

DonorKit changelog

0.1.1 — 2026-07-30

  • DonorKit gets a painterly butterfly net; Disengage now reads "return and stay"