Reference › Function reference › Platform

Platform.casting.GetUnitCastObservation

public

Call as

addon.Platform:GetUnitCastObservation(unit, kind)

Available directly through addon; no dependency is needed.

What it does

Observe a unit casting or channeling on probe- and restricted-policy clients. A known absent unit or a readable inactive result returns active=false. Active records contain name, or nameReason when the name is secret (the unit is still casting), and independently available remainingSeconds, durationSeconds, interruptible and spellID fields, with remainingReason, durationReason, interruptibleReason or spellReason when an optional field is unavailable. Missing, failed or restricted presence observations return nil with a reason.

Arguments

NameTypeWhat it does
selfRMPlatformRotation Master platform adapter (implicit with colon calls).
unitstringUnit token whose current cast or channel should be observed.
kindstringObservation kind: cast or channel. These use different native interruptibility tuple positions.

Returns

1table | nilFresh readable record with active, then name or nameReason, remainingSeconds, durationSeconds, interruptible and spellID. Remaining time and duration are in seconds; remaining time is clamped to zero. An unavailable optional field has its own reason; it does not invalidate an active record.
2string | nilAvailability or query-validation reason when the whole observation is unavailable.

Editions

Built In helpers are registered on every edition. What differs is the game API they read; where one is missing the helper falls back or returns nil with a reason.

  • Not available on that edition (the reason is in the tooltip)
  • Only while Blizzard's deprecation fallbacks are on
Game APIClassic EraTBC AnniversaryClassic progressionForeverRetail
UnitCastingInfoClassic EraTBC AnniversaryClassic progressionForeverRetail
UnitChannelInfoClassic EraTBC AnniversaryClassic progressionForeverRetail
UnitExistsClassic EraTBC AnniversaryClassic progressionForeverRetail

Secret values (Retail and Forever)

On Retail and Forever the game hands addons secret values. This helper checks what it reads (addon.Platform:CanReadValue) and returns nil with a reason such as restricted-value instead of a secret it cannot compare. Treat nil as unavailable, not as false.

Example

local cast = addon.Platform:GetUnitCastObservation("target", "cast")
if not cast then return nil end
if not cast.active then return false end
if cast.interruptible == nil or cast.remainingSeconds == nil then return nil end
return cast.interruptible and cast.remainingSeconds > 0.5

Dependencies

Source

Platform/casting.lua, line 82. Read only in game; Duplicate makes an editable copy.

Platform.casting.GetUnitCastObservation(self, unit, kind)
    local policy=self:GetCombatDataPolicy()
    if policy~='probe' and policy~='restricted' then return nil,'unsupported-policy' end
    if not self:CanReadValue(unit) or not self:CanReadValue(kind) then return nil,'restricted-value' end
    if type(unit)~='string' or unit=='' then return nil,'invalid-unit' end
    if kind~='cast' and kind~='channel' then return nil,'invalid-cast-query' end
    if type(UnitExists)~='function' then return nil,'missing-api' end
    local existsOk,exists=pcall(UnitExists,unit)
    if not existsOk then return nil,'api-error' end
    if not self:CanReadValue(exists) then return nil,'restricted-value' end
    if exists==nil then return nil,'unit-data-unavailable' end
    if type(exists)~='boolean' then return nil,'invalid-api-result' end
    if not exists then return {active=false} end
    local fn
    if kind=='cast' then fn=UnitCastingInfo else fn=UnitChannelInfo end
    if type(fn)~='function' then return nil,'missing-api' end
    -- Capture into an owned tuple table without comparing native values. The
    -- channel flag is slot7; casting includes castID and uses slot8 instead,
    -- so the spell ID is slot9 for a cast and slot8 for a channel.
    local ok,tuple=pcall(function() return {fn(unit)} end)
    if not ok then return nil,'api-error' end
    local name=tuple[1]
    local record
    if not self:CanReadValue(name) then
        -- Retail and Forever make cast fields secret for a unit other than the
        -- player or pet unless the spell is flagged never secret
        -- (SecretWhenUnitSpellCastRestricted). A secret is a value, never nil:
        -- the unit is casting, and only the name is hidden.
        record={active=true,nameReason='restricted-value'}
    else
        if name==nil then return {active=false} end
        if type(name)~='string' or name=='' then return nil,'invalid-api-result' end
        record={active=true,name=name}
    end
    record.remainingSeconds,record.remainingReason=remainingSeconds(tuple[5])
    record.durationSeconds,record.durationReason=durationSeconds(tuple[4],tuple[5])
    record.interruptible,record.interruptibleReason=interruptibility(tuple[kind=='cast' and 8 or 7])
    record.spellID,record.spellReason=spellIdentity(tuple[kind=='cast' and 9 or 8])
    return record

Back to Function reference