Skip to content

Tier 2 — Data

Read-only accessors over EMS state. Each returns a copy or a scalar, so nothing you receive aliases live engine data. There are no setters here — you read state, you don't write it.

API:GetSequenceList()

for _, s in ipairs(API:GetSequenceList()) do
    print(s.name, s.currentStep .. "/" .. s.stepCount, s.stepFunction)
end

Returns an array of summaries for the active sequences, sorted by name. Each entry:

Field Type Meaning
name string sequence name
stepCount number how many steps the button actually cycles through -- the execution count. Equals #GetSequenceSteps(name), and is the correct denominator for currentStep.
currentStep number step the sequence is currently on (1 when idle)
stepFunction string active version's step-function id (e.g. "Sequential")

Two step counts, two meanings

stepCount here is the execution count: the length of the expanded array the secure button cycles through. GetSequenceInfo's activeStepCount is the compiled count: the length of the flat step array the active version compiles to before the step function expands it. They are equal for Sequential and Random, and they differ for Priority, ReversePriority, and any registered step-function expander -- a 4-step Priority sequence has a compiled count of 4 and an execution count of 10, because Priority pre-expands [A,B,C,D] into [A, A,B, A,B,C, A,B,C,D]. Pair currentStep with stepCount; never with activeStepCount.

Neither field is the authored count. A sequence is authored as an action tree, and compiling it inserts interleave copies, unrolls loops, and applies the version's repeat count -- so activeStepCount can exceed the number of steps the user actually wrote. The authored base order is available via API:GetAuthoredSteps(name); the authored tree itself -- intervals, Loop repeat counts, and IF branches -- is still not exposed.

This is the lightweight listing view. For richer per-sequence metadata, call GetSequenceInfo.

API:GetSequenceInfo(name)

local info = API:GetSequenceInfo("My Rotation")
if info then
    print(info.versionCount, "version(s), active is", info.activeVersionIndex)
end

Returns a metadata snapshot for one sequence, or nil when no sequence by that name is active. Every field is a scalar or a fresh copy, so nothing you get back aliases stored data:

Field Type Meaning
name string sequence name
stepFunction string | nil active version's step-function id
versionCount number how many versions the sequence has
defaultVersion number | nil the default version index
activeVersionIndex number | nil version resolved under the current context
activeStepCount number how many steps the active version compiles to, before the step function expands them. For an expanding step function this is smaller than GetSequenceList's stepCount -- see the note above. Not the same as the number of steps the user authored: compiling inserts interleave copies, unrolls loops, and applies the version's repeat count.
contextVersionCount number versions tracked for context resolution
classID number | nil class the sequence is tagged to, if any
specID number | nil spec the sequence is tagged to, if any
author string | nil the sequence's author, if set
description string | nil the sequence's description, if set
help string | nil the sequence's help text, if set
helplink string | nil the sequence's help link, if set
changelog string | nil the sequence's change notes, if set
talentString string | nil the sequence's talent import code, if set
url string | nil the sequence's source URL, if set
privacyMode string | nil the privacy mode stamped on the sequence
version number | nil the sequence's stored version number
createdAt number | nil creation timestamp
updatedAt number | nil last-modified timestamp
disabled boolean whether the sequence is disabled
keybind string | nil the key bound to the sequence, or nil if unbound
variableDeps table fresh sorted array of variable names the sequence depends on

There's no separate "active version" accessor — activeVersionIndex already carries the index the current context resolves to. The richer fields (author, description, keybind, variableDeps, and the timestamps) are what a metadata or about panel reads; v1 returned only the first seven.

API:GetSequenceSteps(name)

local steps = API:GetSequenceSteps("My Rotation")
if steps then
    for _, s in ipairs(steps) do
        print(s.index, s.spellID, s.spellName, s.icon)
    end
end

Returns an array of the active version's steps, or nil when no sequence by that name is active. Each entry is a fresh table of public scalars — a spell's id, name, and icon are public data, never secret the way a unit's health is, so nothing here aliases engine state or carries a taint risk:

Field Type Meaning
index number the step's position, 1-based
spellID number | nil the step's resolved spell id, or nil for a step that isn't a single spell
spellName string | nil the spell name, when one resolves
icon number | nil the spell's icon texture id, for a button face

