Violet

Link Skills

On this page

The core.link_skills module lets scripts inspect the character's three Link Skill presets, assign or unassign one skill on the active preset, and activate another preset.

Return conventions

Read functions return their value directly. When Link Skills are unavailable or an argument is invalid, they return nil, error_message.

lua
local preset, err = core.link_skills.get_active_preset()
if preset == nil then
    core.log("Unable to read Link Skills: " .. err)
    return
end

Actions return true when the request is sent, or false, error_message when it cannot be sent safely.

lua
local ok, err = core.link_skills.assign(
    core.link_skills.skills.WILD_RAGE
)
if not ok then
    core.log("Unable to assign Link Skill: " .. err)
end
Requests change live character data

Assigning, unassigning, and activating a preset are real actions. A true result means the client sent the request, not that the server accepted it. Send one mutation at a time and confirm it by reading the state on a later on_tick; an immediate read may still show the previous state.

The server can reject a skill the account does not own or a change disallowed by the current game state.

Presets and slots

Preset indices use the game's zero-based values:

Lua presetIn-game label
0Preset 1
1Preset 2
2Preset 3

Use preset + 1 when displaying an in-game preset number. Each preset holds at most 12 skills. Arrays returned by get_assigned() are ordinary sequential Lua arrays, so their slot indices begin at 1.

Skill constants

The canonical assignable IDs are available as a convenience catalog under core.link_skills.skills. Prefer these constants over numeric literals. The table is not an enforced whitelist: assign() and unassign() accept any positive signed 32-bit ID, while the server remains authoritative about whether an ID is a valid, owned Link Skill.

ConstantSkill IDDisplay name
FURY_UNLEASHED80000001Fury Unleashed
PHANTOM_INSTINCT80000002Phantom Instinct
MOONLIT_BLADE_LEARNINGS80000003Moonlit Blade Learnings
ELEMENTALISM80000004Elementalism
LIGHT_WASH80000005Light Wash
IRON_WILL80000006Iron Will
HYBRID_LOGIC80000047Hybrid Logic
WILD_RAGE80000050Wild Rage
CYGNUS_BLESSING80000055Cygnus Blessing
RHINNES_BLESSING80000110Rhinne's Blessing
CLOSE_CALL80000169Close Call
JUDGMENT80000188Judgment
UNFAIR_ADVANTAGE80000261Unfair Advantage
TIDE_OF_BATTLE80000268Tide of Battle
SPIRIT_OF_FREEDOM80000329Spirit of Freedom
RUNE_PERSISTENCE80000369Rune Persistence
COMBO_KILL_BLESSING80000370Combo Kill Blessing
SOLUS80000514Solus
BRAVADO80000609Bravado
ELVEN_BLESSING80001040Elven Blessing
KNIGHTS_WATCH80001140Knight's Watch
TERMS_AND_CONDITIONS80001155Terms and Conditions
INVINCIBLE_BELIEF80002758Invincible Belief
EMPIRICAL_KNOWLEDGE80002762Empirical Knowledge
ADVENTURERS_CURIOSITY80002766Adventurer's Curiosity
THIEFS_CUNNING80002770Thief's Cunning
PIRATE_BLESSING80002774Pirate Blessing
NOBLESSE80002857Noblesse
TIME_TO_PREPARE80003015Time to Prepare
NATURES_FRIEND80003058Nature's Friend
INNATE_GIFT80003224Innate Gift
GROUNDED_BODY80003877Grounded Body
FOCUS_SPIRIT80010006Focus Spirit
GUIDING_STARS80010486Guiding Stars
QI_CULTIVATION80011964Qi Cultivation

Sia's source skill 80010343 and Erel's source skill 80010473 are normalized by the supported client build to the shared assignable GUIDING_STARS ID 80010486.

Returns the active zero-based preset index (0, 1, or 2).

lua
local preset, err = core.link_skills.get_active_preset()
if preset ~= nil then
    core.log("Active Link Skill preset: " .. (preset + 1))
else
    core.log(err)
end

Returns a sequential array of the skill IDs assigned to preset. Omit preset, or pass nil, to read the active preset. An empty preset returns an empty table.

lua
local assigned, err = core.link_skills.get_assigned()
if not assigned then
    core.log(err)
    return
end

for slot, skill_id in ipairs(assigned) do
    core.log(string.format("Link slot %d: %d", slot, skill_id))
end

To inspect every preset without activating it:

lua
for preset = 0, 2 do
    local assigned = core.link_skills.get_assigned(preset)
    if assigned then
        core.log(string.format(
            "Preset %d has %d assigned Link Skills",
            preset + 1,
            #assigned
        ))
    end
end

Mutations always target the active preset. To edit another preset, call activate_preset() first, then wait until get_active_preset() reports the requested preset before assigning or unassigning a skill. An immediate mutation can still target the old preset.

Requests assignment of one skill to the active preset. According to the client snapshot at call time, the request is rejected before sending when the skill is already assigned or the preset already contains 12 skills.

lua
local ok, err = core.link_skills.assign(
    core.link_skills.skills.ELVEN_BLESSING
)
if not ok then core.log(err) end

Requests removal of one skill from the active preset. According to the client snapshot at call time, the request is rejected before sending when that skill is not assigned.

lua
local ok, err = core.link_skills.unassign(
    core.link_skills.skills.ELVEN_BLESSING
)
if not ok then core.log(err) end

Requests activation of preset 0, 1, or 2. Requesting the already-active preset returns false, error_message without sending another request.

lua
local ok, err = core.link_skills.activate_preset(1) -- in-game Preset 2
if not ok then core.log(err) end

Setting one skill to a desired state

There is no separate enable/disable flag. A skill is enabled for the active preset when its ID appears in get_assigned(). Use assign() to enable it and unassign() to disable it.

lua
local links = core.link_skills

local function is_assigned(skill_id)
    local assigned, err = links.get_assigned()
    if not assigned then
        return nil, err
    end

    for _, assigned_id in ipairs(assigned) do
        if assigned_id == skill_id then
            return true
        end
    end

    return false
end

local function set_enabled(skill_id, enabled)
    local assigned, err = is_assigned(skill_id)
    if assigned == nil then
        return false, err
    end
    if assigned == enabled then
        return true
    end

    if enabled then
        return links.assign(skill_id)
    end
    return links.unassign(skill_id)
end

local ok, err = set_enabled(links.skills.WILD_RAGE, true)
if not ok then core.log(err) end

After a successful mutation, wait for a later on_tick and confirm the expected state before calling the helper again. Back-to-back requests can otherwise validate against stale character data.