Skip to content

Authoring Lua API Reference

EmoTracker Community edited this page Apr 8, 2026 · 1 revision

Authoring Lua — API Reference

This page is the reference manual for everything EmoTracker exposes to your Lua scripts. It documents each global object, every method and property they expose, and the enum values you can pass back to the runtime.

See Authoring Lua Scripts for the broader overview, and the topic-specific sub-pages (init.lua, Standard Callbacks, Custom Access Rules, Autotracking, Lua Items) for the conceptual guides.

Global objects

When the runtime constructs the Lua environment, it injects six global names. They're all available from line one of init.lua.

Global Source class Description
Tracker TrackerScriptInterface Main entry point — register data files, look up codes, query active variant.
AutoTracker AutoTrackerExtension Direct memory-read API. Only meaningful when an autotracking provider is connected.
Layout LayoutScriptInterface Layout lookup helpers and accessibility-color queries.
ScriptHost ScriptManager Memory-watch registration, notifications, console output, Lua-item factory.
ImageReference ImageReferenceProvider Constructors for image references with optional filters and layering.
AccessibilityLevel enum Constants for the seven accessibility levels rules can return.
NotificationType enum Constants for the four notification severity levels.

NLua exposes C# methods and properties via either the : (instance call) or . (property access) syntax. Methods are called as Tracker:AddItems("..."); properties are read as Tracker.ActiveVariantUID.


Tracker

The main entry point — exposes the data-loading functions, code lookups, and active-variant info. Backed by EmoTracker.Data.TrackerScriptInterface.

Methods

Tracker:AddItems(path)

Loads an items JSON file. The path is pack-relative.

  • path (string) — relative path to the items JSON file.

Items must be loaded before locations and layouts that reference them by code.

Tracker:AddItems("items/common.json")

See Authoring Items for the items file format.

Tracker:AddMaps(path)

Loads a maps JSON file. The path is pack-relative.

  • path (string) — relative path to the maps JSON file.

Maps must be loaded before any layout that uses a map-type element or any location that references a map in map_locations.

Tracker:AddMaps("maps/maps.json")

Tracker:AddLocations(path)

Loads a locations JSON file. The path is pack-relative.

  • path (string) — relative path to the locations JSON file.
Tracker:AddLocations("locations/dungeons.json")

See Authoring Locations for the locations file format.

Tracker:AddLayouts(path)

Loads a layouts JSON file. The path is pack-relative.

  • path (string) — relative path to the layouts JSON file.

Layouts that reference other layouts (via layout elements or button_popup) must be loaded after the layouts they reference.

Tracker:AddLayouts("layouts/popups.json")
Tracker:AddLayouts("layouts/tracker.json")

See Authoring Layouts for the layouts file format.

Tracker:FindObjectForCode(code)

Looks up the first object that provides the given code, going through the runtime's filtered code provider (Tracker.GetFilteredCodeAndProvider). Returns whatever object the matching provider returns, or nil if nothing matches.

  • code (string) — the code to look up. Supports the same prefix syntax as access rules:
    • no prefix → looks up an item
    • @ prefix → looks up a location or section
    • $ prefix → calls a Lua function (rarely useful here; use it from access rules instead)
local sword = Tracker:FindObjectForCode("sword")
local ep_dungeon = Tracker:FindObjectForCode("@Eastern Palace/Dungeon")

The returned object is the underlying C# object, so you can read and write its properties from Lua: sword.Active = true, ep_dungeon.AvailableChestCount = 0, etc.

Tracker:ProviderCountForCode(code)

Returns the count that the runtime's code system associates with the given code. For items this is "how many of this item the player has"; for locations it's 1 if the location is reachable in any way, 0 otherwise; for sections similarly.

  • code (string) — the code to look up. Supports the same prefix syntax as FindObjectForCode.

Returns (count, AccessibilityLevel) where the second value is the maximum accessibility level the matching provider could supply.

local key_count = Tracker:ProviderCountForCode("smallkey0")
if key_count >= 2 then
    -- ...
end

-- Wrap in a 'has' helper for ergonomics
function has(code)
    return Tracker:ProviderCountForCode(code) > 0
end

This is the call you'll typically wrap in a has(...) helper for use inside custom access rule functions.

Properties

Tracker.ActiveVariantUID

(string, read-only)

The UID of the currently-loaded pack variant, as declared in the pack's manifest. Use it to branch on the active variant inside init.lua:

local variant = Tracker.ActiveVariantUID
if variant == "item_tracker" then
    Tracker:AddLayouts("layouts/items_only.json")
end

Tracker.RootLocation

(Location, read-only)

The root location of the location tree. Rarely needed in scripts directly — but useful if you need to walk the location hierarchy.

Settings shortcuts (legacy)

These properties are exposed for backwards compatibility with older packs that needed to read or set application-wide settings from Lua. New packs should usually leave them alone.

