Fisobs connects a custom creature type to template registration, relationships, state, body construction, AI construction, map restrictions, and several game interfaces. The pinned source is Dual-Iron/fisobs at commit 975f532b02431e0ef0b7f5c28033220153eba2a6, whose project declares version 5.1.0. This source version has not been run with Rain World build 22785462.
A Critob is a set of factories and integration choices for one global::CreatureTemplate.Type. It does not supply the creature’s body, graphics, behavior logic, or pathfinder. Those remain mod code returned by the factories.
Registration phases
CritobRegistry installs hooks when registered content is processed. Its source connects the critob to game initialization and creature creation in this order:
flowchart TD A[Register Critob] --> B[InitStaticWorld] B --> C[InitCustomTemplates] C --> D[CreateTemplate] D --> E[Finish static setup] E --> F[EstablishRelationships]
CreateTemplate() must return a template whose type is the critob’s registered ExtEnum value. The registry places it in StaticWorld.creatureTemplates by that value’s index. In the inspected game, InitStaticWorld() calls InitCustomTemplates() during setup. Fisobs hooks that inner call for templates and waits until the original InitStaticWorld() returns before calling EstablishRelationships(). Its separate abstract-creature hooks supply state, abstract AI, and realized factories when creatures are later constructed.
This order addresses two gaps in a direct custom implementation. The vanilla game builds its template array during static world setup, then dispatches body and AI creation through type-specific chains. Fisobs hooks those points and calls the registered factories for its types.
Required factories and matching contracts
| Critob member | Responsibility |
|---|---|
CreateTemplate() | Return movement, AI, save, body scale, and abstract behavior settings for this type |
EstablishRelationships() | Define this creature’s relationships with itself and other registered types |
CreateState(AbstractCreature) | Return persistent creature state, with HealthState as the default |
CreateAbstractAI(AbstractCreature) | Optionally replace the generic abstract AI |
CreateRealizedCreature(AbstractCreature) | Construct the concrete Creature body |
CreateRealizedAI(AbstractCreature) | Construct behavior AI for the realized creature |
The CreatureTemplate.AI value must agree with the factories. When it is true, CreateRealizedAI must return an AI object. A null result causes the pinned registry to throw. CreateAbstractAI may return null for an AI creature, in which case the AbstractCreature constructor’s generic abstract AI remains available. When template AI is false, supplying realized or abstract AI conflicts with the registry checks.
The realized AI still has to add the modules it uses. A creature that calls ArtificialIntelligence.SetDestination needs a suitable PathFinder module for that goal. The template’s allowed tiles and connections must match body movement. Creature templates covers the path costs and AI map data behind this contract.
World and room integration
WorldFileAliases() maps text names in world files to the custom type. Keep released aliases stable where packaged region files or other mods may use them. ConnectionIsAllowed() and TileIsAllowed() can override AI map decisions for body clearance or special movement. They should express limits that the realized creature can follow, not compensate for missing movement code.
DevtoolsRoomAttraction() and the map name and color methods add authoring visibility. LoadedPerformanceCost, SandboxPerformanceCost, ShelterDanger, icons, properties, kill scoring, and sandbox unlocks cover other systems. Each is a separate behavior to validate. A story creature does not need every optional interface for its first test, but omitted values still inherit library defaults.
Persistence and failure points
global::SaveState.AbstractCreatureFromString(global::World,System.String) creates a CreatureTemplate.Type from the saved token and rejects an unknown type. It then asks StaticWorld for the template before constructing the abstract creature and loading state. Register the type and critob before save parsing, and keep the type string stable across releases.
A factory implementation also needs to preserve the creature lifecycle described in Creature AI lifecycle. Test construction from a world spawn, abstract movement between rooms, realization after room readiness, den entry, abstraction, death, hibernation, save and reload, and behavior when the dependency is disabled. Add body clearance, shortcuts, room AI maps, graphics cleanup, sandbox, cooperative play, and Rain Meadow only when those systems are in scope.
No custom creature was compiled or run for this article. The evidence does not establish working body construction, graphics, custom CreatureState, complete relationship coverage, aliases in a packaged region, or runtime compatibility between Fisobs 5.1.0 and build 22785462. Use this page to divide implementation responsibilities and plan tests. It is not a complete creature recipe.
Sources
global::StaticWorld.InitStaticWorld(),global::AbstractCreature.Realize(),global::AbstractCreature.InitiateAI(), andglobal::SaveState.AbstractCreatureFromString(global::World,System.String)inAssembly-CSharp.dll, SHA-256B6BE1D4E18CE219D21091B51564CB6A11C1E4106B41DE903EB8E58849CB16FDB. See Runtime reference.- Critob and CritobRegistry at commit
975f532b02431e0ef0b7f5c28033220153eba2a6. - Fisobs Mosquito critob example at the same commit.