Settings Reference

Complete documentation for tabs/settings.json.

AttributeSettings Schema

interface AttributeSettings {
  attributeNames: string[]                    // ✅ Thematic attribute names for the world
  startingAttributeValue: number              // ✅ Base attribute value (balanced: 0)
  startingAttributePoints: number             // ✅ Points to allocate at creation (balanced: 0)
  maxStartingAttribute: number                // ✅ Hard cap at creation (balanced: 0)
  attributeBonusModifier: number              // ✅ Multiplier for attribute bonus to checks (balanced: 2.5)
  lowAttributeThreshold: number               // ✅ Below this grants weakness traits (balanced: 8)
  lowAttributeTraits: Record<string, string>  // ✅ Weakness descriptions per attribute (required; use {} for none)
  attributeStatModifiers: Record<string, AttributeStatModifier>  // ✅ Keyed by attribute name (required; use {} for none)
  attributeDamageModifiers?: Record<string, number>  // ✅ Per-point % bonus to OUTGOING damage, keyed by attribute. e.g. { strength: 1 } = +1% damage per point of strength. Use positive values; negative values are ignored
  attributeDamageReductionModifiers?: Record<string, number> // ✅ Per-point % reduction to INCOMING damage, keyed by attribute. e.g. { dexterity: 1 } = -1% damage taken per point of dexterity. Use positive values; negative values are ignored
}

interface AttributeStatModifier {
  variable: string                            // Resource name (e.g. 'health' or custom resource)
  amount: number                              // Bonus per attribute point
}

Legend

  • ✅ Predefine-able: Can be set in config, used directly

SkillSettings Schema

interface SkillSettings {
  trainingCooldown: number                    // ✅ Ticks between training (balanced: 10)
  skillBonusModifier: number                  // ✅ Multiplier for skill level to checks (balanced: 1)
  maxSkillLevel: number                       // ✅ Maximum skill level (balanced: 999)
  maxSkillSuccessLevel: number                // ✅ Maximum absolute contribution any single skill, attribute, ability, random roll, or context modifier can make to a success check (balanced: 999)
  startingXPToLevelUpSkill: number            // ✅ XP for first skill level (balanced: 50)
  additionalXPRequiredPerSkillLevel: number   // ✅ Additional XP per level (balanced: 50)
  baseXPFromSkillUpgrade: number              // ✅ Bonus XP on skill level-up (balanced: 100)
  charXPPerSkillLevel: number                 // ✅ Character XP from skill progression (balanced: 100)
  baseChanceToLearnNewSkill: number           // ✅ Learning success rate 0-1 (balanced: 1)
  skillLearningBonusModifier: number          // ✅ Attribute contribution to learning (balanced: 1)
  xpFromNewSkill: number                     // ✅ Character XP awarded when learning a new skill (balanced: 200)
  skillTypeDifficultyBonus: Record<string, number>  // ✅ Bonus by skill type, always include "none": 0
  skillXPRewards: SkillXPRewards              // ✅ XP amounts by impact size
  newSkillGenerationEnabled: boolean          // ✅ Allow AI to invent skills beyond the config (default: true)
}

interface SkillXPRewards {
  small: number                               // ✅ XP for small impact (balanced: 50)
  medium: number                              // ✅ XP for medium impact (balanced: 100)
  large: number                               // ✅ XP for large impact (balanced: 150)
  huge: number                                // ✅ XP for huge impact (balanced: 200)
}

LocationSettings Schema

interface LocationSettings {
  regionSize: number                          // ✅ Region size in km (balanced: 100). Location x/y must stay within half this value of the origin; farther placements are flagged as off the map
  simpleRadius: number                        // ✅ Simple interaction radius in km (balanced: 5)
  complexRadius: number                       // ✅ Complex interaction radius in km (balanced: 10)
  regionLocationCount: number                 // ✅ Locations per region (world-specific)
  avgTravelDistance: number                   // ✅ Average distance between locations (balanced: 40)
  minTravelDistance: number                   // ✅ Minimum distance between locations (balanced: 20)
  newRegionGenerationEnabled: boolean         // ✅ Whether the engine pre-generates adjacent regions as players approach boundaries (default: true). Set false to keep the world bounded to predefined regions only.
  encountersEnabled: boolean                  // ✅ Whether random wilderness encounters can interrupt travel between locations (default: false)
  regionMapBorderFeatheringEnabled?: boolean  // ✅ Whether region map images use the feathered border and rounded frame treatment (default: false)
}

