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
| Type | Description | Default |
|---|---|---|
number | Numeric values with optional min/max bounds | 0 |
string | Text values | "" |
boolean | True/false toggles | false |
array | Lists of values | [] |
object | Complex 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
| Property | Type | Description |
|---|---|---|
id | string | Unique identifier |
name | string? | Display name |
type | string | 'number', 'boolean', 'string', 'array', or 'object' |
precision | number? | Decimal places (number type only) |
isNegative | boolean? | Whether lower values are better |
defaultValue | any | The initial default value |
canOverflow | boolean? | Whether value can exceed max |
skipSave | boolean | true if this is a constant property (readonly) |
currentValue | any | The 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.