V Matrix
On this page
The core.vmatrix module lets scripts inspect V Points and cores, craft and use Nodestones, upgrade cores, manage special cores, and reset allocated V Points.
Return conventions
Read functions return their value directly. When the V Matrix is unavailable or a request is invalid, they return nil, error_message.
local points, err = core.vmatrix.get_points()
if not points then
core.log("Unable to read V Matrix: " .. err)
return
endActions return true when the request is sent, or false, error_message when it cannot be sent safely.
local ok, err = core.vmatrix.craft_nodestones(5)
if not ok then
core.log("Unable to craft Nodestones: " .. err)
endCrafting, opening, upgrading, extending, activating, deactivating, and resetting 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. Packet callbacks run before the native V Matrix update, so do not verify the result inside on_packet_recv.
IDs, counts, and target levels must be positive whole numbers. Core IDs and target levels must also fit a signed 32-bit integer.
Data structures
Points
Returned by core.vmatrix.get_points().
| Property | Type | Description |
|---|---|---|
available | number | V Points currently available to spend |
allocated | number | V Points currently allocated to cores |
total | number | available + allocated |
nodestone_cost | number | V Point cost to craft one Nodestone |
activation_cost | number | Configured V Point registration cost reported for special cores |
reset_meso_cost | number | Meso cost to reset allocated V Points |
Nodestone
Returned by core.vmatrix.get_nodestone().
| Property | Type | Description |
|---|---|---|
item_id | number | Nodestone item ID |
count | number | Number currently in the inventory |
max_use | number | Largest safe batch under the current inventory and V Point limits |
points_per_item | number | V Points granted by each item |
max_use may be capped at 1 for Nodestones that must be opened individually. It does not bypass map, quest, or client-state restrictions; use_nodestones validates those when the action is requested.
Core
Returned by get_cores() and get_core().
| Property | Type | Description |
|---|---|---|
id | number | Core ID used by the other V Matrix functions |
level | number | Current core level |
max_level | number | Maximum core level; 0 when unavailable |
type | string | "skill", "boost", "special", or "unknown" |
active | boolean | Whether a special core is currently activated |
expires_at | number | Expiration time as a Unix timestamp, or 0 when it does not expire |
expired | boolean | Whether the core is expired |
extension_cost | number | Quoted V Point extension cost, or 0 when no extension is configured |
A positive extension_cost is a prerequisite, not a guarantee that extension is currently available. The core must also be eligible and the character must have enough available V Points; extend_core() revalidates both.
Reading V Matrix state
core.vmatrix.get_points() -> table | nil, string?
Returns the character's V Point balances and the costs needed for common actions.
local points, err = core.vmatrix.get_points()
if points then
core.log(string.format(
"V Points: %d available, %d allocated, %d total",
points.available,
points.allocated,
points.total
))
else
core.log(err)
endcore.vmatrix.get_nodestone(item_id?: number) -> table | nil, string?
Returns inventory and usage information for a Nodestone. Omit item_id to use the character's standard Nodestone item.
local nodestone, err = core.vmatrix.get_nodestone()
if nodestone then
core.log(string.format(
"Nodestones: %d owned, up to %d usable now",
nodestone.count,
nodestone.max_use
))
else
core.log(err)
endcore.vmatrix.get_cores() -> table<vmatrix_core> | nil, string?
Returns an array containing every core in the character's V Matrix.
local cores, err = core.vmatrix.get_cores()
if not cores then
core.log(err)
return
end
for _, vmatrix_core in ipairs(cores) do
core.log(string.format(
"%d: %s level %d/%d%s",
vmatrix_core.id,
vmatrix_core.type,
vmatrix_core.level,
vmatrix_core.max_level,
vmatrix_core.active and " (active)" or ""
))
endcore.vmatrix.get_core(core_id: number) -> vmatrix_core | nil, string?
Returns one core by ID. An unknown ID returns nil; an unavailable V Matrix or invalid argument returns nil, error_message.
local vmatrix_core, err = core.vmatrix.get_core(10000000)
if vmatrix_core then
core.log("Core level: " .. vmatrix_core.level)
elseif err then
core.log(err)
endcore.vmatrix.get_upgrade_cost(core_id: number, target_level: number) -> number | nil, string?
Returns the V Point cost to upgrade a core to the absolute target_level. The target must be above the current level and no higher than max_level.
local cost, err = core.vmatrix.get_upgrade_cost(10000000, 3)
if cost then
core.log("Upgrade cost: " .. cost .. " V Points")
else
core.log(err)
endV Matrix actions
core.vmatrix.craft_nodestones(count: number) -> boolean, string?
Converts available V Points into count Nodestones. The request is rejected before sending when there are not enough V Points or inventory slots.
local points, err = core.vmatrix.get_points()
if not points then
core.log(err)
return
end
local count = 0
if points.nodestone_cost > 0 then
count = math.min(5, math.floor(points.available / points.nodestone_cost))
end
if count > 0 then
local ok, craft_err = core.vmatrix.craft_nodestones(count)
if not ok then core.log(craft_err) end
endcore.vmatrix.use_nodestones(count?: number, item_id?: number) -> boolean, string?
Uses Nodestones from the inventory. count defaults to 1; omit item_id to use the standard Nodestone. Inventory, V Point cap, quest, map, and client-state restrictions are validated before sending.
local nodestone, err = core.vmatrix.get_nodestone()
if not nodestone then
core.log(err)
return
end
if nodestone.max_use > 0 then
local ok, use_err = core.vmatrix.use_nodestones(nodestone.max_use)
if not ok then core.log(use_err) end
endcore.vmatrix.upgrade_core(core_id: number, target_level: number) -> boolean, string?
Upgrades a core to the absolute target_level. The function validates the core, target level, upgrade cost, and available V Points before sending.
local vmatrix_core = core.vmatrix.get_core(10000000)
if vmatrix_core and vmatrix_core.level < vmatrix_core.max_level then
local target = vmatrix_core.level + 1
local ok, err = core.vmatrix.upgrade_core(vmatrix_core.id, target)
if not ok then core.log(err) end
endcore.vmatrix.extend_core(core_id: number) -> boolean, string?
Extends an eligible special core. A positive extension_cost supplies the quoted cost, but extend_core() still validates eligibility and the available V Point balance.
local vmatrix_core = core.vmatrix.get_core(10000002)
local points = core.vmatrix.get_points()
if vmatrix_core and points
and vmatrix_core.extension_cost > 0
and points.available >= vmatrix_core.extension_cost then
local ok, err = core.vmatrix.extend_core(vmatrix_core.id)
if not ok then core.log(err) end
endcore.vmatrix.activate_core(core_id: number) -> boolean, string?
Activates an eligible, unexpired special core. Returns false, error_message when the core is not special, is already active, is expired or disabled, or the character is in a state that prevents the change.
core.vmatrix.deactivate_core(core_id: number) -> boolean, string?
Deactivates an active, unexpired special core. It applies the same character-state safety checks as activation.
core.vmatrix.reset_points() -> boolean, string?
Resets all allocated V Points. The function validates the current cores, V Point cap, character state, and Meso balance before sending the request. The cost is available as get_points().reset_meso_cost.
local points, err = core.vmatrix.get_points()
if points and points.allocated > 0 then
core.log("Reset will cost " .. points.reset_meso_cost .. " mesos")
-- Call only after your script has obtained explicit confirmation.
-- local ok, reset_err = core.vmatrix.reset_points()
endComplete example
This example prints the current V Matrix and reports the next upgrade cost for every non-maxed core without changing anything.
local points, points_err = core.vmatrix.get_points()
if not points then
core.log(points_err)
return
end
core.log(string.format(
"V Points: %d available / %d total",
points.available,
points.total
))
local cores, cores_err = core.vmatrix.get_cores()
if not cores then
core.log(cores_err)
return
end
for _, vmatrix_core in ipairs(cores) do
local status = ""
if vmatrix_core.type == "special" then
status = vmatrix_core.active and " (active)" or " (inactive)"
end
core.log(string.format(
"[%d] %s %d/%d%s",
vmatrix_core.id,
vmatrix_core.type,
vmatrix_core.level,
vmatrix_core.max_level,
status
))
if vmatrix_core.level < vmatrix_core.max_level then
local cost = core.vmatrix.get_upgrade_cost(
vmatrix_core.id,
vmatrix_core.level + 1
)
if cost then
core.log(" Next level: " .. cost .. " V Points")
end
end
end