Removed: regionFactionCount. The engine no longer generates factions (see the factions skill), so nothing reads this field; drop it from existing configs.

ItemSettings Schema

interface ItemSettings {
  currencyName: string                        // ✅ Thematic currency name (world-specific)
  startingItems: StartingItem[]               // ✅ Items at character creation (balanced: [])
  itemCategories: string[]                    // ✅ Must include "Armor", "Consumable"
  itemSlots: ItemSlot[]                       // ✅ Must include 7 armor slots
}

interface StartingItem {
  name: string                                // Item key from items.json
  quantity: number                            // Number of items
}

interface ItemSlot {
  slot: string                                // Slot name (head, chest, etc.)
  category: string                            // Category from itemCategories
  quantity: number                            // Max items in slot
}

CombatSettings Schema

interface CombatSettings {
  baseCombatXP: number                        // ✅ Base XP for combat victory (balanced: 200)
  minCombatXP: number                         // ✅ Minimum XP from combat (balanced: 50)
  abilityCooldown: number                     // ✅ Cooldown given to AI-generated (learned) abilities, and the minimum turns between learning new ones. Does NOT affect predefined abilities (balanced: 0)
  abilityBonus: number                        // ✅ Default bonus given to AI-generated (learned) abilities. Does NOT scale predefined abilities, which use their own authored bonus (balanced: 10)
  npcDailyHealingAmount: number               // ✅ NPC healing per day (balanced: 999)
  damageTypes: string[]                       // ✅ Available damage types (world-specific). Use lowercase ASCII — matching against vulnerabilities/resistances/immunities is case-sensitive and unnormalized, so "Fire" ≠ "fire" and mismatches fail silently
  damageTypePresentation: Record<string, DamageTypePresentation>  // ✅ UI presentation per damage type, keyed by a damageTypes entry (required; use {} for none)
}

interface DamageTypePresentation {
  emoji?: string                              // ✅ Emoji shown next to the damage type in combat UI. Emoji characters only; text is rejected
}

OtherSettings Schema

interface OtherSettings {
  npcHealthPerLevel: number                   // ✅ NPC HP per level (balanced: 10)
  npcMinHealth: number                        // ✅ NPC base HP (balanced: 0)
  visualNovelModeByDefault?: boolean          // ✅ Applied once when a player first enters the game; unset lets the player's own device preference decide
}

Player HP scaling lives on the health resource in resourceSettings — maxValue is the level-1 maximum and gainPerLevel is the per-level growth. See the Resource schema in the ai-instructions reference.

ProgressionSettings Schema

Required section controlling character XP, level-ups, and what each level-up grants. Validation surfaces errors for bad values; if an invalid value slips into a saved config anyway, the engine silently falls back to that field’s default when the game loads.

interface ProgressionSettings {
  startingCharacterLevelUpRequirement: number // ✅ XP required to reach level 2 (balanced: 500)
  extraRequiredXPPerCharacterLevel: number    // ✅ Additional XP added per subsequent level; 0 = flat curve (balanced: 100)
  maxCharacterLevel: number                   // ✅ Leveling stops at this level (balanced: 999)
  abilityPointEveryLevels: number             // ✅ Grant ability points every N levels (balanced: 1)
  abilityPointsPerGrant: number               // ✅ Ability points per grant (balanced: 1)
  attributePointEveryLevels: number           // ✅ Grant attribute points every N levels (balanced: 5)
  attributePointsPerGrant: number             // ✅ Attribute points per grant (balanced: 1)
  maxAttributeValue: number                   // ✅ Cap on any attribute raised by spending points (balanced: 999)
  traitPickEveryLevels: number                // ✅ Grant trait picks every N levels (balanced: 10)
  traitPicksPerGrant: number                  // ✅ Trait picks per grant (balanced: 1)
  locationDiscoveryXP: number                 // ✅ XP each party member gains on first entering an area (balanced: 10)
  levelUpTraitPool: string[]                  // ✅ Trait names offered on level-up trait picks (balanced: [])
  milestoneTitles: MilestoneTitle[]           // ✅ Titles granted at exact levels (balanced: Initiate@1, Adept@10, Veteran@20, Expert@30, Master@40, Legend@50)
}

