Jump to content
Toggle menu
Toggle preferences menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.

Add-ons/SotA Event System (SES)/Developer API

From Shroud of the Avatar Wiki - SotA

Developer API

The SotA Event System exposes a global SES table for subscribing, publishing, ordering, replaying, and removing callbacks. Add sota-event-system-ses-addon to the package's dependencies before using it.[1]

Subscribe and unsubscribe

local function onGoldChanged(currentGold, previousGold)
  -- update this add-on's own state
end

local subscription = SES.on("ShroudOnGoldChanged", onGoldChanged)
SES.off("ShroudOnGoldChanged", subscription)

SES.on(eventName, callback, opts) returns a subscription index. SES.off accepts that index, the original function reference, or no second argument to remove all callbacks for the event. SES.once has the same options but removes its wrapper before the first callback runs, so recursively invoking the event cannot fire it twice.

SES.hasSubscribers(eventName) reports whether at least one live callback remains. SES.mute(eventName) and SES.unmute(eventName) suppress and restore dispatch for that event.

Publish custom events

SES.invoke("ExampleAddon.onReady", packageId, version)

Any add-on can publish a custom name with arbitrary Lua arguments. Namespace custom events with the producer's package or project name. A subscriber failure is protected by pcall and logged without stopping the other subscribers.[1]

Custom events are in-process communication, not network messages. They disappear when the Lua session ends unless a producer publishes them again or a subscriber uses a replayed payload still cached in the current session.

Replay late announcements

SES.on("ExampleAddon.onReady", receiveReady, { replayLast = true })

replayLast immediately delivers the most recent payload when it exists. For discovery events with several independent producers, use replayLastPerSender; SES keys the cache by the string form of the first event argument and retains 32 senders by default:

SES.on("ExampleAddon.onLibrary", receiveLibrary,
  { replayLastPerSender = true })

An event can request a larger cache with replayLastPerSenderCap. Choose a stable unique first argument, as POIS and PQS libraries do. Reusing it replaces that sender's cached announcement.[1]

Ordering callbacks

Handlers dispatch through early, normal, then late tiers. Registration order applies within a tier unless named after or before constraints say otherwise.

SES.on("ExampleAddon.onUpdate", prepare, {
  tier = "early", name = "Prepare"
})
SES.on("ExampleAddon.onUpdate", render, {
  tier = "early", name = "Render", after = "Prepare"
})

Names and ordering constraints apply within the same event and tier. after and before may be one name or an array. SES warns about dependency cycles and falls back safely rather than dropping callbacks.

Key and sound helpers

Subscribe to ShroudOnKeyDown_<key> or ShroudOnKeyUp_<key>. For a chord, put held keys before the triggering key, such as ShroudOnKeyDown_LeftControl+Space. SES watches only keys that have subscribers.

SES.sound.watch(instanceId, soundName, channel) observes a channel returned by the add-on's own sound playback and emits ShroudOnSoundStarted and ShroudOnSoundStopped. unwatch stops observation without stopping the sound; isPlaying returns SES's last known state. SES itself never plays or stops the sound.[1]

Runtime configuration

Polling intervals and beacon-arrival distance are exposed through SES.config. Changing them affects every consumer in the shared session, so a library should not retune global values casually. Prefer the defaults unless the add-on family controls and documents the whole deployment.

References

  1. ↑ 1.0 1.1 1.2 1.3 Community Addons: approved SES 1.45.1 package, reviewed October 13, 2026.

See also

Page verification: Unverified · This page could use a check