Layers

The slots players choose origins from — and how to add to them.

A layer is a choice a player makes. The base Origins mod ships one layer — origins:origin — and that’s the “pick your origin” screen everyone knows. Layers are what actually put origins in front of players; an origin not in any layer is invisible.

You can add origins to the existing layer, or define brand-new layers (a second, independent choice — say a “class” alongside an “origin”).

A layer file

Layers live in data/<namespace>/origin_layers/.

{
  "order": 0,
  "enabled": true,
  "name": "layer.my_pack.origin.name",
  "origins": [
    "my_pack:merling",
    "my_pack:ember",
    "origins:human"
  ]
}

Core fields

FieldTypeDefaultPurpose
originslist of conditioned originrequiredThe origins offered in this layer.
orderinteger0Order when several layers are chosen in turn. Lowest first.
enabledbooleantrueWhether the layer is active.
namestringlayer.<ns>.<path>.nameTranslation key for the layer’s title.
gui_titleobject{}choose_origin and view_origin translation keys for the two screens.
missing_namestring""Translation key shown when the player has no origin in this layer.
missing_descriptionstring""Translation key for that placeholder’s description.
default_originidentifierFallback for players this layer offers no choice to.
auto_choosebooleanfalseSkip the screen when the layer offers exactly one choosable origin.
hiddenbooleanfalseHide the layer from the origin-viewing screen.
randomobjectRandom-roll settings — see Randomised layers.
randomiserobjectRe-roll-over-a-life settings — see Lifecycle & re-rolls.
replacebooleanfalseDiscard lower-priority packs’ version of this layer instead of merging into it.

name, missing_name, missing_description and both gui_title entries are translation keys, not literal text. Put the display string in your pack’s language file. A raw string still “works” — an unknown key renders as itself — but it will not translate.

Conditioned origins

An entry in origins is either a plain identifier, or an object that gates a group of origins behind an entity condition — any of them, including origins:origin itself. The two forms mix freely in one list.

{
   "order":2,
   "auto_choose":true,
   "hidden":true,
   "name":"layer.my_pack.evolved.name",
   "origins":[
      {
         "condition":{
            "type":"origins:origin",
            "layer":"origins:origin",
            "origin":"my_pack:ember"
         },
         "origins":[
            "my_pack:ember_evolved"
         ]
      },
      {
         "condition":{
            "type":"origins:origin",
            "layer":"origins:origin",
            "origin":"my_pack:ember",
            "inverted":true
         },
         "origins":[
            "my_pack:unevolved"
         ]
      }
   ]
}

The condition is re-evaluated every time the layer’s options are listed, so a layer can react to what the player picked in an earlier layer, to a resource value, or to anything else an entity condition can see.

The origins in a gated group must be choosable ("unchoosable": true excludes them). An unchoosable origin never appears as an option and auto_choose will not pick it.

auto_choose and default_origin

These are how a conditioned layer grants an origin without ever showing a screen — the pattern above needs one of them, or the player is asked to “choose” from a list of one.

  • auto_choose — when the layer offers exactly one choosable origin for that player, it is assigned silently and no screen opens. With two or more options the player still chooses normally.
  • default_origin — the fallback for a layer the player is never asked about. It is applied only when the layer offers them nothing choosable and no random roll, on join and on data-pack reload. A layer that can be chosen always shows its screen — default_origin never pre-empts a real choice.

Both are re-checked on join, on data-pack reload, after every origin the player picks, and on Orb of Origin use — so a layer whose condition only becomes true after an earlier layer is chosen resolves in the same breath as that choice.

Adding to an existing layer

To drop your origins into the vanilla Origins screen, define a layer with the same idorigins:origin — in your own pack listing just your origins. Origins merges layers that share an id across data packs, so your entries appear alongside the built-in ones rather than replacing them.

// data/origins/origin_layers/origin.json  (in your pack)
{
   "origins":[
      "my_pack:merling",
      "my_pack:ember"
   ]
}

Set "replace": true in the higher-priority pack to throw the merged result away and use only your file.

Randomised layers

Layers can hand out a random origin instead of letting the player choose — the basis for “random origin” servers. Everything lives in the random object:

FieldTypeDefaultPurpose
allowbooleantrueOffer the “random” option in the screen.
allow_unchoosablebooleanfalseLet the roll land on unchoosable origins.
excludelist of identifierOrigins the roll never picks.
stylestring"uniform"uniform, weighted, or roll (alias gacha) for the rolling animation.
weightsmap of identifier → integer{}Per-origin weighting, for style: weighted.
roll_durationinteger80Animation length in ticks, for style: roll.
{
   "origins":[
      "my_pack:merling",
      "my_pack:ember"
   ],
   "random":{
      "allow":true,
      "style":"weighted",
      "weights":{
         "my_pack:ember":3
      }
   }
}

The flat allow_random, allow_random_unchoosable and exclude_random fields are the pre-random-block spelling and still load. A random block wins over all three.

Lifecycle & re-rolls

The randomiser object controls what happens over a life:

FieldTypeDefaultPurpose
on_first_joinbooleanfalseRoll an origin when the player first joins.
on_deathbooleanfalseRe-roll on death.
on_sleepbooleanfalseRe-roll after sleeping.
deaths_between_randomisesinteger1Deaths required before a re-roll.
sleeps_between_randomisesinteger1Sleeps required before a re-roll.
livesobject{}enabled (boolean, false) and starting (integer, 10) — lives before the layer locks.
reset_to_default_on_deathbooleanfalseRevert to default_origin on death instead of re-rolling.
show_screen_on_deathbooleanfalseOpen the choose screen on death rather than rolling.
allow_duplicatebooleanfalseLet a re-roll land on the origin the player already had.
broadcast_messagesbooleantrueAnnounce re-rolls in chat.

These options are how “hardcore origins”, “randomiser”, and “one life per origin” servers are configured — all in JSON, no code.