interface MilestoneTitle {
  levelGranted: number                        // Level at which the title is granted (unique positive integer)
  title: string                               // Displayed title (non-blank)
}

XP Curve

Reaching level 2 requires startingCharacterLevelUpRequirement XP; each later level adds extraRequiredXPPerCharacterLevel on top of the previous requirement (0 gives a flat curve — the only field allowed to be 0). Leveling stops entirely at maxCharacterLevel.

XP Sources

Characters gain XP from quest completion, major story events (party-wide), skill level-ups, and location discovery — every party member gains locationDiscoveryXP the first time the party enters each area (scaled up in NG+).

Level-Up Grants

On each level-up, the new level L is checked against each grant interval:

  • If L is a multiple of abilityPointEveryLevels, grant abilityPointsPerGrant ability points. The defaults (1/1) reproduce the classic one-ability-point-per-level behavior.
  • If L is a multiple of attributePointEveryLevels, grant attributePointsPerGrant attribute points — capped so banked points never exceed what could still be spent under maxAttributeValue.
  • If L is a multiple of traitPickEveryLevels, grant traitPicksPerGrant trait picks — capped by how many eligible pool traits remain.

Spending Points and Picks

Players spend attribute points in the Stats tab (batch spend; the spend is rejected if any attribute would exceed maxAttributeValue), unlock traits from levelUpTraitPool in the Traits tab (the offered list is filtered by trait requirements, unlockedBy, and excludedBy; effects apply immediately, just like starting traits), and choose a displayed title.

GOTCHA: an empty levelUpTraitPool (the default) means no trait picks are ever granted, regardless of traitPickEveryLevels. See the traits skill for authoring the pool traits themselves.

Milestone Titles

Titles are granted only when a level is hit exactly — a skipped milestone level is not back-granted later. A newly earned title is auto-selected and the player is prompted about it. Removing a title from the config retroactively hides it from players who already earned it. levelGranted values must be unique positive integers and titles must be non-blank.

Constraints

Every numeric field must be a positive whole number, except extraRequiredXPPerCharacterLevel which may be 0 (non-negative). levelUpTraitPool entries must name existing traits.

characterCreationMusic

characterCreationMusic?: 'fantasy' | 'nonfantasy'  // ✅ Background music played during character creation. Defaults to 'fantasy'

Sets which background music plays on the character-creation screen. 'fantasy' (the default) or 'nonfantasy'.

imageModelSource

imageModelSource?: string  // ✅ Image model used for every generated image (portraits, location/area images, region maps). One of: 'falai-gpt-image-2-low' | 'falai-gpt-image-2' | 'google-nano-banana-lite' | 'google-nano-banana-pro' | 'falai-flux-2-dev'

Optional top-level field that pins which image-generation model renders the world’s images while editing it. Games created from the world start with this choice as their default, but each game can be created with its own image-model selection. Leave it unset (or set to an unrecognized name) to fall back to the platform’s current default model.

worldVoices

worldVoices?: Record<string, WorldVoice>  // ✅ Voice presets keyed by an id you choose; referenced by npcs[].worldVoiceId and premadeCharacters[].worldVoiceId

interface WorldVoice {
  label: string                               // ✅ Display name shown to players (required). Use `label`, not `name`
  voiceTag: string                            // ✅ One of the character voice tags, e.g. 'male gravelly ancient' (required; trimmed). Picks the base voice
  instructions?: string                       // ✅ Free-text delivery guidance layered on the base voice
  speed?: number                              // ✅ Playback speed; clamped to 0.5-2, omit for the base voice default
  effects?: VoiceEffects                      // ✅ Audio effects chain; omit any sub-effect you do not use
  exposeInCharacterCreation?: boolean         // ✅ true lets players pick this preset for their own character at character creation. NPC and premade assignment works either way
}

