Skip to content

Authoring Items

Melissa Bell edited this page Apr 9, 2026 · 5 revisions

Authoring Items

This page describes the items JSON format that EmoTracker packs use to declare every tracked item — swords, bottles, keys, dungeon prizes, boss reminders, etc. It's the top of a small hierarchy: read this page first for the general rules, then jump to the sub-page for each specific item type.

New to pack authoring? Read Developer Setup first to get VS Code validation wired up — authoring items without schema-backed autocomplete is painful.

Where items files live

Items are declared in one or more JSON files inside your pack and loaded from Lua at pack init time:

-- scripts/init.lua
Tracker:AddItems("items/common.json")
Tracker:AddItems("items/keys.json")
  • Paths are relative to the pack root.
  • You can split items across any number of files — the order you load them in is the order they're registered, which matters for items that reference other items (e.g. Composite Toggle and Badged Toggle).
  • Legacy packs can place everything in a top-level items.json, which EmoTracker still loads automatically. New packs should prefer explicit Tracker:AddItems(...) calls.

Top-level structure

Every items file is a JSON array of item objects:

[
  {
    "name": "Hookshot",
    "type": "toggle",
    "img": "images/items/hookshot.png",
    "codes": "hookshot"
  },
  {
    "name": "Sword",
    "type": "progressive",
    "stages": [
      { "img": "images/items/sword1.png", "codes": "sword,swordlevel:1" },
      { "img": "images/items/sword2.png", "codes": "sword,swordlevel:2" }
    ]
  }
]

Each object must specify at minimum a name and a type. Everything else depends on the type — see the item type sub-pages below.

The canonical JSON schema for items files is published in EmoTracker-Service/sdk/schema/items.json. Wire it up in VS Code per Developer Setup → Configuring JSON schema validation to get autocomplete and validation for every field described here.

Fields every item shares

All item types inherit the following base fields, parsed in ItemBase.CreateItem:

Field Type Required Default Description
name string yes Human-readable display name. Must be unique within the pack.
type string yes One of toggle, progressive, consumable, progressive_toggle, composite_toggle, toggle_badged, static, sectionchests, blank.
capturable boolean no (per-type) Whether this item can be selected in a section's capture slot. Defaults to true for most types, false for static, composite_toggle, sectionchests, and blank.
mask_input boolean no false If true, only the visible pixels of the current image are clickable. If false, the item's whole rectangular area is clickable.
ignore_user_input boolean no false If true, the item ignores mouse clicks entirely (useful for script-driven items).
disabled_image_filter string no inherited from tracker Override the image filter applied to disabled / potential states for this item.
phonetic_substitutes string[] no Alternate spoken phrases the voice control system should recognise as this item's name. See Voice control below.

Codes

Many item types accept a codes field (sometimes on each stage). Codes are the mechanism items use to advertise "state" to the rest of the pack:

  • Location logic asks "is item X present?" by calling has("hookshot"). That resolves to a yes/no answer based on whether an item providing the code hookshot is currently active.
  • Progressive items advertise different codes at each stage (sword,swordlevel:1 at stage 1, sword,swordlevel:2 at stage 2, etc.), so logic can query both "any sword" and "sword level ≥ 2".
  • Consumables advertise their code plus their count — a bomb_count code with AvailableCount=5 resolves in logic as 5 bombs.
  • External Lua scripts can also query codes via the same API.

Rules of thumb

  • Codes are case-insensitive.
  • Multiple codes on one entry are comma-separated: "codes": "bow,arrows".
  • Codes don't need to be predeclared anywhere — just start using them in items and reference them from your logic.
  • Keep code names short, lowercase, and unique. Conflicts across items are allowed (the runtime sums counts), but confusing codes are the #1 source of hard-to-debug logic bugs.
  • By convention, multi-stage items use colon-separated suffixes (swordlevel:2) so logic can do comparisons.

Images

Most item types accept an img field (and some also accept img_mods, disabled_img, disabled_img_mods, etc.) for per-state images.

  • Image paths are relative to the pack root.
  • img_mods is a comma-separated filter spec applied to the referenced image at load time. See Authoring — Image Filters for the full syntax and list of built-in filters (grayscale, dim, brightness, saturation, overlay, and @disabled).
  • disabled_img is a separate image used for the "off" / "potential" state. If you don't supply one, EmoTracker derives it by applying disabled_img_mods (or the pack-level default filter, grayscale, dim) to the main image — see Image Filters → The default disabled filter.
  • Images should be PNG with transparency. Size is up to you — the tracker scales them to fit the grid — but 32×32 or 48×48 per item is typical.

Item types

Pick the sub-page for the type of item you're authoring. Each sub-page documents its JSON fields, behavior, the mouse interactions that result, and at least one small example.

Type What it's for Sub-page
toggle Simple on/off item (hookshot, hammer, big key) Toggle
progressive Multi-stage item with one icon per level (sword, gloves) Progressive
consumable Counter (bottles, bombs, small keys, hearts) Consumable
progressive_toggle Hybrid: multi-stage and on/off (bow/arrows, medallions) Progressive Toggle
composite_toggle Single icon backed by two linked toggle items (boomerangs) Composite Toggle
toggle_badged Toggle item wearing a second toggle as a "badge" Badged Toggle
static Non-interactive icon that still provides codes Static
sectionchests Proxy item that mirrors a location section's unchecked chest count Section Chests Proxy
blank Empty placeholder used for grid spacing Blank

Mouse behavior

Each type has its own left-click / right-click semantics. The Item Types And Mouse Controls page (under For Users) is the canonical reference for what clicks do — it's worth skimming even as an author, because it's what your players will actually see.

Voice control

EmoTracker's voice control extension maps item names to spoken commands. When a player says "hey tracker track hookshot", the extension looks up hookshot in its command table. Because the bundled speech model treats hookshot as a single unknown word, the extension applies an automatic word-split heuristic: it recursively finds the longest known prefix of the word and splits there, so hookshot becomes hook shot, silverarrows becomes silver arrows, and so on.

For most items the heuristic is sufficient. Use phonetic_substitutes when:

  • The automatic split produces the wrong result
  • You want a completely different spoken alias (e.g. "bow" as a shorthand for "fairy bow")
  • The word genuinely has no valid split and you want a pronounceable fallback
{
  "name": "Hookshot",
  "type": "toggle",
  "img": "images/items/hookshot.png",
  "codes": "hookshot",
  "phonetic_substitutes": ["hook shot"]
}
{
  "name": "Silver Arrows",
  "type": "toggle",
  "img": "images/items/silver_arrows.png",
  "codes": "silverarrows",
  "phonetic_substitutes": ["silver arrows", "silver arrow"]
}

All substitutes register the same voice command action as the canonical name, so any recognised variant triggers the same result. The canonical name is always registered as well — you do not need to include it in phonetic_substitutes.

For setup instructions, the full command reference, and troubleshooting, see Voice Control.

See also

Clone this wiki locally