{"tab":"mechanics","section":"attributeSettings","title":"Attributes","summary":"Attributes are the core stats of your system - strength, dexterity, intelligence, or whatever names fit your world. They drive skill-roll modifiers and optionally scale resource pools.","kind":"schema","uiLocation":"Mechanics → Attributes","uiSubtitle":"\"Character attributes\"","editor":"JSON only","related":[{"section":"skills","note":"attributes feed into skill checks"},{"section":"traits","note":"traits can grant attribute bonuses"},{"section":"npcs","note":"NPC entries include attribute scores"}],"wikiUrl":"/mechanics/attributeSettings","schema":{"_type":"intersection","parts":[{"_type":"required","fields":{"attributeNames":{"_type":"array","of":"string"},"startingAttributeValue":"number","startingAttributePoints":"number","attributeStatModifiers":{"_type":"record","domain":"string","codomain":{"_type":"required","fields":{"variable":"string","amount":"number"}}},"maxStartingAttribute":"number","lowAttributeThreshold":"number","lowAttributeTraits":{"_type":"record","domain":"string","codomain":"string"},"attributeBonusModifier":"number"}},{"_type":"partial","fields":{"attributeDamageModifiers":{"_type":"record","domain":"string","codomain":"number"},"attributeDamageReductionModifiers":{"_type":"record","domain":"string","codomain":"number"}}}]},"sizeLimits":[{"id":"attributeNamesCount","group":"Settings Caps","label":"`attributeSettings.attributeNames` (entry count)","measure":"count","unit":"entries","enforced":30,"display":30,"sections":["mechanics/attributeSettings"]},{"id":"attributeNameEntry","group":"Settings Caps","label":"`attributeSettings.attributeNames.*` (each)","measure":"rawChars","enforced":64,"display":64,"sections":["mechanics/attributeSettings"]}],"blocks":[{"type":"example","lang":"json","code":"{\n  \"attributeNames\": [\"strength\", \"dexterity\", \"constitution\", \"intelligence\", \"wisdom\", \"charisma\"],\n  \"maxStartingAttribute\": 16,\n  \"startingAttributeValue\": 8,\n  \"lowAttributeThreshold\": 2,\n  \"lowAttributeTraits\": {\n    \"strength\": \"Frail\",\n    \"constitution\": \"Sickly\",\n    \"intelligence\": \"Slow Learner\",\n    \"charisma\": \"Off-Putting\"\n  },\n  \"attributeBonusModifier\": 2.5,\n  \"attributeStatModifiers\": {\n    \"strength\": { \"amount\": 2, \"variable\": \"health\" },\n    \"constitution\": { \"amount\": 1, \"variable\": \"health\" },\n    \"wisdom\": { \"amount\": 2, \"variable\": \"mana\" },\n    \"intelligence\": { \"amount\": 1, \"variable\": \"mana\" }\n  },\n  \"startingAttributePoints\": 0,\n  \"attributeDamageModifiers\": {\n    \"strength\": 2\n  },\n  \"attributeDamageReductionModifiers\": {\n    \"dexterity\": 1\n  }\n}"},{"type":"fields","fields":[{"name":"attributeNames","tooltip":"Can be fully renamed or expanded.","md":"Can be fully renamed or expanded. Attribute names inform how the AI decides which is relevant to an action. **All attribute name strings must be lowercase.** The engine normalises attribute lookups to lowercase internally; using mixed or title case (e.g. `\"Intellect\"` instead of `\"intellect\"`) causes silent mismatches with `skills[*].attribute` and `attributeStatModifiers` lookups. The same lowercase strings must be used consistently everywhere attributes are referenced: `attributeSettings.attributeNames`, `attributes` dict keys, `skills[*].attribute`, `traits[*].attributes[*].attribute`, `items[*].bonuses[*].variable` (when `type: \"attribute\"`), and `attributeSettings.attributeStatModifiers` keys."},{"name":"startingAttributeValue","tooltip":"The base value every attribute starts at before trait modifiers are applied.","md":"The base value every attribute starts at before trait modifiers are applied. **Required.**"},{"name":"lowAttributeThreshold","tooltip":"Attribute score below which a character is considered \"low\" in that attribute.","md":"Attribute score below which a character is considered \"low\" in that attribute."},{"name":"lowAttributeTraits","tooltip":"Keyed map of traits automatically applied to characters whose score falls below lowAttributeThreshold.","md":"Keyed map of traits automatically applied to characters whose score falls below `lowAttributeThreshold`. Can be used to add narrative or mechanical penalties for dump stats. Leave `{}` to disable."},{"name":"attributeStatModifiers","tooltip":"Maps each attribute to a resource boost.","md":"Maps each attribute to a resource boost. Each entry requires `variable` (the resource name) and `amount` (the boost per attribute point). No `type` field is needed.\n\n- `variable` in modifiers: `health`, or any custom resource name.\n- `amount: 2` = \"for every 1 point of this attribute, boost the resource by 2.\"\n\n> **⚠️ Warning (`attributeStatModifiers` does NOT take a `type` field):** Each entry has only `variable` (the resource name) and `amount` (the bonus per attribute point above 10). Adding `type: \"characterResources\"` or any other type field is silently ignored — the entry still parses, but the extra field has no effect."},{"name":"attributeDamageModifiers","tooltip":"Optional.","md":"Optional. Maps attribute names to a percentage bonus applied to the player's outgoing damage. `{ \"strength\": 2 }` gives +2% damage per strength point — a character with strength 12 deals +24% damage. Multiple configured attributes stack multiplicatively. Negative values are ignored. Calculated on buffed attribute values.\n\n> **📋 Note (damage modifier stacking):** `attributeDamageModifiers` applies a global percentage multiplier to all outgoing damage and stacks with — but does not replace — the existing per-skill attribute damage bonus for combat skills. The per-skill bonus is `max(0, floor((effectiveAttr - 6) / 2))` added directly to damage, calculated from whichever attribute the skill uses. The global modifier applies on top of that. Both scale with the same buffed attribute value."},{"name":"attributeDamageReductionModifiers","tooltip":"Optional.","md":"Optional. Maps attribute names to a percentage reduction in incoming damage to the player. `{ \"dexterity\": 1 }` gives -1% incoming damage per dexterity point — a character with dexterity 14 takes 14% less damage. Multiple attributes stack multiplicatively. Negative values are ignored.\n\n> **📋 Note (renamed field):** This field was previously called `attributeEvasionModifiers`. The behaviour is identical; only the key name changed. Update any older world that still uses the old key.\n\nKeys in both modifier maps must match an entry in `attributeNames` exactly. A misspelled or unknown key (e.g. `strenght`) is silently ignored by the engine and contributes nothing, so the validator flags any key not found in `attributeNames`."}]}],"body":"## Example\n\n```json\n{\n  \"attributeNames\": [\"strength\", \"dexterity\", \"constitution\", \"intelligence\", \"wisdom\", \"charisma\"],\n  \"maxStartingAttribute\": 16,\n  \"startingAttributeValue\": 8,\n  \"lowAttributeThreshold\": 2,\n  \"lowAttributeTraits\": {\n    \"strength\": \"Frail\",\n    \"constitution\": \"Sickly\",\n    \"intelligence\": \"Slow Learner\",\n    \"charisma\": \"Off-Putting\"\n  },\n  \"attributeBonusModifier\": 2.5,\n  \"attributeStatModifiers\": {\n    \"strength\": { \"amount\": 2, \"variable\": \"health\" },\n    \"constitution\": { \"amount\": 1, \"variable\": \"health\" },\n    \"wisdom\": { \"amount\": 2, \"variable\": \"mana\" },\n    \"intelligence\": { \"amount\": 1, \"variable\": \"mana\" }\n  },\n  \"startingAttributePoints\": 0,\n  \"attributeDamageModifiers\": {\n    \"strength\": 2\n  },\n  \"attributeDamageReductionModifiers\": {\n    \"dexterity\": 1\n  }\n}\n```\n\n## Fields\n\n### attributeNames\n\nCan be fully renamed or expanded. Attribute names inform how the AI decides which is relevant to an action. **All attribute name strings must be lowercase.** The engine normalises attribute lookups to lowercase internally; using mixed or title case (e.g. `\"Intellect\"` instead of `\"intellect\"`) causes silent mismatches with `skills[*].attribute` and `attributeStatModifiers` lookups. The same lowercase strings must be used consistently everywhere attributes are referenced: `attributeSettings.attributeNames`, `attributes` dict keys, `skills[*].attribute`, `traits[*].attributes[*].attribute`, `items[*].bonuses[*].variable` (when `type: \"attribute\"`), and `attributeSettings.attributeStatModifiers` keys.\n\n### startingAttributeValue\n\nThe base value every attribute starts at before trait modifiers are applied. **Required.**\n\n### lowAttributeThreshold\n\nAttribute score below which a character is considered \"low\" in that attribute.\n\n### lowAttributeTraits\n\nKeyed map of traits automatically applied to characters whose score falls below `lowAttributeThreshold`. Can be used to add narrative or mechanical penalties for dump stats. Leave `{}` to disable.\n\n### attributeStatModifiers\n\nMaps each attribute to a resource boost. Each entry requires `variable` (the resource name) and `amount` (the boost per attribute point). No `type` field is needed.\n\n- `variable` in modifiers: `health`, or any custom resource name.\n- `amount: 2` = \"for every 1 point of this attribute, boost the resource by 2.\"\n\n> **⚠️ Warning (`attributeStatModifiers` does NOT take a `type` field):** Each entry has only `variable` (the resource name) and `amount` (the bonus per attribute point above 10). Adding `type: \"characterResources\"` or any other type field is silently ignored — the entry still parses, but the extra field has no effect.\n\n### attributeDamageModifiers\n\nOptional. Maps attribute names to a percentage bonus applied to the player's outgoing damage. `{ \"strength\": 2 }` gives +2% damage per strength point — a character with strength 12 deals +24% damage. Multiple configured attributes stack multiplicatively. Negative values are ignored. Calculated on buffed attribute values.\n\n> **📋 Note (damage modifier stacking):** `attributeDamageModifiers` applies a global percentage multiplier to all outgoing damage and stacks with — but does not replace — the existing per-skill attribute damage bonus for combat skills. The per-skill bonus is `max(0, floor((effectiveAttr - 6) / 2))` added directly to damage, calculated from whichever attribute the skill uses. The global modifier applies on top of that. Both scale with the same buffed attribute value.\n\n### attributeDamageReductionModifiers\n\nOptional. Maps attribute names to a percentage reduction in incoming damage to the player. `{ \"dexterity\": 1 }` gives -1% incoming damage per dexterity point — a character with dexterity 14 takes 14% less damage. Multiple attributes stack multiplicatively. Negative values are ignored.\n\n> **📋 Note (renamed field):** This field was previously called `attributeEvasionModifiers`. The behaviour is identical; only the key name changed. Update any older world that still uses the old key.\n\nKeys in both modifier maps must match an entry in `attributeNames` exactly. A misspelled or unknown key (e.g. `strenght`) is silently ignored by the engine and contributes nothing, so the validator flags any key not found in `attributeNames`."}