interface VoiceEffects {
  pitch?: { enabled: boolean, semitones: number }                         // ✅ Pitch shift, -12..12 semitones
  reverb?: { enabled: boolean, space: 'room' | 'hall' | 'cavern', mix: number }  // ✅ mix is the wet/dry balance 0-1
  echo?: { enabled: boolean, delayMs: number, feedback: number, mix: number }    // ✅ delayMs 40-1000, feedback 0-0.85, mix 0-1
  eq?: {                                                                  // ✅ Six fixed bands: cuts outside, shelves inside, two bells in the middle
    enabled: boolean
    highPass: { enabled: boolean, frequency: number }
    lowShelf: { enabled: boolean, frequency: number, gainDb: number }
    bell1: { enabled: boolean, frequency: number, gainDb: number, q: number }
    bell2: { enabled: boolean, frequency: number, gainDb: number, q: number }
    highShelf: { enabled: boolean, frequency: number, gainDb: number }
    lowPass: { enabled: boolean, frequency: number }
  }                                                                       // ✅ Band gainDb -15..15, q 0.3-8
  distortion?: { enabled: boolean, drive: number }                        // ✅ drive 0 (clean) to 1
  output?: { enabled: boolean, gainDb: number, compressor: boolean }      // ✅ gainDb -12..12
}

A catalog of reusable voice presets. NPCs and premade characters reference a preset with worldVoiceId; the id must exist in worldVoices. Only presets with exposeInCharacterCreation: true appear as choices when players build their own character.

The engine sanitizes every preset on load: label and voiceTag are trimmed, speed and every effect parameter are clamped into the ranges above, a missing or non-numeric parameter falls back to its default rather than failing, and an effect with enabled: false is kept but inactive. The catalog size is capped, so keep it to voices the world actually uses.

Example:

{
  "gravel-elder": {
    "label": "Gravel Elder",
    "voiceTag": "male gravelly ancient",
    "instructions": "Slow, weary, every sentence costs effort.",
    "speed": 0.9,
    "effects": {
      "reverb": { "enabled": true, "space": "hall", "mix": 0.2 }
    },
    "exposeInCharacterCreation": false
  }
}

successLevelSettings

successLevelSettings: SuccessLevelSettings  // ✅ Required top-level field; the example world carries the stock ladder below

interface SuccessLevelSettings {
  firstSuccessfulTierId: string   // ✅ id of the lowest tier that counts as a success; it and every higher band succeed
  tiers: SuccessTier[]            // ✅ Contiguous whole-number score bands; list order does not matter, bands do
}

interface SuccessTier {
  id: string                      // ✅ Unique key, referenced by firstSuccessfulTierId
  name: string                    // ✅ Player-facing outcome name, unique ignoring case and surrounding spaces. action-success-level trigger conditions name tiers by this
  minScore: number | null         // ✅ Lowest adjusted score in the band; null only on the lowest tier
  maxScore: number | null         // ✅ Highest adjusted score in the band; null only on the highest tier. The next tier starts one point higher
  prompt: string                  // ✅ Narration note for this outcome;  is replaced with the acting character's name
  imageUrl?: string | null        // ✅ Optional image shown with the result, on official Latitude image hosting
}

The success ladder turns a player’s skill-check score into a named outcome. The score (see Skill Check Formula) is adjusted down by 2 per 10 character levels, and the tier whose band contains the adjusted score is the outcome. The tier’s name is the success level shown to players and recorded on the action, and its prompt is the note the narrator receives for that action. Simple actions (no check needed) and impossible actions do not use the ladder. NPC actions never use it either; they keep the engine’s fixed bands (see NPC Success Rolls).

Every tier from firstSuccessfulTierId upward is a success; tiers below it are failures. Successful tiers also carry a strength from 0 (the first successful tier) to 1 (the highest tier), spaced evenly across the successful tiers; a ladder with a single successful tier gives it full strength. Strength is what combat reads:

Action Effect of a successful tier with strength s
Attack or heal Base damage 8 + 20 × s (rounded), before the level bonus and the usual multipliers. A simple action uses 16. Failures deal nothing
Evade or defend Incoming damage reduced by 0.5 + 1.6 × s, capped at 1.0, so any success from roughly a third of the way up the successful tiers fully nullifies the hit. A simple action fully nullifies
preventAttack or subdue Full effect on any success
Buff Buff potency 0.2 + 0.8 × s; the damage boost granted by a buff intent is 0.1 + 0.4 × s
Combat conflict When a player’s defend or evade contests an NPC attack, a player success with strength 0.5 or more turns the NPC’s attack into a failure; a weaker success limits it to mixed results