This is the per-step view an action-bar plugin draws chrome from. Pair it with the SEQUENCE_STEP_ADVANCED event, which hands your handler (seqName, step, numSteps), to know which entry is live, then call C_Spell.GetSpellCooldown yourself for the swipe and glow. EMS resolves the ids through the same path the engine compiles from, so they match what the sequence actually casts. The action-bar plugin guide walks through the whole flow.

API:GetAuthoredSteps(name)

-- Presence check: GetAuthoredSteps arrived in EMS 2.3.7 and API_VERSION
-- did not change, so RequireVersion cannot tell you it is there.
if API.GetAuthoredSteps then
    local steps = API:GetAuthoredSteps("My Rotation")
    if steps then
        for _, s in ipairs(steps) do
            print(s.index, s.spellID, s.spellName, s.icon)
        end
    end
end

Added in EMS 2.3.7 -- check for it before you call it

API_VERSION is still 3: this accessor is an additive change, and the contract only bumps on a breaking one. The stepdata capability predates it too. That means neither RequireVersion(3) nor the capability list can tell you whether this build has GetAuthoredSteps -- both answer yes on EMS 2.3.6, where it is nil. Test for the method itself: if API.GetAuthoredSteps then ... end. Reading a key the API does not have returns nil rather than raising, so the check is safe on any build.

Returns the active version's steps in authored base order — the order the user actually wrote, before the step function expands the sequence and before interleave copies are inserted — or nil when no sequence by that name is active. Each entry is the same fresh table of public scalars GetSequenceSteps returns, so nothing here aliases engine state or carries a taint risk:

Field Type Meaning
index number the step's position in authored order, 1-based
spellID number | nil the step's resolved spell id, or nil for a step that isn't a single spell
spellName string | nil the spell name, when one resolves
icon number | nil the spell's icon texture id, for a button face

This is the authored domain, and it is deliberately kept distinct from the execution domain GetSequenceSteps returns. Its indices do not line up with currentStep or the step index SEQUENCE_STEP_ADVANCED hands your handler — those live in the execution domain, where the step function has already expanded the array. Use GetSequenceSteps when you need to track the live step; use this when you want the base order the user built.

Two limits keep this a flat base order rather than the action tree: a Loop is unrolled — a Loop with repeat 3 contributes its children three times — and an IF branch is flattened. The version's own repeat count is not applied, and interleave copies are suppressed, so a plugin reading per-spell frequency sees each authored spell once instead of the interleave-inflated count GetSequenceInfo's activeStepCount carries.

API:GetSequenceMacroIndex(name)

local index = API:GetSequenceMacroIndex("My Rotation")
if index then
    PickupMacro(index)  -- now drag it onto an action bar
end

Returns the macro slot index of the sequence's action-bar macro, or nil when no macro exists for it yet. Read-only — it never creates anything. To make sure a macro exists first, use the authoring-tier handle:EnsureSequenceMacro, then read or pick up the index.

A sequence's macro is a standard WoW macro EMS maintains, so it's draggable and PickupMacro-able with no taint. It's also capped at 255 characters and runs in the default environment, so it's a simplified stand-in for the sequence — enough for many rotations, but it doesn't carry the full engine the keybind runs.

API:GetCurrentContext()

local ctx = API:GetCurrentContext()  -- "none", "Raid", "MythicPlusHigh", "Arena", ...

Returns the content context EMS has detected, as a string key. It's "none" outside any recognized context. The full set of keys is internal and can grow between patches, so treat unknown values as "some context I don't handle" rather than switching exhaustively on it.

Context isn't a public event — to react to a change, poll this on the lifecycle events you already handle, or read it when you need it.

API:GetSetting(key)

local layout = API:GetSetting("uiLayout")  -- "classic" | "modern" | nil

Returns the value of an allowlisted setting, or nil for anything off the allowlist. The allowlist is deliberately small and scalar-valued:

Key Type Meaning
uiLayout string | nil active layout-provider id; nil before one is stored
debug boolean whether EMS debug logging is on

There's no setter. If you need visibility into a setting that isn't allowlisted, subscribe to SETTING_CHANGED — it broadcasts every changed key and value, so you can watch for the one you care about.

API:GetRegisteredPlugins()

for _, p in ipairs(API:GetRegisteredPlugins()) do
    print(p.name, p.version, p.loaded, p.sequenceCount)
end

Returns an array of records for plugins that have registered sequences through the addon registry:

Field Type Meaning
name string plugin name
version string plugin version as registered
loaded boolean whether its sequences are loaded into the engine
sequenceCount number how many sequences it registered