Repository navigation
For modders
Skills++ already gives every skill of a modded survivor a generic bonus. This page is for authors who want their skills to have upgrades of their own.
Add Skills++ to dependencies in your manifest.json:
"GreenAlen22-SkillPlusPlus-0.2.0"Only inside Initialize.add. Skills++ builds its API in its own initialization, which runs before yours; at the top of your file it does not exist yet, and any use there stops with an error that says so.
Initialize.add(function()
-- ... create your survivor and skills ...
local spp = mods["GreenAlen22-SkillPlusPlus"].api
-- register here
end)Writing upgrades for another author's survivor? Use Initialize.add(Callback.Priority.AFTER, function() ... end), so their skills exist by then.
A skill you do not register gets the generic bonus of its slot:
| Slot | Per level |
|---|---|
| Z - Primary | +15% (+15% per level) skill damage. |
| X - Secondary | +10% (+10% per level) skill damage, -8% (-8% per level) cooldown. |
| C - Utility | -10% (-10% per level) cooldown, +1 charge every 2 levels. |
| V - Special | +10% (+10% per level) skill damage, -8% (-8% per level) cooldown. |
The damage bonus only lands if the skill takes its damage from the actor: actor:skill_get_damage(skill) or actor:get_active_skill(slot).damage. If it fires with the damage of the Skill itself (mySkill.damage, the value you set when creating it) or a number of its own, register it without damage (section 4) or as false (section 6).
spp.register(mySecondary, { damage = 0.10, cooldown = 0.92 })
spp.register({ mySpecial, mySpecialBoosted }, { cooldown = 0.92, stock_every = 2 })| Field | Per level | Example |
|---|---|---|
damage |
added skill damage |
0.10 = +10% per level |
cooldown |
cooldown multiplier, compounds |
0.92 = -8% per level |
stock_every |
+1 charge every N levels; 1 reads +1 (+1 per level) |
2 |
cooldown and stock_every do nothing on a primary skill: the game does not let them change there. A skill and its Ancient Scepter version share one table - pass both. Skills++ writes the description line for these three fields itself.
Put your numbers in the table, list the ones the description shows in text, and apply them in your own code with spp.rank:
local DASH = {
invuln = 0.2, invulnMax = 1.0,
text = { { "invuln", "sec", "invulnMax" } },
}
spp.register(myUtility, DASH)
Callback.add(myDashState.on_enter, function(actor, data)
local level = spp.rank(actor, myUtility)
if level < 1 then return end
local seconds = math.min(DASH.invuln * level, DASH.invulnMax)
actor.invincible = math.max(tonumber(actor.invincible) or 0, math.floor(seconds * 60))
end)spp.rank(actor, skills) - the level of whichever of skills (one Skill or a list) the actor has active; 0 if none is, and for anything that is not a player. While a temporary skill that no survivor has holds the slot - another mod's reload, for one - the slot's own skill counts as active. Every machine gets the same answer. Your effect follows the same network rules as the rest of your code: damage and chance rolls are decided on the host.
A text entry is { field, format }, or { field, format, extra_field [, extra_format] } when the line names one more number - a cap or a duration; the extra number uses the entry's format unless given its own.
| Format | Value | Written as | Example string |
|---|---|---|---|
pct |
0.15 |
15 twice: level 1, then per level |
"+%s% (+%s% per level) blast radius" |
count |
2 |
2 twice |
"+%s (+%s per level) pellets" |
sec |
0.5 |
0.5 twice (0,5 in Russian) |
"+%ss (+%ss per level) stun" |
every |
2 |
2 once |
"+1 bullet every %s levels" |
from |
3 |
3 once |
"from level %s" |
share |
0.1 |
10 once: a fixed share, it does not grow |
"heals for %s% of the damage dealt" |
The strings go to your own language files, under the namespace of the skill (the one ReturnsAPI's .auto{ namespace = ... } gave it; for another author's survivor that is their namespace, not yours), then skillPlusPlus, then the field:
-- language/english.lua
return {
mysurvivor = { skillPlusPlus = {
invuln = "+%ss (+%ss per level, up to %ss) invulnerability after the dash",
} },
}Write it the way vanilla writes item stacking: the gain at level 1, then the gain per level in brackets. A missing string shows up in the description as a raw key.
spp.register(myPassive, false)register raises an error, and ReturnsAPI logs it as "Initialize ... failed to execute fully": the rest of that Initialize function does not run, so register after creating everything else. The message names the skill, unless the argument itself is not a Skill. It happens when:
- the first argument is not a Skill or a list of Skills (
nilusually means the skill does not exist yet - see section 2); - the skill is a vanilla one - its upgrades belong to Skills++;
- the table is neither a table nor
false; -
damage,cooldownorstock_everyis not a number;cooldownis outside (0, 1];stock_everyis not a whole number of 1 or more; -
textnames a field the table lacks or one that is not a number, or a format that does not exist.
Warnings in the log, not errors: a skill registered again (the new table replaces the old one - normal after a hotload); a cooldown below 0.5 (it is a multiplier: 0.92 means -8%).
spp_status in the console shows how many skills other mods registered.