The highest tier is the critical outcome; the lowest failing tier is the critical failure.

Bands are whole numbers and contiguous: each tier starts one point above the previous tier’s maxScore, with no gaps or overlaps, only the lowest tier has minScore: null, and only the highest tier has maxScore: null. Ids are unique, and names are unique ignoring case and surrounding spaces. During play the engine falls back to the stock ladder in place of a ladder that breaks these rules; an authored world must carry a valid ladder of its own.

Stock ladder (the one in the example world):

Tier id Band Outcome
Critical Failure critical-failure up to -66 failure
Failure failure -65 to -51 failure
Mixed Results mixed-results -50 to -26 success, strength 0 (first successful tier)
Basic Success basic-success -25 to -1 success, strength 0.25
Success success 0 to 24 success, strength 0.5
Great Success great-success 25 to 49 success, strength 0.75
Critical Success critical-success 50 and up success, strength 1

Renaming a tier changes what action-success-level conditions must name; a condition naming a tier the ladder no longer has stays inactive (see the triggers reference).

Skill Check Formula

successScore = totalBonus - totalDifficulty
adjustedScore = successScore - floor(characterLevel / 10) * 2   (placed on the success ladder)

totalBonus = skillBonus + attributeBonus + earlyGameBonus + randomBonus + modifierBonus

Where:
  skillBonus = skillBonusModifier * effectiveSkillLevel
  attributeBonus = (effectiveAttribute - 10) * attributeBonusModifier
  earlyGameBonus = 10 (if gameTick < 50, else 0)

The attribute is the one linked by the relevant skill, taken from the world’s skill definition or, failing that, the character’s own skill entry. The link resolves against the character’s attributes by exact key first, then ignoring case and spacing. A skill whose attribute matches none of the character’s attributes contributes no attribute bonus at all.

Combat Balance System

Player HP Formula

Player HP at level L = resourceSettings.health.maxValue
                     + gainPerLevel × (L - 1)
                     + milestoneHealthBonus

Where milestoneHealthBonus = floor(L / 5) × 5. maxValue is level-1 HP; gainPerLevel accrues from level 2 onward.

Example at level 20 with balanced values (maxValue=80, gainPerLevel=10):

  • Base: 80 + (10 × 19) = 270
  • Milestone: floor(20/5) × 5 = 20
  • Total: 290 HP

Player Damage Formula

Player DPR = 16.4 + (2.5 × level) + milestoneDamageBonus

Where milestoneDamageBonus = floor(level / 5) × 2

NPC damage scales more simply: +2.0 per level with no milestone bonuses. So a high-level player out-scales an equal-level NPC slightly (2.5/level + milestones vs. a flat 2.0/level).

These are engine constants, not configurable. They determine how fast players deal damage at each level.

NPC HP Formula

NPC HP = (npcHealthPerLevel × level + npcMinHealth) × tierHPModifier × healthMultiplier × difficultyHealthMultiplier

When an NPC has no authored hpMax, this is derived live whenever it’s needed (not frozen at world load), so HP always reflects the game’s current difficulty. An authored hpMax on an NPC with an authored level is used exactly as written; on a level-less NPC it only guarantees a minimum. See the npcs reference for details.

Tier HP Modifier
trivial 0.15
weak 0.5
average 1.0
strong 1.25
elite 1.5
boss 1.7
mythic 1.85

NPC Tier Damage Modifiers

Each tier also scales NPC damage output (engine constants, not configurable):

Tier Damage Modifier
trivial 0.65
weak 0.8
average 1.0
strong 1.12
elite 1.25
boss 1.4
mythic 1.55

Milestone Bonuses

Players receive milestone bonuses every 5 character levels (engine constants):

Milestone HP Bonus Damage Bonus
Every 5 levels +5 HP +2 damage

Example at level 25: 5 milestones = +25 HP, +10 damage on top of per-level scaling.

Difficulty Multipliers

NPC stats scale by encounter difficulty (engine constants, not configurable):

