Violet

Inner Ability

On this page

Provides read access to the character's Inner Ability lines for the currently active preset, a manual circulate() re-roll, and the Auto Inner Ability engine that circulates until your goals are met.

Line Object Structure

core.inner_ability.get_current() returns an array of line objects with the following properties:

PropertyTypeDescription
skill_idnumberAbility ID (see the ability reference)
posnumberSlot index (1-3)
gradenumberRarity grade (see table below)
namestringAbility name in your client's language, e.g. "Boss Monster Damage Increase"

The name is the ability's name only — it never carries the rolled value. The magnitude the game shows in the tooltip is resolved separately and is not exposed here.

Inner Ability Grades

GradeName
0Rare
1Epic
2Unique
3Legendary

Functions

core.inner_ability.get_current() -> table

Returns an array of the active preset's Inner Ability lines (up to 3). Returns an empty table if unavailable.

lua
local lines = core.inner_ability.get_current()
for _, line in ipairs(lines) do
    core.log(string.format("Slot %d (Grade %d): %s", line.pos, line.grade, line.name))
end

core.inner_ability.get_active_preset() -> number

Returns the index of the currently active Inner Ability preset (0-based), or -1 if none. This is the preset get_current() reads and the default target of circulate().


core.inner_ability.get_honor_exp() -> number

Returns the character's current Honor EXP — the currency spent circulating Inner Ability (capped at 9,999,999).


core.inner_ability.circulate(preset_index?: number, lock_positions?: table) -> boolean

Re-rolls (circulates) the Inner Ability lines, spending Honor EXP. preset_index (0-based) defaults to the active preset. lock_positions is an optional array of slot numbers (1-3) to keep — the rest are re-rolled. Omit to re-roll all lines. Locking is only allowed once the preset is Unique grade or higher, and at least one slot must be left to re-roll.

lua
-- Re-roll every line of the active preset
core.inner_ability.circulate()

-- Keep slot 1, re-roll the rest
core.inner_ability.circulate(core.inner_ability.get_active_preset(), { 1 })

Auto Inner Ability

The functions above act once. Auto Inner Ability keeps circulating for you and stops on its own the moment the lines satisfy your goals, the Honor EXP floor is reached, or the circulate cap runs out. It is the same engine the web menu drives — right-click your character portrait on the Player screen and choose Auto Inner Ability — so a script and the menu can never disagree about a run.

Goal Object Structure

Each entry of opts.goals describes one line you want. Every goal must be met by a different line, so two goals never both count the same lucky roll.

PropertyTypeDescription
skill_idstableAbility IDs this goal accepts, e.g. { 70000035 }. See the ability reference
min_levelnumberMinimum line level
min_gradenumberMinimum grade for that line (see the grade table above)
abilitystringLegacy. Case-insensitive substring of the ability name, used only when skill_ids is absent

Prefer skill_ids: IDs are the same in every region, while names are localized, so an ID-based goal keeps working on a non-English client. Some abilities share a display name — "Increases Speed" is both 70000005 and 70000011 — so a goal that means "either" lists both.

Warning

min_level is the line's level as the client reports it. Whether that equals the magnitude the tooltip shows (i.e. whether level 20 means "+20%") is not verified and is unlikely to hold for every ability — several lines bake a fixed value into their text, and the dual-stat lines produce two numbers from one level. Treat it as a floor on the level, not a promise about the percentage.

core.inner_ability.start(opts?: table) -> boolean, string?

Starts the Auto Inner Ability engine, returning false plus an error message if the options are invalid. Every option persists until changed, so omitting one keeps whatever the menu holds.

OptionTypeDescription
presetnumberPreset index to circulate (0-31); omit or -1 for the active preset
min_gradenumberGrade every line must reach (0-3). Default 2 (Unique)
goalstableArray of goal objects (see above). Empty means the grade gate alone decides
auto_lockbooleanKeep goal-matching lines and re-roll only the rest. Only lines that also clear min_grade are kept, and only on a Unique+ preset
min_honornumberStop once Honor EXP reaches this. 0 spends it all
max_circulatesnumberSafety cap on circulates for the run (1-999), or 0 for no cap
roll_delaynumberMilliseconds to wait between circulates (0-5000). Default 350. Not shown in the menu — scripts only

