Properties

Properties serve as typed global variables for your game. Use them for game-wide values like currencies, settings, counters, and flags that need to persist across saves.

Properties are defined in the engine editor under General → Properties.


Key Features

Auto-Serializable & Reactive

Properties are automatically saved and loaded with your game. Any changes trigger reactive updates in the UI - no manual save/load code needed.

Live Schema Updates

If you add a new property during development and a player loads an old save file where that property didn't exist yet, the game will automatically initialize the newly added property with its default value.

This means you can safely add new properties without breaking existing saves.


Property Types

TypeDescriptionDefault
numberNumeric values with optional min/max bounds0
stringText values""
booleanTrue/false togglesfalse
arrayLists of values[]
objectComplex nested data (JSON){}

Number Properties

Number properties support additional options:

  • precision - Decimal places (0 = integers, 2 = two decimals)
  • min_value / max_value - Automatic clamping
  • can_overflow - Allow exceeding max (still respects min)
  • is_negative - UI hint that lower is better (e.g., damage taken)

Constant Properties

Mark a property as constant to create immutable game values that:

  • Cannot be modified at runtime - Attempts to change the value will log a warning and be ignored
  • Are excluded from save files - Smaller saves, and players always get the latest values
  • Can be overridden in exisiting save files by mods - Perfect for base stats, multipliers, and config values

Use Cases

  • Base damage/health values that mods can tweak
  • Game balance multipliers
  • Configuration constants (e.g., max inventory size)
  • Reference values that should never change during gameplay

Behavior

// Attempting to modify a constant property:
game.getProperty("base_damage").currentValue = 100;
// Console: "Cannot modify constant property 'base_damage'"
// Value remains unchanged

// Reading works normally:
const damage = game.getProperty("base_damage").currentValue; // Works fine

Checking if Constant

Use the skipSave property to check if a property is constant:

const prop = game.getProperty("base_damage");
if (prop.skipSave) {
  console.log("This is a constant property");
}

Default Value Behavior

Important: Changing the default value of a property that has already been initialized in a save file will not update that save value UNLESS it is flagged as 'constant'.

If you need to force a value change for non-constant properties in existing saves, use the game_initiated event:

game.on("game_initiated", () => {
  // Force update for existing saves if needed
  if (game.isNewGame === false) {
    let prop = game.getProperty("my_property");
    if (prop.currentValue === oldValue) {
      prop.currentValue = newValue;
    }
  }
});

Accessing Properties in Dungeons

Conditions

_property(gold) > 100
_property(settings.volume) >= 50

Placeholders

You have |property(gold)| gold remaining.
Volume: |property(settings.volume)|%

Actions

// String format (= set, > add, < subtract)
{ property: "gold>100" }           // add 100 to gold
{ property: "score=0, lives<1" }   // set score to 0, subtract 1 from lives

// Object format (for setting complex values)
{ property: { settings: { volume: 80, theme: "dark" } } }

API Reference

Getting a Property

const reputation = game.getProperty("reputation");

Properties

PropertyTypeDescription
idstringUnique identifier
namestring?Display name
typestring'number', 'boolean', 'string', 'array', or 'object'
precisionnumber?Decimal places (number type only)
isNegativeboolean?Whether lower values are better
defaultValueanyThe initial default value
canOverflowboolean?Whether value can exceed max
skipSavebooleantrue if this is a constant property (readonly)
currentValueanyThe current value (get/set directly)

Value Methods

getCurrentValue()

Get the current value.

const value = game.getProperty("gold").getCurrentValue();

setCurrentValue(value)

Set a new value. For numbers, automatically applies clamping and precision.

game.getProperty("gold").setCurrentValue(500);

addCurrentValue(amount) - Number only

Add to the current value. Use negative numbers to subtract.

game.getProperty("gold").addCurrentValue(100);  // gain 100
game.getProperty("gold").addCurrentValue(-50);  // lose 50

Min/Max Methods (Number only)

getMinValue() / setMinValue(value)

Get or set the minimum allowed value.

const min = game.getProperty("reputation").getMinValue(); // -100
game.getProperty("reputation").setMinValue(-50); // raise floor

getMaxValue() / setMaxValue(value)

Get or set the maximum allowed value.

const max = game.getProperty("reputation").getMaxValue(); // 100
game.getProperty("reputation").setMaxValue(150); // raise cap

addMinValue(amount) / addMaxValue(amount)

Adjust min/max by an amount.

game.getProperty("reputation").addMaxValue(20); // increase cap by 20

Utility Methods

getRatio() - Number only

Get the ratio of current value to maximum (0.0 to 1.0). Useful for progress bars.

const ratio = game.getProperty("reputation").getRatio(); // 0.75 = 75%
const barWidth = ratio * 100 + "%";

Returns 1 if max is not set or is 0.

switch() - Boolean only

Toggle between true and false.

game.getProperty("dark_mode").switch(); // toggle on/off

Examples

Reputation System

// Check if player can afford something
const reputation = game.getProperty("reputation");
if (reputation.currentValue >= 100) {
  // give item
}

Settings Object

// Store complex settings
const settings = game.getProperty("settings");
settings.currentValue = {
  volume: 80,
  theme: "dark",
  notifications: true
};

// Access nested value in conditions: _property(settings.volume) > 50

Progress Tracking

// Track completion with min/max
const progress = game.getProperty("chapter_progress");
progress.setMaxValue(10); // 10 objectives
progress.addCurrentValue(1); // complete one

// Show progress bar
const percent = progress.getRatio() * 100; // 10%, 20%, etc.