Stats Config Format

Overview

Player statistics are a core part of modern game design. They power mechanics such as character leveling, abilities, achievements, leaderboards, and player rewards.

This article describes the stats config format and provides examples of common stat types. For details on how the game interacts with the statistics server, see the: .


Adding Stats

To use and store statistics, you need to:

  1. Add stat descriptions to the stats config.

  2. Deploy configs to services.


Stat Description Format

{
  "name": "kills_death_rating",
  "type": "FLOAT",
  "minValue": 0,
  "maxValue": 1,
  "defValue": 0,
  "window": 20,
  "onlyIncrement": true,
  "leaderboard": true,
  "showForAll": true,
  "allowChangeFromClient": false,
  "meta": {},
  "condition": "s.death ? s.kills/s.death : 0",
  "gameModesEnabled": ["solo"],
  "gameModesDisabled": ["duo"]
}

Fields

name string required

Name of the stat. Must be unique across all stats.

type string required

Type of the stat. Possible values:

  • INT – Integer stat

  • FLOAT – Floating-point stat

  • AVGRATE – Stat calculated as a moving average

minValue int or float optional

Minimum allowed value of the stat. The stat value will never fall below this.

maxValue int or float optional

Maximum allowed value of the stat. The stat value will never exceed this.

defValue int or float optional

Initial value of the stat. Defaults to 0 if not set.

window float optional

Coefficient used to calculate the moving average. Must be greater than 0. Only applies when type is AVGRATE. See moving average calculation.

onlyIncrement bool optional

If true, the stat value can only increase – it can never be decreased. Defaults to false.

leaderboard bool optional

If true, the stat is included in the leaderboard. Defaults to false.

showForAll bool optional

If true, the stat is visible to other users. Defaults to false.

Note

To request another user’s statistics, use the action. Stats are returned only for public tables and modes.

allowChangeFromClient bool optional

If true, allows the client to modify this stat directly. Defaults to false.

Warning

Use this only for non-critical statistics. The client is not protected against tampering, so players can manipulate stats set this way. To change a stat from the client, use the action.

meta json object optional

Arbitrary data attached to the stat. Use this to pass custom information to the game client – for example, display settings or UI hints.

condition string optional

An expression that calculates the stat’s value from other stats. When set, the stat becomes read-only – external updates to it are silently ignored. See Condition Format for syntax and examples.

gameModesEnabled array of string optional

If set, the stat is only tracked in the listed game modes.

gameModesDisabled array of string optional

If set, the stat is not tracked in the listed game modes.

Note

gameModesDisabled is only applied when gameModesEnabled is empty or not set. If both fields are present, gameModesEnabled takes precedence.


Condition Format

Condition is a quirrel language expression. The expression must return a value compatible with the stat’s declared type. Reference other stats using s.stat_name syntax.

Examples

Kill/death ratio:

condition: s.death ? s.kills/s.death.tofloat() : 0

Score-weighted rating (requires at least 10 battles):

condition: s.battles_count > 10 ? s.battles_count*s.score : 100

Stat Examples

Simple Stats

Simple stats store raw player data. They can be used as inputs for calculated stats and unlocks.

battle_level

Player’s level in battle. Type: INT. Can be decreased. Not shown in leaderboard.

{
  "name": "battle_level",
  "type": "INT"
}
kills

Total number of player kills. Type: INT. Can only increase. Shown in leaderboard.

{
  "name": "kills",
  "type": "INT",
  "onlyIncrement": true,
  "leaderboard": true
}
accuracy

Player’s shooting accuracy. Type: FLOAT. Clamped between 0.2 and 1.0. Not shown in leaderboard.

{
  "name": "accuracy",
  "type": "FLOAT",
  "minValue": 0.2,
  "maxValue": 1.0,
  "defValue": 0.2
}

Moving Average Stats

relativePlayerPlace

Player’s average finishing place, weighted over recent sessions. Type: AVGRATE. Shown in leaderboard.

{
  "name" : "relativePlayerPlace",
  "type" : "AVGRATE",
  "window" : 20,
  "leaderboard" : true
}

Moving Average Calculation

The moving average is calculated using:

  • oldVal — the current stored value of the stat

  • val — the new incoming value

  • len — the duration, set in the

  • window — the coefficient defined in the stat config

Formula:

newVal = len/window < 1 ? val/window + oldVal(1- len/window): val/len

Behavior:

  • If len >= window: oldVal is ignored; the result equals val / len.

  • If len < window: oldVal has significant weight; the result changes gradually.


Calculable Stats

Calculable stats derive their value from other stats using a condition expression. They are typically used for ratings and averages.

Win Rate

Tracks the ratio of wins to total battles.

Supporting stats:

battle_count

Total number of player’s battles. Type: INT. Used for calculation.

{
  "name" : "battle_count",
  "type" : "INT",
  "onlyIncrement" : true
}
battle_wins

Total number of player’s wins in battles. Type: INT. Used for calculation.

{
  "name" : "battle_wins",
  "type" : "INT",
  "onlyIncrement" : true
}

Calculable stat:

win_rate

Player’s battle win rating. Type: FLOAT. Shown in leaderboard.

{
  "name" : "win_rate",
  "type" : "FLOAT",
  "leaderboard" : true,
  "condition" : "s.battle_count ? s.battle_wins/s.battle_count.tofloat() : 0"
}

Average Score per Life

Tracks the player’s average score per life spent.

Supporting stats:

lifes_count

Total number of lives spent by the player. Type: INT. Used for calculation.

{
  "name" : "lifes_count",
  "type" : "INT",
  "onlyIncrement" : true
}
total_score

Total game score. Type: INT. Used for calculation.

{
  "name" : "total_score",
  "type" : "INT",
  "onlyIncrement" : true
}

Calculable stat:

avg_score

Average player score per life. Type: FLOAT. Shown in leaderboard.

{
  "name" : "avg_score",
  "type" : "FLOAT",
  "leaderboard" : true,
  "condition" : "s.lifes_count ? s.total_score/s.lifes_count.tofloat() : 0"
}

Special Stats

Warning

The __ prefix is reserved for special stats. Do not use it for game-specific stats.

__leaderboardGroup

Groups players into leaderboard segments. Documentation will be added soon.