CultTweaker

Custom structures

Add buildings as flat sprites or animated Spine skeletons, and override the art of the game's own structures.

Structures live in BepInEx > plugins > CultTweaker > CustomStructures, one folder each, with a config.json.

A sprite structure

{
  "StructureName": "Custom Altar",
  "StructureDescription": "A custom altar for your cult.",
  "SpritePath": "icon.png",
  "BuildDurationMinutes": 60,
  "BuildOnlyOne": true,
  "RequiresTempleToBuild": true,
  "CanBeFlipped": false,
  "HideFromBuildMenu": false,
  "Bounds": { "X": 2, "Y": 2 },
  "ItemCost": { "LOG": 20, "STONE": 10 }
}

The shipped template, Templates/CustomStructures/ExampleStructure, is the same config with an Overrides array:

{
  "StructureName": "Custom Altar",
  "StructureDescription": "A custom altar for your cult.",
  "SpritePath": "custom_altar.png",
  "Overrides": [],

  "BuildDurationMinutes": 60,

  "BuildOnlyOne": true,

  "RequiresTempleToBuild": true,

  "CanBeFlipped": false,

  "HideFromBuildMenu": false,
  "Bounds": { "X": 2, "Y": 2 },

  "ItemCost": { "LOG": 20, "STONE": 10 }
}

Fields

FieldTypeDescription
StructureNamestringThe name the structure is listed and built under.
StructureDescriptionstringThe description shown in the build menu.
SpritePathstringA PNG in the same folder. For a sprite structure this is the structure; for a Spine structure it is only the build menu icon.
OverridesarraySprite overrides, in the same shape as a building override.
BuildDurationMinutesnumberHow long the structure takes to build.
BuildOnlyOneboolWhether only one may exist in the settlement.
RequiresTempleToBuildboolWhether a temple is needed before it can be built.
CanBeFlippedboolWhether the structure can be mirrored when placed.
HideFromBuildMenuboolKeeps the structure out of the player's build menu.
Bounds{ X, Y }The footprint in tiles.
ItemCostobjectItem name to quantity, the cost to build it.
SpineobjectBuilds the structure as an animated skeleton instead of a flat sprite. See below.

Set HideFromBuildMenu to true to keep a structure out of the player's build menu while still being able to place it yourself in the map editor. This is useful for scenery that belongs to a map rather than to a cult.

Hidden or not, every custom structure appears in the map editor's structure tool under the Custom group, and saved maps load it either way.

Custom structures also gain the editor's structure extras: an Affected by wind checkbox so they sway with the biome's own wind, shadows, and see-through when they block the camera during editing.

Building a Spine structure instead of a sprite

Add a Spine block and drop the Spine export (.json skeleton, .atlas, .png pages) into the same folder. The structure is then built as an animated skeleton rather than a flat sprite:

  "Spine": {
    "SkinName": "Marble",
    "Animation": "idle",
    "Loop": true,
    "Offset": { "X": 0, "Y": 0, "Z": 0 },
    "Scale": { "X": 1, "Y": 1, "Z": 1 }
  }

The shipped Templates/CustomStructures/ExampleSpineStructure is a complete example:

{
  "StructureName": "Occultist Effigy",
  "StructureDescription": "A scamp of the Old Faith, knelt in endless prayer. It does not look up when you pass.",
  "SpritePath": "icon.png",
  "Overrides": [],

  "BuildDurationMinutes": 45,
  "BuildOnlyOne": false,
  "RequiresTempleToBuild": true,
  "CanBeFlipped": true,
  "Bounds": { "X": 1, "Y": 1 },

  "ItemCost": { "LOG": 15, "STONE": 5 },

  "Spine": {
    "SkinName": "SF_Occultist_Scamp",
    "Animation": "_idles/pray",
    "Loop": true,

    "SkeletonScale": 0.005,
    "Offset": { "X": 0, "Y": 0, "Z": 0 },
    "Scale": { "X": 1, "Y": 1, "Z": 1 },
    "HideSprite": true
  }
}

Spine block fields

Every field is optional.

