Skip to content

Authoring Items Progressive

EmoTracker Community edited this page Apr 8, 2026 · 3 revisions

Authoring Items — Progressive

A progressive item shows a single icon that cycles through multiple stages — one image per stage — as the player collects upgrades. The canonical example is a Link to the Past sword going Fighter → Master → Tempered → Gold, all in the same slot.

See Authoring Items for the general items file format and base fields. This page only covers fields specific to the progressive type.

JSON schema

Parsed in EmoTracker.Data/Items/ProgressiveItem.cs. Matches the progressive branch in items.json.

Top-level fields

Field Type Required Default Description
type "progressive" yes Literal string.
stages array yes Ordered list of stage definitions (see below).
allow_disabled boolean no true If true, EmoTracker prepends an automatic "off / stage 0" entry to the list. Set to false if you want to manage the unacquired state yourself (for example with a custom stages[0]).
initial_stage_idx integer no -1 Zero-based index of the stage the item should start in. -1 means "the disabled stage", which is the first entry when allow_disabled is true.
loop boolean no false If true, advancing past the last stage wraps around to the first.
disabled_img_mods string no Image filter spec applied to the automatically-generated disabled stage (used when allow_disabled is true).

Per-stage fields

Each entry in stages is its own object:

Field Type Required Default Description
img string yes Path (relative to pack root) to this stage's image.
img_mods string no Comma-separated image filter spec applied to img.
codes string no Comma-separated codes this stage provides.
inherit_codes boolean no true If true, this stage's code set is the previous stage's codes plus anything in this stage's codes. If false, the inheritance chain resets and this stage only provides the codes declared here.

Mouse behavior

Button Action
Left click Advance to the next stage (wraps if loop is true)
Right click Go back to the previous stage

See Item Types And Mouse Controls → Progressive for the user-facing explanation.

How stages and code inheritance work

By default each stage inherits the codes of the stage before it. This is what lets logic do simple "any version of this item" checks:

{
  "stages": [
    { "img": "sword1.png", "codes": "sword,swordlevel:1" },
    { "img": "sword2.png", "codes": "swordlevel:2" },
    { "img": "sword3.png", "codes": "swordlevel:3" },
    { "img": "sword4.png", "codes": "swordlevel:4" }
  ]
}

After loading, each stage's effective code set is:

Stage Effective codes
0 (disabled auto-added) (none)
1 (fighter) sword,swordlevel:1
2 (master) sword,swordlevel:1,swordlevel:2
3 (tempered) sword,swordlevel:1,swordlevel:2,swordlevel:3
4 (gold) sword,swordlevel:1,swordlevel:2,swordlevel:3,swordlevel:4

So a logic check of has("sword") is true as soon as you reach stage 1, and has("swordlevel:3") works automatically once the player hits tempered.

Setting "inherit_codes": false on a stage resets the chain — that stage's codes are the only ones it advertises, and subsequent stages start inheriting from it.

Examples

Sword — classic inherited progressive

{
  "name": "Sword",
  "type": "progressive",
  "stages": [
    { "img": "images/items/sword1.png",  "codes": "sword,swordlevel:1" },
    { "img": "images/items/sword2.png",  "codes": "swordlevel:2" },
    { "img": "images/items/sword3.png",  "codes": "swordlevel:3" },
    { "img": "images/items/sword4.png",  "codes": "swordlevel:4" }
  ]
}

Gloves — short progressive

{
  "name": "Gloves",
  "type": "progressive",
  "stages": [
    { "img": "images/items/glove1.png", "codes": "glove,powerglove" },
    { "img": "images/items/glove2.png", "codes": "titansmitt" }
  ]
}

After loading: stage 1 provides glove,powerglove, stage 2 provides glove,powerglove,titansmitt thanks to inheritance.

Bottles — each stage is a new count

Bottles in the official ALttPR pack use a progressive with a different image per bottle count:

{
  "name": "Bottles",
  "type": "progressive",
  "stages": [
    { "img": "images/items/bottle1.png", "codes": "bottle,bottlecount:1" },
    { "img": "images/items/bottle2.png", "codes": "bottlecount:2" },
    { "img": "images/items/bottle3.png", "codes": "bottlecount:3" },
    { "img": "images/items/bottle4.png", "codes": "bottlecount:4" }
  ]
}

Looping progressive

{
  "name": "Trial Bonus",
  "type": "progressive",
  "loop": true,
  "stages": [
    { "img": "images/items/bonus_none.png", "codes": "bonus:0" },
    { "img": "images/items/bonus_1.png",    "codes": "bonus:1" },
    { "img": "images/items/bonus_2.png",    "codes": "bonus:2" }
  ]
}

Tips and pitfalls

  • allow_disabled vs explicit stage 0. The automatic disabled stage is almost always what you want. Only disable it if you need full control over the unacquired icon and its codes — for example if the "unacquired" state should still provide some code.
  • Inheriting colons matter. Suffix-style codes like swordlevel:2 play nicely with inheritance; a stage that advertises swordlevel:2 while its predecessor advertised swordlevel:1 means both codes are active at stage 2.
  • Starting stage. initial_stage_idx is zero-based across the full stage list including the auto-added disabled stage. With allow_disabled: true and 4 real stages, valid indices are 0 (disabled) through 4 (last real stage).
  • Don't use a progressive to fake a consumable. If you want a numeric counter, use a Consumable — the UI handles the number rendering for you, and the logic side is cleaner.

See also

Clone this wiki locally