-
Notifications
You must be signed in to change notification settings - Fork 8
Authoring Lua
This page is the top of the Lua scripting hierarchy for pack authors. It explains what scripts can do, how the runtime hosts them, the global objects EmoTracker exposes, and the security model. Then it links out to the per-topic sub-pages for everything that needs more space.
New to pack authoring? Read Developer Setup first to install a Lua language server in VS Code, then Authoring Items, Authoring Locations, and Authoring Layouts to get familiar with the data sides of a pack — Lua sits on top of all three.
Most of a pack is data: items, locations, layouts, and maps declared in JSON. Lua handles everything that can't be expressed declaratively:
-
Bootstrapping the pack. The runtime calls a single
scripts/init.luafile when your pack loads, and it's your script's job from there to call back into the engine to register items, locations, layouts, and maps. -
Custom access logic. Some checks are too complex for plain code requirements — multi-step routes, conditional dungeon entrances, runtime settings — and need a function rather than a static rule. The
$prefix in access rules drops down into Lua. - Autotracking. When the user has the autotracker connected, the runtime hands you raw memory bytes from the running game. A Lua callback turns those bytes into item state changes.
- Reactive callbacks. EmoTracker calls a handful of well-known function names automatically when major events happen (pack ready, accessibility refreshed, save loaded, autotracker connected). You implement the ones you need.
-
Dynamic items. When none of the built-in item types fit, you can build a fully scripted item via
ScriptHost:CreateLuaItem().
Every pack that uses Lua has a scripts/init.lua at its root. The runtime runs this file once when the pack loads, after items / locations / layouts are available to register but before any of them are loaded. Your init script is responsible for choosing what to register, in what order.
→ See Authoring Lua — init.lua for the full pattern, ordering rules, and variant detection.
EmoTracker hosts your scripts via NLua running an embedded Lua 5.x interpreter. The environment is a slightly restricted standard Lua:
-
Standard library is mostly available —
string,math,table,coroutine,os(with restrictions), etc. -
iois removed entirely unless your pack is flagged asUnsafe. Scripts cannot read or write arbitrary files on the user's disk. -
os.execute,os.exit,os.setlocaleare always removed even for unsafe packs. os.tmpname,os.rename,os.getenv,os.removeare removed unless the pack is flagged unsafe.-
importis a no-op. It's stubbed out so scripts that come from an environment expecting it don't break. -
printis rewired to write to EmoTracker's script console (the same one you see in the developer view) instead of stdout.
If your pack genuinely needs filesystem access (e.g. for cached state), you have to set enable_unsafe_scripting: true in its manifest.json. Doing so triggers a warning icon in the Package Manager and discourages most users from installing it — only do this if there's no alternative.
When the runtime constructs the Lua environment, it injects six global names that give you access to EmoTracker's machinery. The full reference for each lives on Authoring Lua — API Reference; the short version:
| Global | Type | What it's for |
|---|---|---|
Tracker |
object | The main entry point — register items/locations/layouts/maps, look up codes, query active variant, etc. |
AutoTracker |
object | Memory-read API for autotracking. Only meaningful when an autotracking provider is connected. |
Layout |
object | Find loaded layouts and registered layout elements by name. |
ScriptHost |
object | Memory watch registration, notifications, console output, and Lua-item creation. |
ImageReference |
object | Construct image references (with optional filters / layering) you can hand back to other APIs. |
AccessibilityLevel |
enum | The set of accessibility levels that custom-logic functions can return. Has constants like AccessibilityLevel.Normal, .SequenceBreak, .Inspect. |
NotificationType |
enum | Notification severity levels for ScriptHost:PushMarkdownNotification. Has constants Message, Celebration, Warning, Error. |
These globals are set up before init.lua runs, so you can use them from line one of your script.
EmoTracker reroutes Lua's print(...) so that anything you print goes to the Script Output view inside the developer console, not to a real stdout. This view is shown in EmoTracker's developer mode and is the primary way to debug your scripts at runtime.
You can also call into ScriptHost directly for color-coded output:
print("normal output") -- printed in the standard color
ScriptHost:Output("dim status line") -- dark grey
ScriptHost:OutputWarning("warning") -- yellow
ScriptHost:OutputError("error") -- redThe output area is capped at 500 lines; older lines drop off the top.
The deeper topics each get their own page:
| Topic | Sub-page |
|---|---|
Writing your scripts/init.lua and managing load order |
init.lua |
| Standard callback functions the runtime invokes by name | Standard Callbacks |
$-prefixed Lua functions used as custom access rules |
Custom Access Rules |
| Adding autotracking to a pack via Lua | Autotracking |
Building fully-scripted items with LuaItem
|
Lua Items |
Full reference for Tracker, AutoTracker, Layout, ScriptHost, and ImageReference
|
API Reference |
- Developer Setup — tools, Lua learning resources, schema validation
- Authoring Items — item JSON files, which scripts typically register first
-
Authoring Locations — location JSON files, including the
$prefix for Lua access rules - Authoring Layouts — layout JSON files
- Hosting a Package Repository — publishing your finished pack
- 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