FieldTypeDefaultDescription
SkinNamestringthe skeleton's default skinWhich skin to dress the structure in.
AnimationstringnoneWhich animation to play once placed. Empty holds the setup pose, which is what a static prop wants.
LoopbooltrueWhether that animation loops.
Offset{ X, Y, Z }zeroNudges the skeleton relative to the structure's tile.
Scale{ X, Y, Z }oneScales the skeleton relative to the structure's tile.
Rotation{ X, Y, Z }matches the structure's spriteThe world is drawn on a tilt, so anything standing upright in it is rotated -60 on X (300 in the inspector). Left out, the skeleton copies whatever the structure's own sprite does, falling back to that tilt. Set it to { "X": 0, "Y": 0, "Z": 0 } for a prop meant to lie flat on the ground.
SkeletonScalefloat0.005Spine's import scale, for art authored at a different unit size. 0.005 matches the game's own skeletons.
SkeletonPath, AtlasPath, TexturePathsstring / arrayauto-discoveredSet these only when the folder holds more than one export.
ShaderNamestringSpine/SkeletonThe material shader used for the skeleton.
HideSpritebooltrueHides the flat sprite underneath. Set false to keep a painted base under an animated skeleton.

Auto-discovery

Nothing needs to be named in the Spine block because everything is discovered from the folder:

  • the skeleton is the one .json that is not config.json
  • the atlas is the one .atlas
  • the pages are every .png except the one SpritePath claims as the icon

Set SkeletonPath / AtlasPath / TexturePaths only if a folder holds more than one set.

SpritePath is still used as the build menu icon, so keep a sprite for it. The icon PNG is deliberately excluded from atlas page discovery - without that exclusion it would be loaded as an atlas page and the skeleton would render blank. Without an icon the structure falls back to a placeholder and still builds as the skeleton.

A skin or animation name the skeleton does not have is a warning in the log, not a crash: the structure falls back to the default skin and the setup pose.

Log lines to look for

Found custom structure folder: ...
Structure '...': spine attached

The first appears at startup, the second the first time the structure is placed.

The ready-made ExampleSpineStructure is an occultist scamp knelt in prayer, written against the same Spine export the CustomNpcs/TestNpc sample uses - the Human.json / Human.atlas / Human.png / Human2.png export - so copying those four art files in beside it makes it work as-is.

Overriding the game's own structures

Create a folder named after the structure you want to override in the BuildingOverrides folder. Add images and a config.json.

A complete structure skin folder looks something like this:

| CultTweaker.dll
| BuildingOverrides
    | FISHING_HUT
        | fishing_hut_BACK.png
        | fishing_hut_FRONT.png
        | config.json

Each structure override folder must have a config.json in it:

{
    "overrides": [
        {
            "spriteImageName": "fishing_hut_BACK.png",
            "offset": { "x": 0, "y": 0, "z": 0 },
            "scale": { "x": 1, "y": 1, "z": 1 },
            "rotation": { "x": 0, "y": 0, "z": 0 }
        },
        {
            "spriteImageName": "fishing_hut_FRONT.png",
            "offset": { "x": 0, "y": 0, "z": 0 },
            "scale": { "x": 1, "y": 1, "z": 1 },
            "rotation": { "x": 0, "y": 0, "z": 0 }
        },
    ]
}
FieldTypeDescription
spriteImageNamestringA PNG in the same folder.
offset{ x, y, z }Where the sprite sits relative to the structure.
scale{ x, y, z }How large it is drawn.
rotation{ x, y, z }How it is oriented in the world.

Change your offset and rotation accordingly, so as to build your structure design. A few things to note when building a custom structure design:

  • When sprites are rendered at rotation 0,0,0 the sprite is placed flat against the ground.
  • An offset Z of at least -0.027 should be applied to flat sprites to remove z-fighting. To place other sprites above that one, go more negative, such as -0.04.
  • If the sprites should be facing the camera, a rotation of 300,0,0 is necessary.

Mods and site by InfernoDragon0

Cult of the Lamb is a trademark of Massive Monster and Devolver Digital. This is an unofficial fan project.