Talents
Add nodes to the game's own skill tree, or give your mod a whole talent tree of its own.
Two fixes await a client retest: keeping unlocks when a mod list moves a node, and German labels on a Kiln tree’s screen. A Kiln tree’s respec has no game result yet.
Two ways, both in skills/*.json, both with "side": "both" and "clients": "mod", because the game builds the same tree
from the same files. Start with kiln new talents MyTalents.
| The game’s tree | A Kiln tree | |
|---|---|---|
| Drawn by | the game’s skill screen | a Kiln screen in the game’s look, from the pause menu or a key |
| Paid with | the game’s skill points | its own points, or a share of the game’s |
| Effects | run by the game | attributes, buffs, game-node effects, programs, abilities, code |
Nodes in the game’s tree
{ "format": 1,
"gameTree": { "nodes": [
{ "guid": "3e2f6a1b-7c48-4d95-a1e3-5b9c0d7e8f21", "name": "mymod_ember_ward",
"class": "Mage", "like": "0xcfa5985b", "from": ["0xcfa5985b"], "offset": [170, -40],
"cost": 1, "configs": { "0x0a0c87e7": 2 },
"texts": { "en": { "name": "Ember Ward", "description": "+2 Intelligence." },
"de": { "name": "Glutwehr" } } } ] } }
guidis fixed forever: saves keep the node’s id.likecopies a node’s effect, values, icons and texts.configsandscaleschange its number values. Writetextsfor what that node does:0xcfa5985braises Intelligence.fromandtoare links.position, ornear+offset, place it.costis per level.maxLevelis 0 (one unlock) to 7.- Also
program,iconFile,unlocksAbility. From code:GameTree.Define(...), which on a dedicated server counts from the next start.
The game’s tree has room for only a few more nodes. Past that, Kiln keeps the extras in a shadow table (up to 4096 in all). The screen shows them and the game’s rules apply, but they stay out of the character save, so a character stays valid on servers without Kiln.
Adding a mod can move a node between the game’s tree and the shadow table. It no longer undoes the unlock: both directions keep
it and its level. If the game’s rules refuse a node moving back, its points come back and kiln.log warns.
Remove a mod and its nodes are taken out and refunded at the next join. On a server without Kiln, the game resets the whole tree instead if the save holds Kiln nodes.
A Kiln tree
{ "format": 1, "trees": [ {
"id": "mymod:ember", "name": { "en": "Ember Arts", "de": "Glutkünste" },
"points": { "start": 1, "perLevel": 1 },
"menu": { "en": "Ember Arts" }, "key": "K", "respec": true,
"nodes": [
{ "id": "kindle", "name": { "en": "Kindle" },
"description": { "en": "+1 Intelligence per level." },
"col": 1, "row": 0, "cost": 1, "maxLevel": 3, "icon": "icons/kindle.png",
"effects": [ { "attribute": "Intelligence", "amount": 1 } ] },
{ "id": "step", "name": { "en": "Flame Step" }, "col": 1, "row": 2,
"requires": ["kindle"], "pointsSpent": 3, "level": 10,
"effects": [ { "buff": "MyMod_Warmth", "refresh": 30 },
{ "ability": "mymod:flame-step" } ] } ] } ] }
A data-only mod needs no code. A node’s id is its save key: never change it. col and row run 0 to 31, levels to 99.
requires needs any one node, or all with requireAll. pointsSpent and level make tiers.
| Effect | Runs while the node is taken |
|---|---|
{"attribute": "Strength", "amount": n} |
n × level on any of the six attributes |
{"gameNode": "0x<id>"} |
that game node’s effect, without unlocking it |
{"program": "<guid>", "configs": {...}} |
any Impact program on the player |
{"buff": "<GUID or clone>", "refresh": s} |
a buff, renewed; ends within refresh + 5 s of a lock |
{"ability": "<id>"} |
a Kiln ability only holders may cast |
TalentEffect.Callback(apply, remove) |
your C#, on the tick thread |
points is {"start", "perLevel"}, or {"share": 0.5} for half the game’s total (its tree keeps its own), or
TalentPoints.Custom(f).
Unlocks are per character, and follow the character to other worlds. A lock is refused while another taken node needs it. Respec is free unless turned off.
The tree’s key opens it during play only, so typing in chat doesn’t trigger it. In a game hosted offline the pause menu stops the world: the screen shows a change at once, and it applies when you resume.
In chat: /talents, /talents <tree>, /talents <tree> unlock|lock <node>, /talents <tree> respec. Admins:
/talents <tree> grant <points> [player].
From code
Skills.Register(new TalentTree
{
Id = "mymod:talents", Name = UiText.Of(("en", "Talents"), ("de", "Talente")),
Points = TalentPoints.Own(start: 1, perLevel: 1),
MenuEntry = "Talents", Key = "K",
Nodes = [ new TalentNode { Id = "a", Name = "Strong", Column = 0, Row = 0,
Effects = [TalentEffect.Attribute(TalentAttributes.Strength, 2)] } ],
});
var h = Skills.HolderOf(player); // server, tick thread
Skills.Unlock("mymod:talents", "a", h); // also Lock, Respec, Grant, Points, State
[Subscribe]
void OnUnlocking(TalentUnlockingEvent e) { if (TooSoon()) { e.Reason = "not yet"; e.Cancel(); } }