Skip to content

18 Custom Terrains

ionriftgm edited this page Oct 21, 2026 · 3 revisions

Custom Terrains

Import terrain JSON to add custom locations and environments. A custom terrain appears in Quartermaster and Respite pickers after one import.

For cache generation and loot pools, see Setup: Quartermaster. For rest environments, see Setup: Respite.

How it works

Open Game Settings > Module Settings > Ionrift Library and click Manage Terrains. The panel shows any imported terrains and an Import Terrain button.

  1. Click Import Terrain.
  2. Select a .json file.
  3. The terrain registers and appears in Quartermaster's cache generator and Respite's rest setup.

Imported terrains persist across sessions. They survive module updates.

The JSON format

A terrain file has a spine (id, label, category) and optional module sections.

{
  "id": "cheese-caves",
  "label": "Cheese Caves",
  "category": "built",
  "quartermaster": {
    "flavorPhrases": [
      "Behind a wheel of aged cheddar, {container} sits undisturbed.",
      "A hollow gouda conceals {container}.",
      "Wedged between two enormous brie rounds, something glints."
    ],
    "materials": ["Crystallised Whey", "Rind Plate"],
    "itemDescriptions": {}
  },
  "respite": {
    "comfort": "sheltered",
    "weather": ["damp", "still", "fragrant"],
    "mealRules": { "waterPerDay": 0, "foodPerDay": 1 },
    "events": []
  }
}

Save that as cheese-caves.json and import it. The cache generator picks up "Cheese Caves" in the terrain dropdown. Generated caches use the flavor phrases for discovery text and the materials list for masterwork labels.

Spine fields

Field Type Required Notes
id string yes Lowercase, hyphens allowed, no spaces. Must not match a base terrain (forest, swamp, desert, urban, dungeon)
label string yes Display name in all pickers
category string no wilderness, built, or safe-haven. Defaults to wilderness

The category controls which group the terrain lands in. built covers indoor, constructed, or urban areas. safe-haven is inns and protected zones. Everything else is wilderness.

Quartermaster section

Optional. If present, the cache generator uses it when generating loot for this terrain.

Field Type Notes
flavorPhrases array of strings Discovery text for caches. Use {container} as a placeholder for the container name
materials array of strings Masterwork material keywords (for example "Stalagmite Iron"). Falls back to "Mastercraft" if empty
itemDescriptions object Per-category mundane masking descriptions. Keys match item categories (sword, axe, shield, generic). Optional

Flavor phrases

Each string is a sentence describing how the cache is found. The generator picks one at random. {container} is replaced with the container name at generation time.

"flavorPhrases": [
  "A crack in the cavern wall reveals {container}.",
  "Behind a curtain of mineral deposits, something glints.",
  "Tucked into a crevice, {container} is barely visible."
]

Three to five phrases keep the output varied. One works if that is all you need.

Respite section

Optional. If present, Respite can use it for rest setup defaults. If absent, the terrain appears in the picker as a custom stub with travel and forage off.

Field Type Notes
comfort string Default comfort: safe, sheltered, rough, or hostile
weather array of strings Weather pool for the event system
mealRules object { "waterPerDay": N, "foodPerDay": N }
events array Custom rest events in Respite event format. Empty array is valid

The Respite section is a starting point. Full event authoring follows the same format as Content Packs custom event imports. You can add events later by importing an event pack with the matching terrain tag.

Removing a terrain

Open the Manage Terrains panel. Click the trash icon on the row. Confirm. The terrain leaves all pickers on the next render. Existing caches or rest logs that used the terrain keep their data; they reference the terrain id as a string, not a live object.

Example: something less silly

A practical custom terrain for a campaign that goes underground.

{
  "id": "crystal-cavern",
  "label": "Crystal Cavern",
  "category": "built",
  "quartermaster": {
    "flavorPhrases": [
      "A geode split wide reveals {container} inside.",
      "Light refracts through a crystal cluster. {container} sits at its base.",
      "Loose shards crunch underfoot near {container}."
    ],
    "materials": ["Geode Iron", "Crystal Lattice"],
    "itemDescriptions": {}
  }
}

No Respite section here. The terrain shows in Respite's picker as a custom stub with travel off. That is fine for a location that only needs loot generation.

Sharing terrains

Export your JSON by copying the file. Import by selecting it in another world's Manage Terrains panel. The file is self-contained.

Feel free to share terrain JSON in #community-packs on the Ionrift Discord.

Related

Clone this wiki locally