-
Notifications
You must be signed in to change notification settings - Fork 8
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
progressivetype.
Parsed in EmoTracker.Data/Items/ProgressiveItem.cs. Matches the progressive branch in items.json.
| 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). |
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. |
| 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.
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:
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.
{
"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" }
]
}{
"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 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" }
]
}{
"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" }
]
}-
allow_disabledvs 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:2play nicely with inheritance; a stage that advertisesswordlevel:2while its predecessor advertisedswordlevel:1means both codes are active at stage 2. -
Starting stage.
initial_stage_idxis zero-based across the full stage list including the auto-added disabled stage. Withallow_disabled: trueand 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.
- Authoring Items — top-level items file format and base fields
-
Authoring — Image Filters — syntax and built-in filters for
img_mods/disabled_img_mods - Item Types And Mouse Controls → Progressive — user-facing click behavior
- Authoring Items — Progressive Toggle — for items that also need an independent on/off state
-
items.jsonschema — authoritative JSON schema
- Installation
- Installing and Loading Packages
- Item Types and Mouse Controls
- Map Locations
- Map Location Colors
- Saving and Loading
- Multi-Tab and Window
- Autotracking
- NDI Broadcasting
- Twitch Chat HUD
- Note Taking
- Voice Control
- Keyboard Shortcuts
{ "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" } ] }