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:
Add stat descriptions to the stats config.
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
namestring required Name of the stat. Must be unique across all stats.
typestring required Type of the stat. Possible values:
INT– Integer statFLOAT– Floating-point statAVGRATE– Stat calculated as a moving average
minValueint or float optional Minimum allowed value of the stat. The stat value will never fall below this.
maxValueint or float optional Maximum allowed value of the stat. The stat value will never exceed this.
defValueint or float optional Initial value of the stat. Defaults to
0if not set.windowfloat optional Coefficient used to calculate the moving average. Must be greater than
0. Only applies whentypeisAVGRATE. See moving average calculation.onlyIncrementbool optional If
true, the stat value can only increase – it can never be decreased. Defaults tofalse.leaderboardbool optional If
true, the stat is included in the leaderboard. Defaults tofalse.showForAllbool optional If
true, the stat is visible to other users. Defaults tofalse.allowChangeFromClientbool optional If
true, allows the client to modify this stat directly. Defaults tofalse.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.
metajson 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.
conditionstring 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.
gameModesEnabledarray of string optional If set, the stat is only tracked in the listed game modes.
gameModesDisabledarray of string optional If set, the stat is not tracked in the listed game modes.
Note
gameModesDisabledis only applied whengameModesEnabledis empty or not set. If both fields are present,gameModesEnabledtakes 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_levelPlayer’s level in battle. Type:
INT. Can be decreased. Not shown in leaderboard.{ "name": "battle_level", "type": "INT" }
killsTotal number of player kills. Type:
INT. Can only increase. Shown in leaderboard.{ "name": "kills", "type": "INT", "onlyIncrement": true, "leaderboard": true }
accuracyPlayer’s shooting accuracy. Type:
FLOAT. Clamped between0.2and1.0. Not shown in leaderboard.{ "name": "accuracy", "type": "FLOAT", "minValue": 0.2, "maxValue": 1.0, "defValue": 0.2 }
Moving Average Stats
relativePlayerPlacePlayer’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 statval— the new incoming valuelen— the duration, set in thewindow— the coefficient defined in the stat config
Formula:
newVal = len/window < 1 ? val/window + oldVal(1- len/window): val/len
Behavior:
If
len >= window:oldValis ignored; the result equalsval / len.If
len < window:oldValhas 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_countTotal number of player’s battles. Type:
INT. Used for calculation.{ "name" : "battle_count", "type" : "INT", "onlyIncrement" : true }
battle_winsTotal number of player’s wins in battles. Type:
INT. Used for calculation.{ "name" : "battle_wins", "type" : "INT", "onlyIncrement" : true }
Calculable stat:
win_ratePlayer’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_countTotal number of lives spent by the player. Type:
INT. Used for calculation.{ "name" : "lifes_count", "type" : "INT", "onlyIncrement" : true }
total_scoreTotal game score. Type:
INT. Used for calculation.{ "name" : "total_score", "type" : "INT", "onlyIncrement" : true }
Calculable stat:
avg_scoreAverage 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.
__leaderboardGroupGroups players into leaderboard segments. Documentation will be added soon.