Difficulty NPC Damage NPC Health
very easy 0.7× 0.5×
easy 0.85× 0.75×
medium 1.0× 1.0×
hard 1.15× 1.25×
very hard 1.3× 1.5×

Level-Differential Damage Reduction

When an attacker hits a target that is a higher level than themselves, outgoing damage is reduced. Each level of difference adds less than the last (5% for the first, diminishing by 10% per step), and the total plateaus at 27.5% once the gap reaches 10 levels.

Levels target is above attacker Damage reduction
1 5.0%
2 9.5%
3 13.5%
4 17.0%
5 20.0%
6 22.5%
7 24.5%
8 26.0%
9 27.0%
10+ 27.5% (max)

Hitting a target at the same or lower level applies no reduction.

Impact

Every attack carries an impact value from 50 to 200 (100 = normal) that the AI assigns per-attack based on how the action is described. It multiplies damage by impact / 100, and applies to both player and NPC attacks.

Impact Multiplier
50 0.5×
100 1.0×
150 1.5×
200 2.0×

Evasion

A character that takes a defend / evade action on a turn reduces the incoming damage of attacks against them that turn. For players the reduction is 0.5 + 1.6 × strength of the resolved success tier, capped at 1.0 (see successLevelSettings); a reduction of 1.0 fully nullifies the hit (it lands but deals 0), and a failed roll gives no reduction. This is an active, per-turn choice driven by the defend roll, not a passive stat.

NPC Success Rolls

An NPC attack’s success level is fixed RNG each turn (NPCs have no skills or attributes to roll). NPC rolls use the engine’s own fixed bands and names, independent of the world’s successLevelSettings:

Outcome Chance
critical success 10%
great success 20%
success 40%
basic success 30%

The only way an NPC attack drops below “basic success” is combat conflict: when a player’s defend or evade action succeeds against it, the attacking NPC’s outcome is degraded. A player success with strength 0.5 or more (Success or better on the stock ladder) turns the NPC’s attack into a failure; a weaker success limits it to mixed results. The conflict only touches the contested NPC intent, so an NPC’s other actions that turn resolve normally.

Encounter Health Budget

The engine targets 4 rounds to kill (TTK) when sizing encounters:

Encounter HP Budget = 4 × effectivePartySize × playerExpectedDPR

Where effectivePartySize = playerCount + (npcAllyCount × 0.7)

NPC allies count at 70% effectiveness. This determines total enemy HP the engine distributes across NPCs in a generated encounter.

Skill XP Requirements

XP to reach skill level N = startingXPToLevelUpSkill + (N - 1) * additionalXPRequiredPerSkillLevel

With balanced values (50/50):

  • Level 1: 50 XP
  • Level 10: 500 XP
  • Level 30: 1,500 XP

Character Level XP Requirements

Both fields live in progressionSettings:

XP to reach character level N = startingCharacterLevelUpRequirement + (N - 2) * extraRequiredXPPerCharacterLevel

With balanced values (500/100):

  • Level 2: 500 XP
  • Level 5: 800 XP
  • Level 10: 1,300 XP

Leveling stops at maxCharacterLevel.

Power Level Success Rates

Power Level Skill Range vs Medium (30) vs Hard (60)
I 1-10 Fails most Fails almost all
II 10-30 Sometimes Rarely
III 30-40 Usually Sometimes
IV 40-60 Almost always Usually

Cross-References

Field References
itemSettings.itemCategories Used by tabs/items.json category field
itemSettings.itemSlots[].category Must match itemCategories values
combatSettings.damageTypes Used by NPC vulnerabilities/resistances/immunities and as the keys of combatSettings.damageTypePresentation
worldVoices keys Referenced by npcs[].worldVoiceId and premadeCharacters[].worldVoiceId
successLevelSettings.tiers[].name Named by action-success-level conditions in tabs/triggers.json
successLevelSettings.firstSuccessfulTierId A tiers[].id in the same section
attributeSettings.attributeNames Used in trait and skill attribute associations
progressionSettings.levelUpTraitPool Trait keys from tabs/traits.json (see the traits skill)
resourceSettings keys Used by ability and trait resource modifiers

This site uses Just the Docs, a documentation theme for Jekyll.