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:

  1. Add unlock descriptions to the unlocks config.

  2. 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

name string required

Name of the unlock. Must be unique.

type string required

Type of the unlock. Possible values:

  • NORMAL – a standard unlock. Example.

  • SESSIONAL – progress is calculated from a single session’s statistics. Can be opened only once. Example.

  • MULTISESSIONAL – works like SESSIONAL but can be opened in every session. Example.

table string required

Name of the table used to calculate the unlock condition. See Statistics Tables.

condition string required

A quirrel expression used to calculate unlock progress. Uses the same format as stats condition. Maximum 512 characters.

stages array required

Array of unlock stages. Must have at least one stage, maximum 1,000 stages. See Stage Format.

mode string optional

Name of the game mode used to calculate the unlock condition. See Statistics Modes.

hidden bool optional

If true, the unlock is hidden from the user. Use this for helper unlocks that implement complex mechanics. Defaults to false. Examples.

periodic bool optional

If true, unlock stages are cyclic – they repeat after the last stage is reached. Defaults to false. Example.

startStageLoop positive int optional

The stage number at which the cycle begins. Only applies when periodic is true. If not set, the cycle starts from stage 1. Example.

autoRewarding bool optional

If true, stage rewards are granted automatically when the stage opens. Defaults to false. If false, use the action to grant rewards manually. Example.

dynamicUnlock bool optional

If true, both the unlock progress and stage decrease when the condition expression result decreases. Defaults to false. Example.

dynamicProgress bool optional

If true, only the unlock progress decreases when the condition result decreases – the stage remains unchanged. Defaults to false. Example.

dynamicRewards bool optional

If true, rewards are granted every time a stage is opened, including after the stage has been decreased and re-opened. Only applies when dynamicUnlock is true. Defaults to false. Example.

showForAll bool optional

If true, the unlock is visible to other users. Defaults to false. To request another user’s unlocks, use the action.

requirement string 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 &.

iconUrl string (URL) optional

URL of the icon displayed for this unlock on the client.

meta JSON 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.

namespace string optional

Namespace of the unlock. Used to organize unlocks across different configurations.

personal string optional

Type of the personal unlock generator this unlock belongs to. Must match the type field of a personalUnlockGenerators entry in the tables config. Defaults to common.

newbie bool 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 when personal is set.

steamAchievement bool optional

If true, the unlock is sent to Steam as a completed achievement when it is fully opened. Only applies to Steam accounts. Defaults to false.

showByAchvService bool optional

If true, the unlock is visible in the achievement service. Sent to the client as part of the unlock description. Defaults to false.


Stage Format

Each stage is opened when the condition expression result reaches or exceeds the stage’s progress value.

progress positive int required

The threshold value at which this stage opens.

updStats array 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.

itemRewards object 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 rating by 3 and sets helper_stat to 1 in default mode.

  • Stage 3 opens at progress ≥ 30. Decreases penalty by 2 in default mode.


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.


Hidden Unlocks

Win Limit Helper

winLimitHelper – opens when the player wins 10 battles in squad mode. Hidden from the user. Used as a helper to block other unlock rewards. See grenadeKiller.

{
  "name": "winLimitHelper",
  "type": "NORMAL",
  "table": "global",
  "mode": "squad",
  "hidden": true,
  "condition": "s.wins",
  "stages": [{ "progress": 10 }]
}

Premium Helper

premiumHelper – opens when the player has an active premium. Hidden from the user. Uses dynamicUnlock because the premium stat can increase and decrease. Used as a helper to block other unlock rewards. See premiumKiller.

{
  "name": "premiumHelper",
  "type": "NORMAL",
  "table": "global",
  "mode": "default",
  "hidden": true,
  "condition": "s.premium",
  "dynamicUnlock": true,
  "stages": [{ "progress": 1 }]
}

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 - progressPrevCycleStartStage

  • cycles_count = floor((stage - startStageLoop) / (last_stage - startStageLoop + 1))

  • stageIdx = (stage - startStageLoop) mod (last_stage - startStageLoop + 1) + startStageLoop

  • stageIdx_progress – the progress of stage stageIdx from the unlock description

  • progressPrevCycleStartStage – the progress of the stage just before startStageLoop

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:

  1. playerRating = 22 → stage = 2.

  2. playerRating drops to 12 → stage stays = 2.

  3. playerRating rises to 25 → stage stays = 2 (25 < 30).

  4. playerRating reaches 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" }
      ]
    }
  ]
}

Premium Killer

premiumKiller – opens when the player kills 100 enemies. Rewards are only granted if premiumHelper is also open.

{
  "name": "premiumKiller",
  "type": "NORMAL",
  "table": "global",
  "mode": "default",
  "condition": "s.kill",
  "requirement": "premiumHelper",
  "stages": [
    {
      "progress": 100,
      "updStats": [
        { "mode": "default", "name": "premiumLevel", "value": 5, "type": "ADD" }
      ]
    }
  ]
}

Premium Grenade Killer

premiumGrenadeKiller – opens when the player kills 20 enemies with grenades. Requires both winLimitHelper and premiumHelper to be open.

{
  "name": "premiumGrenadeKiller",
  "type": "NORMAL",
  "table": "global",
  "mode": "default",
  "condition": "s.grenadeKill",
  "requirement": "winLimitHelper & premiumHelper",
  "stages": [
    {
      "progress": 20,
      "updStats": [
        { "mode": "default", "name": "premiumLevel", "value": 10, "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" }
}