Unlocks Config Format
Overview
Unlocks are the way player achievements are implemented in our services. An unlock can be simple, like killing 10 zombies, or complex, like tracking changes in player level, abilities, or battle pass progress.
Unlock progress is calculated from player statistics.
To learn how to use unlocks in your game, see the .
Adding Unlocks Config
To use unlocks, you need to:
Add unlock descriptions to the unlocks config.
Deploy configs to services.
The config supports up to 1,000 unlocks.
Unlock Description Format
{
"name": "pistol_master",
"type": "NORMAL",
"table": "global",
"condition": "s.pistol_kills",
"stages": [{"progress": 10}],
"mode": "default",
"hidden": false,
"periodic": false,
"startStageLoop": 4,
"autoRewarding": false,
"dynamicUnlock": false,
"dynamicProgress": false,
"dynamicRewards": false,
"showForAll": false,
"requirement": "winLimitHelper",
"iconUrl": "https://example.com/icons/pistol_master.png",
"meta": {}
}
Fields
namestring required Name of the unlock. Must be unique.
typestring required Type of the unlock. Possible values:
tablestring required Name of the table used to calculate the unlock condition. See Statistics Tables.
conditionstring required A quirrel expression used to calculate unlock progress. Uses the same format as stats condition. Maximum 512 characters.
stagesarray required Array of unlock stages. Must have at least one stage, maximum 1,000 stages. See Stage Format.
modestring optional Name of the game mode used to calculate the unlock condition. See Statistics Modes.
- bool optional
If
true, the unlock is hidden from the user. Use this for helper unlocks that implement complex mechanics. Defaults tofalse. Examples.periodicbool optional If
true, unlock stages are cyclic – they repeat after the last stage is reached. Defaults tofalse. Example.startStageLooppositive int optional The stage number at which the cycle begins. Only applies when
periodicistrue. If not set, the cycle starts from stage 1. Example.autoRewardingbool optional If
true, stage rewards are granted automatically when the stage opens. Defaults tofalse. Iffalse, use the action to grant rewards manually. Example.dynamicUnlockbool optional If
true, both the unlock progress and stage decrease when the condition expression result decreases. Defaults tofalse. Example.dynamicProgressbool optional If
true, only the unlock progress decreases when the condition result decreases – the stage remains unchanged. Defaults tofalse. Example.dynamicRewardsbool optional If
true, rewards are granted every time a stage is opened, including after the stage has been decreased and re-opened. Only applies whendynamicUnlockistrue. Defaults tofalse. Example.showForAllbool optional If
true, the unlock is visible to other users. Defaults tofalse. To request another user’s unlocks, use the action.requirementstring or list of strings optional Other unlocks that must be opened before this unlock’s rewards can be granted. If the required unlocks are not open, rewards are withheld.
Can be specified as a string using
&as separator, or as a list:"requirement": "unlock1 & unlock2"
"requirement": ["unlock1", "unlock2"]
Allowed characters: letters, digits, underscores, hyphens, spaces, and
&.iconUrlstring (URL) optional URL of the icon displayed for this unlock on the client.
metaJSON object optional Arbitrary JSON data attached to the unlock. Use this to pass custom game-specific information to the client. Maximum 32,768 characters. Example.
namespacestring optional Namespace of the unlock. Used to organize unlocks across different configurations.
personalstring optional Type of the personal unlock generator this unlock belongs to. Must match the
typefield of apersonalUnlockGeneratorsentry in the tables config. Defaults tocommon.newbiebool optional If
true, this unlock is included in the newbie pool of its personal unlock generator. Newbie players receive unlocks from this pool instead of the general pool. Only applies whenpersonalis set.steamAchievementbool optional If
true, the unlock is sent to Steam as a completed achievement when it is fully opened. Only applies to Steam accounts. Defaults tofalse.showByAchvServicebool optional If
true, the unlock is visible in the achievement service. Sent to the client as part of the unlock description. Defaults tofalse.
Stage Format
Each stage is opened when the condition expression result reaches or exceeds
the stage’s progress value.
progresspositive int required The threshold value at which this stage opens.
updStatsarray optional Stats to update as a reward when this stage opens. Each entry has:
mode– the game mode in which the stat is updated.name– the name of the stat to update.value– the value to apply.type– how the value is applied:ADD– adds the value to the current stat:stat += value.SET– sets the stat to the value directly.
itemRewardsobject optional Items to grant as a reward when this stage opens. Specified as a mapping of item identifiers to quantities.
"itemRewards": { "1001": 1, "1002": 3 }
Example with multiple stages:
"stages": [
{ "progress": 10 },
{
"progress": 20,
"updStats": [
{ "mode": "default", "name": "rating", "value": 3, "type": "ADD" },
{ "mode": "default", "name": "helper_stat", "value": 1, "type": "SET" }
]
},
{
"progress": 30,
"updStats": [
{ "mode": "default", "name": "penalty", "value": -2, "type": "ADD" }
]
}
]
Stage 1 opens at progress ≥ 10. No rewards.
Stage 2 opens at progress ≥ 20. Increases
ratingby 3 and setshelper_statto 1 indefaultmode.Stage 3 opens at progress ≥ 30. Decreases
penaltyby 2 indefaultmode.
Unlock Examples
Simple Unlocks
Simple unlocks track straightforward player achievements.
firstSoloKill – opens when the player makes their first kill in solo mode.
{
"name": "firstKill",
"type": "NORMAL",
"table": "global",
"mode": "solo",
"condition": "s.kills",
"stages": [{ "progress": 1 }]
}
Simple unlocks can also serve as helpers to split complex logic across multiple unlocks.
Periodic Unlocks
Periodic unlocks repeat their stages cyclically. Each stage opens when the condition result reaches or exceeds the stage’s calculated progress.
The progress of any arbitrary stage is calculated as:
arbitraryStageProgress = cycles_count × cycle_delta + stageIdx_progress
Where:
cycle_delta = lastStageProgress - progressPrevCycleStartStagecycles_count = floor((stage - startStageLoop) / (last_stage - startStageLoop + 1))stageIdx = (stage - startStageLoop) mod (last_stage - startStageLoop + 1) + startStageLoopstageIdx_progress– the progress of stagestageIdxfrom the unlock descriptionprogressPrevCycleStartStage– the progress of the stage just beforestartStageLoop
Simple Player Level
One cyclic stage, repeating indefinitely:
{
"name": "simplePlayerLevel",
"type": "NORMAL",
"table": "global",
"mode": "default",
"periodic": true,
"condition": "s.playerExp",
"stages": [{ "progress": 10 }]
}
Since there is only one stage and the cycle starts at stage 1,
progressPrevCycleStartStage = 0, so cycle_delta = 10 - 0 = 10.
Each stage opens at stage_num × 10:
Stage 1 — progress = 10
Stage 2 — progress = 20
Stage 3 — progress = 30
…
Progressive Player Level
Five stages, cycle starts at stage 4 (startStageLoop: 4):
{
"name": "progressivePlayerLevel",
"type": "NORMAL",
"table": "global",
"mode": "default",
"periodic": true,
"startStageLoop": 4,
"condition": "s.playerExp",
"stages": [
{ "progress": 5 },
{ "progress": 15 },
{ "progress": 30 },
{ "progress": 50 },
{ "progress": 100 }
]
}
progressPrevCycleStartStage = progress of stage 3 = 30, so
cycle_delta = 100 - 30 = 70. Stage progress:
Stage 1 — 5
Stage 2 — 15
Stage 3 — 30
Stage 4 — 50
Stage 5 — 100
Stage 6 — 120 (= 1 × 70 + 50)
Stage 7 — 170 (= 1 × 70 + 100)
Stage 8 — 190 (= 2 × 70 + 50)
…
Auto Rewarding Unlocks
expForLoot – automatically grants 15 experience points when the player loots 100 items.
{
"name": "expForLoot",
"type": "NORMAL",
"table": "global",
"mode": "default",
"condition": "s.lootedItems",
"autoRewarding": true,
"stages": [
{
"progress": 100,
"updStats": [
{ "mode": "default", "name": "playerExp", "value": 15, "type": "ADD" }
]
}
]
}
Sessional Unlocks
Progress is calculated from a single session’s statistics. Can be opened only once. See .
battleKiller – kill 10 enemies in one battle. Grants 1
sessionalUnlocksCount as a reward.
{
"name": "battleKiller",
"type": "SESSIONAL",
"table": "global",
"mode": "default",
"condition": "s.kills",
"stages": [
{
"progress": 10,
"updStats": [
{ "mode": "default", "name": "sessionalUnlocksCount", "value": 1, "type": "ADD" }
]
}
]
}
Multisessional Unlocks
Works like sessional unlocks but can be opened in every session.
battleBonus – opens in each session where the player’s rating is ≥ 5.
Grants 10 playerExp points.
{
"name": "battleBonus",
"type": "MULTISESSIONAL",
"table": "global",
"mode": "default",
"condition": "s.rating",
"stages": [
{
"progress": 5,
"updStats": [
{ "mode": "default", "name": "playerExp", "value": 10, "type": "ADD" }
]
}
]
}
Dynamic Unlocks
The unlock stage decreases when the condition result decreases.
karmaLevel – 3 stages that increase and decrease with the karma stat.
{
"name": "karmaLevel",
"type": "NORMAL",
"table": "global",
"mode": "default",
"condition": "s.karma",
"dynamicUnlock": true,
"stages": [{ "progress": 5 }, { "progress": 20 }, { "progress": 70 }]
}
Stage boundaries:
Stage 0 — karma < 5
Stage 1 — karma ≥ 5 and < 20
Stage 2 — karma ≥ 20 and < 70
Stage 3 — karma ≥ 70
Dynamic Progress
The unlock progress decreases with the condition, but the stage never decreases.
ratingLevel – once a stage is opened, it stays open regardless of how
playerRating changes.
{
"name": "ratingLevel",
"type": "NORMAL",
"table": "global",
"mode": "default",
"condition": "s.playerRating",
"dynamicProgress": true,
"stages": [{ "progress": 10 }, { "progress": 20 }, { "progress": 30 }]
}
Example scenario:
playerRating= 22 → stage = 2.playerRatingdrops to 12 → stage stays = 2.playerRatingrises to 25 → stage stays = 2 (25 < 30).playerRatingreaches 30 → stage = 3, permanently.
Dynamic Rewards
Works only with dynamicUnlock. Grants rewards every time a
stage is opened, including after it has been decreased and re-opened.
winSequence – grants 10 playerExp each time the player wins 5 consecutive
battles. Resets consecutiveWins after each reward.
{
"name": "winSequence",
"type": "NORMAL",
"table": "global",
"mode": "default",
"condition": "s.consecutiveWins",
"dynamicUnlock": true,
"dynamicRewards": true,
"stages": [
{
"progress": 5,
"updStats": [
{ "mode": "default", "name": "playerExp", "value": 10, "type": "ADD" },
{ "mode": "default", "name": "consecutiveWins", "value": 0, "type": "SET" }
]
}
]
}
Unlocks with Requirement
Grenade Killer
grenadeKiller – opens when the player kills 5 enemies with grenades. Rewards are only granted if winLimitHelper is also open.
{
"name": "grenadeKiller",
"type": "NORMAL",
"table": "global",
"mode": "default",
"condition": "s.grenadeKill",
"requirement": "winLimitHelper",
"stages": [
{
"progress": 5,
"updStats": [
{ "mode": "default", "name": "level", "value": 3, "type": "ADD" }
]
}
]
}
Using Meta
Use the meta field to pass game-specific data to the client, for
example an image path to display for the unlock:
{
"name": "pistolKiller",
"type": "NORMAL",
"table": "global",
"mode": "default",
"condition": "s.pistolKills",
"stages": [{ "progress": 10 }],
"meta": { "fileName": "/images/pistolKiller.png" }
}