For the complete documentation index, see llms.txt. This page is also available as Markdown.

Website: Inscription Tooltips

Step-by-step guide for web developers - read an item's inscriptions from the ItemExt table and show them in website item tooltips exactly like the game client, with full Node.js and PHP code.

Inscribed items show extra lines in the game tooltip: Potential, slots, inscriptions and the bound owner. Item data on a website (character viewer, rankings, market, warehouse) only shows the 16-byte item, so these lines are missing.

This guide shows how to read the inscription data and print the same lines as the game client.

For what inscriptions are and how to configure them, see Inscription (overview).

What the tooltip shows

The game client adds this block at the end of the item tooltip, after the normal option lines:

Potential 30 / 80                    <- yellow, bold
Might II                             <- violet, bold   (filled slot)
Damage +4%                           <- blue           (its description)
Inscription Slot (empty)             <- gray           (open slot)
Inscription Slot (corrupted)         <- dark red       (corrupted slot)
Bound to Hero                        <- red            (only if bound)
  • Potential 30 / 80 = Potential left / Potential total.

  • Closed slots print nothing.

  • An item with no inscription data prints nothing at all.

Where the data lives

You need three things:

Data
Where
What you get

Item serial

The 16-byte item, bytes 3-6

Key into ItemExt

Inscription record

SQL table ItemExt, column Data

Potential, slots, bound name

Inscription names and texts

Data/Plugins/Inscription/Pools.xml

Name, description, magnitude per tier

Also read the Enabled attribute of Data/Plugins/Inscription/Inscription.xml. When it is 0, the game shows no inscription lines, so the website must not either.

If the website runs on another machine, copy Pools.xml and Inscription.xml to it (or export them to JSON) every time you change them on the server.

Step 1 - Get the serial from the item

Every 16-byte item has its serial in bytes 3-6, big-endian (most significant byte first). This is the same in every column that stores items: Character.Inventory, warehouse.Items, ExtWarehouse.Items, market rows.

Byte
Content

0-2

Item index, level, options (you already decode these)

3-6

Serial, big-endian unsigned 32-bit

7-15

More options, sockets

Skip:

  • Empty slots: byte 0 = 0xFF, byte 7 has bit 0x80 set, and the high 4 bits of byte 9 are all set (0xF0).

  • Serial 0: shop and system items without a serial can never carry inscriptions.

  • Stackable items (jewels, potions): never carry inscriptions.

Example: bytes 3-6 = 00 01 E2 40 → serial 0x0001E240 = 123456.

Step 2 - Load the ItemExt rows

One row per item that has extra data. No row = nothing to show.

Collect the serials of all items on the page, then load them in one query:

Step 3 - Find the inscription record

Data is a list of records, one per end-game system. Inscription is system 1. Other systems may be added later, so always walk the list; never assume the inscription record is first.

Each record:

Offset
Size
Field

0

1

SystemId (0 = end of list)

1

1

Version

2

1

Len = size of the body

3

Len

Body

Walk: start at offset 0. Stop when SystemId is 0 or the record would run past byte 128. Otherwise, if SystemId is 1 that is the record; if not, jump 3 + Len bytes to the next one.

Use the record only when Version = 1 and Len ≥ 21. Anything else: show nothing (same as the game).

Step 4 - Read the record body

Offset
Size
Field
Values

0

1

Potential

0-100, total budget

1

1

Spent

Potential used so far

2

3

Slot 1

Id, Tier, State (one byte each)

5

3

Slot 2

Id, Tier, State

8

3

Slot 3

Id, Tier, State

11

10

Bound

Character name, ASCII, zero-padded. All zero = not bound

21

2

(server only)

Reroll range. Never show it

Slot fields:

Field
Meaning

Id

Entry Id in Pools.xml. 0 = none

Tier

0 = inscribed, 1 = empowered once (II), 2 = twice (III) ... up to 7 (VIII)

State

0 = closed, 1 = open (empty), 2 = filled, 3 = corrupted

The Bound name uses all 10 bytes when the name is 10 characters long - there is no zero at the end then. Read up to the first zero or 10 bytes.

