Abilities and commands¶
Ability lookups accept a case-insensitive display name or an exact current
opaque ability_handle. Ability metadata is local-player-only.
gos.abilities.loadout()¶
Returns the selected local loadout:
{
status = "pending" | "ready" | "unavailable",
action_bar_available = boolean,
action_bar_truncated = boolean,
combat_style = string | nil,
discipline = string | nil,
talents_available = boolean | nil,
known = { [ability_or_active_talent_display_name] = true } | nil
}
The last four fields are present only when status == "ready". known
contains currently owned abilities and active talents. The active talent set includes both selectable choices (for example
Force Mobility) and automatically learned/passive progression rows (for
example Force Shelter). Talents remain distinct from ability metadata
internally: presence in known does not make a passive castable or give it an
ability_handle. Talent discovery is enrichment only; a transient invalid
talent snapshot never makes the owned-ability loadout unavailable.
When talents_available=false, missing talent names are not proof that those
talents are unselected. Action-bar availability is independent of loadout
identity; an empty or incomplete bar does not imply a player-session change.
local loadout = gos.abilities.loadout()
if loadout.status ~= "ready" then
return
end
if loadout.combat_style == "sage" and
loadout.discipline == "Telekinetics" and
loadout.known["Telekinetic Gust"] then
-- Exact current loadout match.
end
Ability Row¶
gos.abilities.action_slots() returns a pure array of current on-bar rows.
Use loadout().action_bar_available and action_bar_truncated to distinguish
a coherent empty bar from missing/incomplete observations.
gos.abilities.info(ability) returns one matching row, including a known
off-bar row, or nil.
{
name = string,
name_source = "client" | "core",
on_bar = boolean,
ability_handle = "ability:..." | nil,
activation_handle = "ability:..." | nil,
slot_index = integer | nil,
key_number = integer | nil,
ready = boolean,
submission_pending = boolean,
has_cooldown_remaining = boolean,
cooldown_remaining = number | nil,
has_cooldown_duration = boolean,
cooldown_duration = number | nil,
has_current_charges = boolean,
current_charges = integer | nil,
has_max_charges = boolean,
max_charges = integer | nil,
has_resource_cost = boolean,
resource_cost = number | nil,
has_line_of_sight_requirement = boolean,
line_of_sight_required = boolean | nil
}
slot_index is zero-based. ability_handle is accepted by ability lookup and
submission functions. activation_handle is for comparing activation and
event identity; do not pass it as the submission ability.
name_source identifies observed client text versus Core-derived display text;
Core text may differ from localized UI spelling. Name-based ability queries prefer the current on-bar group
over historical off-bar rows and reject distinct IDs with the same matching
name within that group. Duplicate bindings of one ID remain valid. Use the
ability_handle for an unambiguous lookup.
Charge and resource fields remain absent until their current observations are available. Do not infer charge counts or costs from timers.
has_line_of_sight_requirement says whether the requirement is known; only then is line_of_sight_required meaningful. This metadata is not a visibility test. Use the cast-readiness result to observe whether line of sight was actually checked.
gos.abilities.info(ability)¶
Returns the matching prepared Ability Row or nil. In addition to the shared
row fields, a returned info row includes metadata_request_status:
| Value | Meaning |
|---|---|
registered |
A metadata request was registered |
pending |
An existing request remains pending |
deferred_capacity |
Request capacity is full; try on a later tick |
satisfied |
The current row satisfies the request |
invalid |
No request can be made in the current context |
Requests are serviced later and are not permanent subscriptions. satisfied
does not prove castability or guarantee every optional field; check has_*
flags and optional values. A known off-bar row can return invalid because
requests currently require an on-bar ability and valid script/player context.
The row is still usable. metadata_request_status belongs only to info(),
not action_slots() rows. Retry pending requests on a later tick.
Readiness Helpers¶
These helpers read prepared local-player observations. Timers use seconds;
nil means the observation is unavailable, rather than a zero timer.
gos.abilities.cooldown_remaining(ability)¶
Returns observed remaining cooldown in seconds, or nil when the ability or
its cooldown observation is unavailable.
gos.abilities.cooldown_duration(ability)¶
Returns observed total cooldown duration in seconds, or nil when the ability
or its duration observation is unavailable.
gos.abilities.gcd_remaining()¶
Returns the local player's observed global cooldown in seconds, or nil when
the snapshot or GCD observation is unavailable.
gos.abilities.is_ready(ability)¶
is_ready() reads the resolved ability row's readiness flag and returns false when the row is unavailable. It does not perform the target-specific validation done by can_cast(). A ready row does not prove target visibility, facing, range or command admission.
gos.abilities.is_casting_or_channeling()¶
Returns the current busy observation as a boolean. It can remain true briefly
while current_cast() is nil because busy state and named cast identity have
different availability. A missing ability snapshot also returns false.
gos.abilities.current_cast()¶
Returns the current cast/channel observation, or nil when its active snapshot
is unavailable:
{
ability_handle = "ability:..." | nil,
name = string,
has_timing = boolean,
remaining = number | nil
}
name is "-" when the display name is unavailable. remaining is in seconds
and is present only when has_timing=true.
gos.abilities.result_codes¶
Stable numeric branch keys returned by can_cast and cast:
{
unknown = 0,
ok = 1,
queued = 2,
missing_target = 3,
missing_ability_name = 4,
ability_not_resolved = 5,
ability_not_found = 6,
ability_not_bound = 7,
cooldown = 8,
gcd = 9,
busy = 10,
ability_command_busy = 11,
ability_command_unavailable = 12,
command_busy = 13,
bad_argument = 14,
cast_unavailable = 15,
no_combat_snapshot = 16,
core_unavailable = 17,
cast_failed = 18,
target_override_failed = 19,
stale_unit = 20,
target_unavailable = 21,
fallback_target_unavailable = 22,
unsupported_target = 23,
ability_metadata_unavailable = 24,
ability_submission_pending = 25,
explicit_target_sync_pending = 26,
explicit_target_sync_suspended = 27,
castability_pending = 28,
castability_unavailable = 29,
ability_disabled = 30,
target_dead = 31,
player_dead = 32,
too_far = 33,
stunned = 34,
not_facing = 35,
insufficient_resource = 36,
target_view_blocked = 37,
too_close = 38,
target_not_dead = 39,
target_untargetable = 40,
incapacitated = 41
}
Branch on code, not the explanatory reason string.
Ability Result¶
can_cast and cast return a common result table. Optional fields appear only
when relevant:
{
ok = boolean,
code = integer,
reason = string,
wait_ms = integer,
client_check_available = boolean,
client_eff_result = integer | nil,
client_los_checked = boolean,
client_request_capacity_deferred = boolean,
blocker = table | nil,
lifecycle_capture_lost = boolean,
lifecycle_unavailable_mask = integer,
command_admission_blocked = boolean,
target_valid = boolean,
target_override = boolean,
target_mode = "none" | "selected" | "explicit" | "selected_fallback",
target_fallback = "none" | "selected",
fallback_used = boolean,
fallback_reason = string | nil,
requested_target_handle = "unit:..." | nil,
target_handle = "unit:..." | nil,
dry_run = boolean,
name = string | nil,
ability_handle = "ability:..." | nil,
on_bar = boolean | nil,
submission_pending = boolean | nil,
cooldown_remaining = number | nil,
cooldown_duration = number | nil,
gcd_duration = number | nil,
uses_global_cooldown = boolean | nil,
has_resource_cost = boolean | nil,
resource_cost = number | nil,
has_line_of_sight_requirement = boolean | nil,
line_of_sight_required = boolean | nil,
gcd_remaining = number | nil,
busy = boolean | nil,
current_cast_name = string | nil,
current_cast_has_timing = boolean | nil,
current_cast_remaining = number | nil,
command_handle = "ability_command:..." | nil,
command_state = string | nil
}
wait_ms reports only a currently known cooldown, applicable global cooldown,
or busy wait. Core consults the global GCD only when exact ability metadata says
that ability has a positive GCD duration; off-GCD abilities remain eligible while
the global GCD is active. Cast/channel busy remains a separate conservative gate.
It is not a future scheduling promise. Shared client admission additionally
checks modified resource costs, minimum/maximum range, the client's facing
gate/cone, ordinary unit target death and attackability, ability enabled state,
caster death/stun/incapacitation with ability exceptions, and gated character LOS.
Readiness is a current local observation, not a promise of game acceptance. castability_pending and castability_unavailable do not acquire a command; retry on a later tick or evaluate another action. Do not turn transient blocked results into a permanent target blacklist.
lifecycle_capture_lost reports lost lifecycle observations. lifecycle_unavailable_mask is opaque availability metadata, not a documented bit layout; do not decode it or infer success from it. Preserve unavailable outcomes and rely on the public result code and command status.
client_check_available distinguishes a completed local check from missing context. client_los_checked reports whether line of sight was checked. client_eff_result is optional rejection metadata; branch on the public code. Ability-specific rules may still reject a submitted action.
client_request_capacity_deferred indicates that the bounded client-check request capacity deferred this observation. It does not mean the target is invalid or the ability failed. Retry on a later bounded tick rather than spinning; it is distinct from metadata_request_status on an info row. blocker is optional diagnostic-only metadata; its internal keys and numeric values are not a stable public contract. Use the documented result code and command ownership instead.
The built-in Line of sight and Targeting you overlays are visual features; they add no Lua query methods or unit fields. A clear visual line does not report another player's ability readiness or replace can_cast() and command status.
Target and readiness semantics¶
can_cast() answers ready now, not may be queued for later. cast() with an omitted target may be admitted to the normal command queue while a cast or GCD is still finishing; acceptance is not guaranteed. Consequently, requiring can_cast().ok before every such submission is a conservative policy that can prevent otherwise valid prequeueing.
An explicit unit or handle uses ready-now admission, including when that unit currently equals the selected target. It therefore has different prequeue behavior from an omitted target. Changing selection or adding a fallback does not preserve the same explicit-target contract.
Malformed target handles, wrong argument types and unknown cast-option keys raise Lua errors. A well-formed but unresolved explicit handle instead produces a result with code target_unavailable; stale unit targets produce code stale_unit. These are ability result codes, distinct from a stale unit method raising an error. An unhandled Lua error disables the callback until reload.
gos.abilities.can_cast(ability, target?)¶
Checks current readiness and supported local conditions. Abilities requiring no external target can be checked without one and report target_mode="none". Other omitted targets use the captured selection. An explicit target is a current GosUnit or its opaque handle and is never silently converted to targetless mode.
local world = gos.world()
if not world.current_target then return end
local readiness = gos.abilities.can_cast("Force Stun", world.current_target)
if readiness.ok then
-- Ready according to the current local snapshot.
end
gos.abilities.cast(ability, target?, options?)¶
Submits one asynchronous command. An explicit target may be a current GosUnit or an opaque unit handle. By default this does not persistently change the visible selected target. Use gos.target.select separately when a persistent selection change is intended.
With no target, targetless abilities need no external unit; other abilities use the selected target at dispatch. A queued command is not activation proof. Let the command status report progress rather than repeatedly submitting the same action.
Supported options:
{
target_fallback = "none" | "selected", -- explicit targets only
replace_command = "ability_command:..." -- only when replacement_allowed
}
target_fallback defaults to none. Selected fallback is opt-in and applies
only when an explicit target cannot be used before the command is queued. Supplying this option, even as "none", with an omitted/nil target raises a Lua error. Omit the option to use its no-fallback default.
ok=true with code == gos.abilities.result_codes.queued means Core accepted
the command for asynchronous processing. It does not mean the ability began.
Retain command_handle and poll command_status. Release ownership only when
terminal=true and cleanup_pending=false.
After polling the retained command in the owning callback, submit only when it has cleared:
if pending_command then return end
local target = gos.world().current_target
if not target then return end
local result = gos.abilities.cast("Force Stun", target, {
target_fallback = "none",
})
if result.ok then
pending_command = result.command_handle
end
Only one nonterminal command may be owned at a time. If a submission returns
ability_command_busy, use the returned command handle/status instead of
submitting repeatedly.
gos.abilities.command_status(command_handle)¶
Returns the stable public command state:
{
known = boolean,
state = "unknown" | "queued" | "dispatching" | "dispatched" | "native_queued" |
"accepted" | "targeting" | "synchronizing" | "submitted" |
"acknowledged" | "failed" | "superseded" | "cancelled" | "abandoned" | "expired",
terminal = boolean,
acknowledged = boolean,
activation_proven = boolean,
cleanup_pending = boolean,
game_result_known = boolean,
invocation_started = boolean,
invocation_exited = boolean,
invocation_returned = boolean,
callback_completed = boolean,
game_result = integer,
game_result_name = string,
game_result_source = "activation_return" | "server_result" | "server_notification" | "",
replacement_allowed = boolean,
reason = string,
command_handle = "ability_command:..." | nil,
retained_command_handle = "ability_command:..." | nil,
name = string | nil,
target_mode = "none" | "selected" | "explicit" | "selected_fallback",
target_fallback = "none" | "selected",
fallback_used = boolean,
fallback_reason = string | nil,
requested_target_handle = "unit:..." | nil,
target_override_applied = boolean,
target_restore_attempted = boolean,
target_restore_succeeded = boolean
}
Use terminal to detect lifecycle completion and cleanup_pending to retain
ownership until target cleanup finishes. Neither means the ability succeeded.
activation_proven and acknowledged report positive start evidence.
dispatching means native dispatch is in progress. superseded is terminal:
other work or a changed player/ability context overtook the command. A terminal
submitted status can have activation_proven=false: Core observed submission,
but has no start proof. Missing proof alone is not permission to replay it.
Retained terminal receipts may acquire later outcome information.
game_result_known distinguishes a captured game result from missing data;
use game_result_name for display. game_result_source distinguishes an
immediate activation return from a later server result or notification.
Invocation fields describe transport progress only: invocation_started
records entry, invocation_exited records exit including exceptions,
invocation_returned records a normal return, and callback_completed records
completion of the owning callback. Target override/restore flags likewise
describe target handling, rather than ability activation.
A finished receipt evicted from the 64-record command history returns known=true, terminal=true, state="expired", reason="command_history_expired". This releases ownership without inventing an activation or failure outcome; missing outcome flags on that tombstone are not negative gameplay evidence. An unrecognized handle remains unknown. Handles do not survive Core restart/load.
if pending_command then
local status = gos.abilities.command_status(pending_command)
if status.known and status.terminal and not status.cleanup_pending then
pending_command = nil
end
end
When replacement_allowed=true, submit a replacement with
replace_command=status.command_handle. A successful replacement returns a new
command handle. Only replace a command owned by this script instance: reading a
known status or seeing replacement_allowed=true does not grant ownership of
another script's command.
gos.abilities.release_command(command_handle)¶
Requests safe cancellation of this script instance's command and returns the command-status fields plus ok. A readable handle is not an ownership grant: another script's retained command returns ok=false, with reason="foreign_command_owner", even when its status is otherwise known.
ok=true means the command was cancelled before dispatch or was already cancelled. It does not stop an ability that has already begun. A dispatched command that cannot be cancelled, an unknown handle, or an already-terminal non-cancelled command returns ok=false; inspect known, terminal, cleanup_pending and the outcome instead of treating every false result as an active command.
gos.abilities.abandon_command(command_handle)¶
Compatibility endpoint returning command-status fields plus ok. It does not change a command: ok=true requires a retained command owned by this script instance that is already terminal. Foreign, unknown, evicted, or in-flight commands return ok=false, including an otherwise known expired-history tombstone. It does not drop an in-flight command or bypass cleanup. New scripts should retain and resolve command ownership instead of abandoning it.