Every goal row is validated before it is stored. A row that names no ability at all (neither skill_ids nor a non-empty ability), or whose min_level / min_grade / skill_ids are the wrong type, is rejected with false and a message rather than being carried into the run.

lua
core.inner_ability.start({
    min_grade = 3,                     -- every line Legendary
    goals = {
        -- Boss Monster Damage Increase, Legendary, level 20+
        { skill_ids = { 70000035 }, min_level = 20, min_grade = 3 },
    },
    min_honor = 50000,
    max_circulates = 100,
})

core.inner_ability.stop() -> boolean

Stops a running Auto Inner Ability run. Safe to call when nothing is running.


core.inner_ability.is_running() -> boolean

Returns whether an Auto Inner Ability run is currently active.


core.inner_ability.get_status() -> table

Returns the live state of the run: running, state, preset, circulates_used, honor_spent, and a result table mirroring what the web menu shows.

FieldTypeDescription
runningbooleanWhether the engine is enabled
statestringidle, waiting_result, checking_result or cooldown
presetnumberPreset this run is circulating (-1 once the run has ended)
circulates_usednumberCirculates spent so far by the live run
honor_spentnumberHonor EXP spent so far by the live run
resulttable{ status, circulatesUsed, honorSpent, honor, preset, nextCost, startLines, currentLines }

result.status is one of circulating, rolling, done, no_honor, max_reached, preset_not_found, timeout or character_changed. honor is the character's Honor EXP balance at the time of the update. nextCost is the Honor EXP the run has reserved for its next circulate (see Circulate cost). startLines and currentLines are arrays of { pos, skillId, level, grade, name }, letting a script report what the run changed.

Tip

The top-level circulates_used / honor_spent / preset describe the run in progress and are cleared the moment it ends. Read the totals of a finished run from result.circulatesUsed / result.honorSpent, which keep the values that stopped it.

Warning

A run spends real Honor EXP on every circulate. Always set max_circulates (or min_honor) to something you are willing to lose — a goal that cannot roll will otherwise keep circulating until the cap trips. With max_circulates = 0 there is no cap at all, and min_honor becomes the only thing that ends an unrollable run.

Tip

roll_delay is the only pacing knob the run exposes, and the only wait in the engine the server can see. Lowering it makes a run finish sooner; if circulates start coming back refused (a timeout status), raise it again.

Circulate cost

A circulate is priced by the preset's current rank and by how many lines are locked. Before each circulate the engine reserves the larger of this table's price for the current rank and lock count and the cost the previous circulate actually took, and refuses to spend when that would break min_honor. Taking the larger of the two matters: the table can be wrong about a given server, while an observed cost goes stale the moment the preset ranks up or a lock is added.

RankNo locks1 locked2 locked
Rare100400900
Epic2001,1002,600
Unique1,5003,0005,500
Legendary8,00011,00016,000

Examples

lua
local lines = core.inner_ability.get_current()
if #lines == 0 then
    core.log("No Inner Ability lines")
    return
end

for _, line in ipairs(lines) do
    core.log(string.format("[%d] %s (skill %d, grade %d)",
        line.pos, line.name, line.skill_id, line.grade))
end

Circulate for a Legendary Boss Damage line, then report

lua
core.inner_ability.start({
    min_grade = 3,
    goals = { { skill_ids = { 70000035 }, min_level = 30, min_grade = 3 } },
    max_circulates = 200,
})

function on_tick()
    if core.inner_ability.is_running() then return end

    -- Read the finished run's totals from `result` — the top-level counters
    -- are cleared as soon as the run ends.
    local result = core.inner_ability.get_status().result
    if result and result.status == "done" then
        core.log(string.format("Done in %d circulates (%d Honor EXP)",
            result.circulatesUsed, result.honorSpent))
    end
end

Inner Ability Reference

Every ability a line can roll, from the client's own data (v270). Use these IDs in a goal's skill_ids.

Where two IDs share a name they are listed together — they are indistinguishable in-game, so a goal that wants that ability should list both.

