Capabilities

DELIVER_SKILL_GRANT

Hand a bought skill to a character

Optional

Without this capability the Skill option is removed from the product and bundle builders, even when the skill catalog is searchable. Items and coins are unaffected — a pack that only delivers items is a complete portal.

The grant object
{
  "type": "l2.grant_skill",
  "schemaVersion": 1,
  "skillId": 1204,
  "skillLevel": 1
}

This is the grant object inside the command payload — the envelope with commandId, orderId, target and grant is documented on DELIVER_ITEM_GRANT and is the same for every grant kind. Everything about outcomes, replay protection and the command journal is identical too — one journal covers both.

It is a separate capability because a pack can genuinely do one and not the other. On an L2Off server both travel through the same queue, but the extender code that grants an item and the code that grants a skill are different, and either can exist alone.

Never a downgrade

skillLevel is a normal skill level, never an enchant route. Enchanted levels (101+, 201+ in retail data) are out of scope: the builders never offer them, because SEARCH_SKILL_CATALOG reports maxLevel as the highest non-enchanted level.

Three branches, and the middle one decides whether a player is charged for nothing:

What the character knowsWhat you return
the skill at an equal or higher levelREFUSED with SKILL_ALREADY_KNOWN, having written nothing
the skill at a lower levelapply it — this is an upgrade, not a duplicate
nothingapply it

This answer moves money, in both directions

Forgeport gives the coins back on REFUSED, because the bridge is saying the purchase cannot be delivered. The code decides only which sentence the player reads — see Refusal codes. The reservation is released without anyone approving it, so the condition has to be exactly the one above.

Too permissive — reporting APPLIED for a skill you left alone — and the player pays for nothing and has no way to tell. Too eager — returning the refusal for a skill you could have granted, or for every skill — and your own sales cancel themselves, silently, for as long as the mistake is in the build.

Return it before writing anything, the journal included. There is nothing to be idempotent about when no mutation happened, and the release is granted on the strength of that claim.

Tell the player too. Every refusal happens with the character in the world, so the one place they are certainly looking is the game — without a line there, the purchase simply does not arrive and the only explanation is on a web page they may not open for hours:

player.sendMessage("Portal: your purchase was not delivered — " + because + ".");

Both reference bridges send one for every refusal they can attach a player to. The order also carries the reason in the player's own history, and the coins are already back by then.

Never leave the skill alone and report APPLIED: that reads as delivered, so the player is charged for a purchase they never received and nothing anywhere says so.

Implementing it

The same applyGrant method, handling l2.grant_skill. Add the skill to the live character and refresh the client's skill window.

Use the pack's own refresh call rather than constructing the packet yourself. In Mobius that is player.sendSkillList() — the SkillList packet there is an empty builder, so sending a bare one blanks the skill window instead of refreshing it.

Advertise this capability only once the payload is handled, and return REFUSED with UNSUPPORTED_GRANT_TYPE for any payload type you do not implement — nothing was written, so the coins go back.

Both reference bridges read the level from the live character, which is the only copy that is current — a skill learned this session is not in character_skills until the character is saved:

final Skill known = player.getKnownSkill(skillId);
if ((known != null) && (known.getLevel() >= skillLevel))
{
    return Result.refused("SKILL_ALREADY_KNOWN");
}

Revocation

There is none, exactly as with items. A granted skill cannot be taken back through this capability.

Verification

Connector check does not exercise this one — a granted skill has no revocation path, so there is no harmless probe. Confirm it by buying a skill on a test character.

On this page