Skip to content

Ability helpers

Top-level shortcuts for asking about an ability by name or by id, without fetching the ability object first.

These sit directly on mq.TLO, not under Me. They are the fast path for the question a rotation actually asks — "can I cast this right now" — and avoid building an ability table per check.

Forms

number GetAbilityID(name)

The raw ability id for name. 0 if not found.

bool AbilityReady(name)

Is the named ability off recast?

number AbilityRecastRemaining(name)

Seconds left on the named ability's recast. 0 when ready.

bool AbilityReadyID(id)

Same as AbilityReady, by raw ability id.

number AbilityRecastRemainingID(id)

Same as AbilityRecastRemaining, by raw ability id.

bool AbilityCacheReady

Has the local ability-name cache finished warming?

table AbilityCacheProgress

{ Done, Total } — warm-up progress.

bool HaveMaintainedIcon(mainIcon, backdropIcon)

Is an effect with this icon pair on your maintained bar?

bool HaveDetrimentalIcon(mainIcon, backdropIcon)

Is an effect with this icon pair on your detriment bar?

Usage

if mq.TLO.AbilityReady("Fireball") then
  eq2.cmd('/useability "Fireball"')
end

Names resolve through a cache that warms asynchronously

Ability names are not available the instant you log in — the client fetches them, and clockwork caches what it sees. Until that cache is warm, a by-name lookup can miss an ability you definitely know.

Everything here fails soft, which means a cold cache and a genuinely-unknown ability look identical: GetAbilityID() returns 0 and AbilityReady() returns false. A rotation that starts casting immediately on login will appear to have forgotten half its abilities.

Wait for the cache before treating a miss as real:

while not mq.TLO.AbilityCacheReady() do
  local p = mq.TLO.AbilityCacheProgress()
  eq2.print(("warming abilities %d/%d"):format(p.Done, p.Total))
  eq2.delay(1000)
end

Once warm, resolve names to ids once and use the ...ID forms in your hot loop — it skips the name lookup on every call:

local id = mq.TLO.GetAbilityID("Fireball")
if id == 0 then eq2.print("don't know Fireball") return end

while true do
  if mq.TLO.AbilityReadyID(id) then eq2.cmd('/useability "Fireball"') end
  eq2.delay(250)
end

"Ready" is not "castable"

AbilityReady() means no recast is ticking. It does not check power, range, line of sight, stance, or whether the ability is actually slotted.

A never-castable ability starves everything below it

An ability that can never fire never starts a recast, so it reads as permanently ready. A rotation that walks rows top-down and casts the first ready one will stop at that row forever and never reach the rest.

A rotation that "stopped working" after a respec or an unslotted advantage is almost always this. See ability.IsReady().

Icon-pair checks

HaveMaintainedIcon / HaveDetrimentalIcon are the low-level layer under Me.Buff(name). Prefer the by-name form unless you already have icon ids in hand — for example, from an effect you pulled off a bar:

local ab = mq.TLO.Me.Ability("Aura of Void")
if ab and not mq.TLO.HaveMaintainedIcon(ab.MainIconID(), ab.BackDropIconID()) then
  eq2.cmd('/useability "Aura of Void"')
end

See also