Property Type Description
Tracker.DisplayAllLocations boolean Mirrors ApplicationSettings.DisplayAllLocations.
Tracker.AlwaysAllowClearing boolean Mirrors ApplicationSettings.AlwaysAllowClearing.
Tracker.PinLocationsOnItemCapture boolean Mirrors ApplicationSettings.PinLocationsOnItemCapture.
Tracker.AutoUnpinLocationsOnClear boolean Mirrors ApplicationSettings.AutoUnpinLocationsOnClear.

These let you read and write user settings from Lua, but you should generally not change user-facing settings without their consent.


AutoTracker

The autotracker memory-read API. Backed by EmoTracker.Extensions.AutoTracker.AutoTrackerExtension.

These methods only return meaningful data when an autotracker provider is connected (autotracker_started has fired and the connection hasn't been lost). Outside that window they return the supplied default value.

For most autotracking, you'll use ScriptHost:AddMemoryWatch and read bytes from the segment passed to your callback. The methods below are for one-off reads outside any registered watch.

AutoTracker:ReadU8(address, default)

Reads an unsigned 8-bit byte at the given address.

  • address (integer) — absolute memory address.
  • default (integer, optional, default 0) — value returned if the read fails (e.g., disconnected, address rejected by the whitelist, etc.).

Returns the byte value (or default).

AutoTracker:Read8(address, default)

Same as ReadU8 but interprets the byte as signed.

AutoTracker:ReadU16(address, default)

Reads an unsigned 16-bit word at the given address.

AutoTracker:Read16(address, default)

Reads a signed 16-bit word at the given address.

All addresses passed to these methods must be inside the game's memory whitelist (declared in supported_games.json). Reads outside the whitelist silently return the default.


Layout

Layout lookup helpers. Backed by EmoTracker.Data.LayoutScriptInterface.

Layout:FindLayout(key)

Looks up a previously-loaded layout by name.

  • key (string) — the layout name as registered in your layouts JSON files.

Returns the Layout object, or nil if no layout with that name exists.

Layout:FindElement(uid)

Looks up a layout element by its uid. Layout elements that have a uid field are registered with the layout manager at parse time and can be looked up later via this call.

  • uid (string) — the unique identifier the element was tagged with.

Returns the LayoutItem, or nil if no element with that uid exists.

-- A layout element declared with "uid": "main_items_grid"
local grid = Layout:FindElement("main_items_grid")
if grid ~= nil then
    -- ...
end

Layout:GetColorForAccessibility(accessibility)

Returns the color string the application currently uses for the given accessibility level. Useful when scripting custom rendering or text colorization.

  • accessibility (AccessibilityLevel) — one of the AccessibilityLevel enum values.

Returns a web color string (e.g., "#ff3030").

local red = Layout:GetColorForAccessibility(AccessibilityLevel.None)

ScriptHost

The "kitchen sink" API — memory watches, notifications, console output, and the Lua-item factory. Backed by EmoTracker.Data.ScriptManager.

Loading other scripts

ScriptHost:LoadScript(path)

Loads and runs another Lua file from your pack. Equivalent to dofile-ing it inside the same Lua state.

  • path (string) — pack-relative path to the script.
ScriptHost:LoadScript("scripts/logic.lua")

Use this instead of Lua's require — EmoTracker doesn't configure the package path to your pack root.

Memory watches (autotracking)

ScriptHost:AddMemoryWatch(name, startAddress, length, callback, period)

Registers a memory watch that polls the given memory region and calls back into your script when the bytes change.

  • name (string) — a label for the watch (used for logging and debugging).
  • startAddress (integer) — the absolute memory address the watch begins at.
  • length (integer) — the number of bytes the watch covers.
  • callback (function) — a Lua function function(segment) ... end invoked each time the runtime detects a change. The segment argument is an IMemorySegment (see below).
  • period (integer, optional, default 1000) — polling period in milliseconds.

Returns the IMemorySegment handle. You can store this and pass it back to RemoveMemoryWatch(...) later, but normally you don't need to — the runtime cleans up automatically when the autotracker stops.

ScriptHost:AddMemoryWatch("Items", 0x7EF340, 0x100, function(segment)
    local sword = segment:ReadUInt8(0x7EF359)
    -- ... update items based on the read ...
    return true
end, 500)

See Authoring Lua — Autotracking for the full pattern.

ScriptHost:RemoveMemoryWatch(segment)

Removes a previously-registered memory watch.

  • segment (IMemorySegment) — the segment handle returned by AddMemoryWatch.

You don't need to call this in normal use — the runtime removes all watches when the autotracker disconnects or the pack unloads.

Notifications

ScriptHost:PushMarkdownNotification(type, markdown, timeout)

Pushes a notification banner with markdown-formatted content into the EmoTracker UI.

  • type (NotificationType)Message, Celebration, Warning, or Error.
  • markdown (string) — markdown text body.
  • timeout (integer, optional, default -1) — how long the notification stays visible, in milliseconds. -1 means "until dismissed".
ScriptHost:PushMarkdownNotification(
    NotificationType.Message,
    "### Welcome\nYour pack has loaded successfully."
)

Useful for surfacing important info to the user — version warnings, autotracker connection status, "you forgot to enable X", etc.

Console output

The runtime reroutes Lua's print(...) to EmoTracker's script output console, but ScriptHost exposes color-coded variants if you want them:

Method Color
ScriptHost:Output(text) dark grey (informational)
ScriptHost:OutputWarning(text) yellow
ScriptHost:OutputError(text) red

These accept a single string argument. The output area is capped at 500 lines; older lines drop off the top.

LuaItem factory

ScriptHost:CreateLuaItem()

Creates and registers a new LuaItem and returns it.

local item = ScriptHost:CreateLuaItem()
item.Name = "My Custom Item"
item.ItemState = { ... }
item.OnLeftClickFunc = function(self) ... end

The created item is automatically added to the item database, so it participates in code lookups, capture pickers, and the save system.


ImageReference

Constructors for image references that you can hand back to other APIs (typically a LuaItem's Icon or PotentialIcon). Backed by EmoTracker.Data.ImageReferenceProvider.

ImageReference:FromPackRelativePath(path, filter)

Loads an image from your pack and optionally applies an image filter spec.

  • path (string) — pack-relative path to the image file (typically a PNG).
  • filter (string, optional) — a filter spec like "grayscale, dim" or "@disabled". See Image Filters for the full syntax.

Returns an ImageReference you can assign to any property that takes one.

item.Icon = ImageReference:FromPackRelativePath("images/items/sword.png")
item.PotentialIcon = ImageReference:FromPackRelativePath("images/items/sword.png", "@disabled")

ImageReference:FromImageReference(existing, filter)

Wraps an existing image reference with an additional filter spec.

  • existing (ImageReference) — an image reference returned by one of the other constructors.
  • filter (string, optional) — a filter spec to apply on top of whatever the existing reference already had.

Returns a new image reference. Returns the original unchanged if the filter is empty/nil.

local base = ImageReference:FromPackRelativePath("images/items/sword.png")
local dimmed = ImageReference:FromImageReference(base, "saturation|0.3, brightness|0.7")

ImageReference:FromLayeredImageReferences(...)

Combines multiple image references into a single layered image, where each layer is drawn on top of the previous one (alpha blended).

  • ... (ImageReference, variadic) — any number of image references to layer.

Returns a single layered ImageReference. Skips any nil arguments.

local layered = ImageReference:FromLayeredImageReferences(
    ImageReference:FromPackRelativePath("images/items/sword.png"),
    ImageReference:FromPackRelativePath("images/badges/used.png")
)

AccessibilityLevel enum

The set of accessibility levels rules can return. Use these as the second return value of a custom access rule function to cap the rule's effective level.

Constant Meaning
AccessibilityLevel.None Inaccessible — rule fails entirely.
AccessibilityLevel.Partial Some sub-elements accessible, others not.
AccessibilityLevel.Inspect Visible/peekable but not actually reachable.
AccessibilityLevel.SequenceBreak Reachable via sequence break / out-of-logic trick.
AccessibilityLevel.Normal Fully accessible (default).
AccessibilityLevel.Cleared Section is fully checked. (Rules don't typically return this; the runtime sets it.)
function some_rule()
    if has("flippers") then
        return 1, AccessibilityLevel.Normal
    elseif has("moonpearl") then
        return 1, AccessibilityLevel.SequenceBreak
    end
    return 0
end

See Map Location Colors for the user-facing meaning of each level.


NotificationType enum

Severity levels for ScriptHost:PushMarkdownNotification.

Constant Meaning
NotificationType.Message Informational.
NotificationType.Celebration Positive / achievement.
NotificationType.Warning Yellow warning.
NotificationType.Error Red error.

IMemorySegment (passed to memory-watch callbacks)

The argument your AddMemoryWatch callback receives. Not a global — you don't construct one yourself, you just receive it from the runtime.

Property / method Description
segment.Name The name you gave the watch.
segment.StartAddress Base address of the watched region (integer).
segment.Length Number of bytes in the watched region (integer).
segment:ReadUInt8(address) Read a single unsigned byte at an absolute address.
segment:ReadInt8(address) Same, but signed.
segment:ReadUInt16(address) Read a 16-bit unsigned word.
segment:ReadInt16(address) Same, but signed.
segment:Freeze() Freezes the segment's bytes (advanced; rarely needed).
segment:Unfreeze() Releases a previous freeze.

The read methods take absolute addresses, not offsets within the segment — pass the same number you'd see in a memory editor or RAM map. The runtime translates to a segment-local offset internally.

function items_callback(segment)
    local sword = segment:ReadUInt8(0x7EF359)
    local bow_state = segment:ReadUInt8(0x7EF38E)
    -- ...
    return true
end

See also

Clone this wiki locally