AbilityID(s)Effect
Additional Damage on Targets with Abnormal Status70000039+#y% damage when attacking targets inflicted with Abnormal Status.
All Stats Increase70000015, 70000044All Stats: +#strFX
Attack Increase70000012Attack +#padX
Attack Increase By Level70000025, 70000040Attack +1 for every #lv2pad levels
Attack Skill Target Increase70000047Number of enemies hit by multi-target skill +#targetPlus
Attack Speed Increase70000016Attack Speed +1 Level
Avoidability Boost70000034Avoidability +#er%
Boss Monster Damage Increase70000035Boss Damage: +#bdR%
Buff Duration Increase70000048Buff skill duration: +#bufftimeR%
Chance for no cooldown.70000045#nocoolProp% chance to skip cooldowns
Critical Rate Increase70000014Critical Rate: +#cr%
DEF to Damage Conversion70000041Final Damage: +#pdd2dam% of DEF
Defense Set Percentage Increase70000029, 70000030DEF: +#pddR%
DEX and INT Increase70000054DEX: +#dexFX, INT: +#intFX
DEX and LUK Increase70000055DEX: +#dexFX, LUK: +#lukFX
DEX and STR Increase70000057DEX: +#dexFX, STR: +#strFX
DEX Increase70000001DEX: +#dexFX
DEX to STR Conversion70000022#dex2str% of AP assigned to DEX added to STR
Increases Critical Rate70000043Critical Rate: +#cr%
Increases DEF70000006, 70000007Defense: +#pddX
Increases DEX70000018DEX: +#dexFX
Increases INT70000019INT: +#intFX
Increases Jump70000004Jump: +#psdJump
Increases LUK70000020LUK: +#lukFX
Increases Meso Drop70000033Mesos Obtained: +#mesoR%
Increases Speed70000005, 70000011Speed +#psdSpeed
Increases STR70000017STR: +#strFX
Instant-Kill on Normal Monsters in Azwan Liberation Supply Mode70000038#minionDeathProp% chance to instant-kill when attacking normal monsters in Azwan Liberation Supply Mode
INT and DEX Increase70000060INT: +#intFX, DEX: +#dexFX
INT and LUK Increase70000056INT: +#intFX, LUK: +#lukFX
INT and STR Increase70000058INT: +#intFX, STR: +#strFX
INT Increase70000002INT: +#intFX
INT to LUK Conversion70000023#int2luk% of AP assigned to INT added to LUK
Item Drop Rate Increase70000049Item Drop Rate +#dropR%
JUMP Increase70000010Jump +#psdJump
LUK and DEX Increase70000061LUK: +#lukFX, DEX: +#dexFX
LUK and INT Increase70000062LUK: +#lukFX, INT: +#intFX
LUK and STR Increase70000059LUK: +#lukFX, STR: +#strFX
LUK Increase70000003LUK: +#lukFX
LUK to DEX Conversion70000024#luk2dex% of AP assigned to LUK added to DEX
Magic Attack Increase70000013Magic Attack +#madX
Magic Attack Increase By Level70000026, 70000042Magic Attack +1 for every #lv2mad levels
Max HP Increase70000008Max HP: +#mhpX
Max HP Set Percentage Increase70000027, 70000031Max HP: +#mhpR%
Max MP Increase70000009Max MP: +#mmpX
Max MP Set Percentage Increase70000028, 70000032Max MP: +#mmpR%
Meso Drop Increase70000050Mesos Obtained: +#mesoR%
Normal Monster Damage Increase70000036+#nbdR% damage to normal monsters
Passive Skill Level +170000046Passive Skills: +#passivePlus Level (excludes Active Hybrids, 5th job skills, 6th job skills)
STR and DEX Increase70000051STR: +#strFX, DEX: +#dexFX
STR and INT Increase70000052STR: +#strFX, INT: +#intFX
STR and LUK Increase70000053STR: +#strFX, LUK: +#lukFX
STR Increase70000000STR: +#strFX
STR to DEX Conversion70000021#str2dex% of AP assigned to STR added to DEX
Tower Damage Increase70000037+#tdR% damage to towers

The #placeholder in each effect is filled in by the game from the line's level; that per-level table is not readable from the client's data files, which is why it is shown raw.