Step 5 - Load the inscription texts from Pools.xml

For every <Entry> in every <Pool>, keep:

Attribute
Use

Id

Key (1-255, unique across all pools)

Name

First 31 characters

Desc

First 95 characters. Can be empty

Magnitude

Comma list, one number per tier (max 8)

Magnitude rule: a short list repeats its last number. Magnitude="3,4,5" means tiers 0-7 = 3, 4, 5, 5, 5, 5, 5, 5. An empty list = all 0.

Parse the file once and cache it. Reload it when the file changes.

Step 6 - Print the lines

In this order:

  1. Potential line (yellow, bold): Potential {left} / {Potential} where left = Potential - Spent, never below 0.

  2. One block per slot, slot 1 to 3:

    State
    Lines

    0 closed

    nothing

    1 open

    Inscription Slot (empty) - gray

    3 corrupted

    Inscription Slot (corrupted) - dark red

    2 filled, Id found in Pools.xml

    Name + tier suffix - violet, bold. Then the description - blue (skip if Desc is empty)

    2 filled, Id not in Pools.xml

    Unknown Inscription - gray

  3. Bound line (red), only if the name is not empty: Bound to {name}.

Tier suffix: tier 0 = nothing, 1 = II, 2 = III, 3 = IV, 4 = V, 5 = VI, 6 = VII, 7+ = VIII. Example: Might II.

Description: take Desc, replace the first %d with that tier's magnitude, and replace every %% with %. Damage +%d%% at tier 1 → Damage +4%.

Colors used by the game client, for a dark tooltip background:

Line
Color

Potential

#FFCC1A (yellow)

Inscription name

#B366FF (violet)

Description

#80B3FF (blue)

Empty slot, unknown

#666666 (gray)

Corrupted slot

dark red, for example #A01818

Bound

#FF331A (red)

Full code

Uses mssql and fast-xml-parser (npm i fast-xml-parser).

Using it on a character page:

Uses PDO (sqlsrv) and SimpleXML.

Using it on a character page:

Worked example

A sword with serial 123456. Item bytes 3-6: 00 01 E2 40.

ItemExt.Data for serial 123456 (first 26 bytes, the rest is zeros):

Bytes
Meaning

01 01 17

System 1 (Inscription), version 1, body 23 bytes

50

Potential 80

19

Spent 25

01 01 02

Slot 1: entry 1, tier 1, filled

00 00 01

Slot 2: open

00 00 00

Slot 3: closed

00 × 10

Not bound

32 64

Server only - ignore

Entry 1 in the shipped Pools.xml: Name="Might" Desc="Damage +%d%%" Magnitude="3,4,5". Tier 1 → magnitude 4.

Result:

Important Behavior

  • Data is live. The game server writes ItemExt as soon as an inscription changes. The item columns (Inventory, ...) are saved on the normal save cycle, so for a few seconds a just-moved item can show in its old place. That is normal.

  • Rows follow the serial. Trade, warehouse, drop and pick-up keep the record. Selling to an NPC, using the item in a mix, or the item vanishing from the ground deletes the row.

  • No record yet. Eligible items get their Potential the first time a player gets them (pick-up, mix, shop, or the first login after the plugin was turned on). Until then the item has no row and shows nothing. The game shows nothing too.

  • Plugin off or unlicensed. With Enabled="0" the rows stay in the database but the game shows nothing. Your website checks Enabled for this. The website cannot see the license; if the paid module is not licensed, the server owner should set Enabled="0".

  • Entry removed from Pools.xml. Items keep the Id. The game shows Unknown Inscription; do the same. Never renumber entry Ids.

  • Same serial twice. Only stackable items can share a serial, and they never have records. One serial = one record.

Optional - catalyst lines on jewels

The game also explains catalyst jewels. Hovering a jewel that is the Catalyst of an entry shows:

One pair of lines per entry whose Catalyst="Group,Index[,Level]" matches the jewel (and its level, if given). The game only lists entries whose Class includes the viewer's class; on a website, either filter by the character being viewed or show all.

Common Issues

Last updated