{
  "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.",
  "uiLocation": "Mechanics → Attributes",
  "uiSubtitle": "\"Character attributes\"",
  "editor": "JSON only",
  "sizeLimits": [
    {
      "field": "`attributeSettings.attributeNames` (entry count)",
      "limit": "30 entries",
      "sections": [
        "mechanics/attributeSettings"
      ]
    },
    {
      "field": "`attributeSettings.attributeNames.*` (each)",
      "limit": "64 chars",
      "sections": [
        "mechanics/attributeSettings"
      ]
    }
  ],
  "related": "skills - attributes feed into skill checks; traits - traits can grant attribute bonuses; npcs - 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"
          }
        }
      }
    ]
  },
  "body": "## Example\r\n\r\n```json\r\n{\r\n  \"attributeNames\": [\"strength\", \"dexterity\", \"constitution\", \"intelligence\", \"wisdom\", \"charisma\"],\r\n  \"maxStartingAttribute\": 16,\r\n  \"startingAttributeValue\": 8,\r\n  \"lowAttributeThreshold\": 2,\r\n  \"lowAttributeTraits\": {\r\n    \"strength\": \"Frail\",\r\n    \"constitution\": \"Sickly\",\r\n    \"intelligence\": \"Slow Learner\",\r\n    \"charisma\": \"Off-Putting\"\r\n  },\r\n  \"attributeBonusModifier\": 2.5,\r\n  \"attributeStatModifiers\": {\r\n    \"strength\": { \"amount\": 2, \"variable\": \"health\" },\r\n    \"constitution\": { \"amount\": 1, \"variable\": \"health\" },\r\n    \"wisdom\": { \"amount\": 2, \"variable\": \"mana\" },\r\n    \"intelligence\": { \"amount\": 1, \"variable\": \"mana\" }\r\n  },\r\n  \"startingAttributePoints\": 27,\r\n  \"attributeDamageModifiers\": {\r\n    \"strength\": 2\r\n  },\r\n  \"attributeDamageReductionModifiers\": {\r\n    \"dexterity\": 1\r\n  }\r\n}\r\n```\r\n\r\n## Fields\r\n\r\n### attributeNames\r\n\r\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.\r\n\r\n### startingAttributeValue\r\n\r\nBase value before point buy. **Required.**\r\n\r\n### lowAttributeThreshold\r\n\r\nAttribute score below which a character is considered \"low\" in that attribute.\r\n\r\n### lowAttributeTraits\r\n\r\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.\r\n\r\n### attributeStatModifiers\r\n\r\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.\r\n\r\n- `variable` in modifiers: `health`, or any custom resource name.\r\n- `amount: 2` = \"for every 1 point of this attribute, boost the resource by 2.\"\r\n\r\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.\r\n\r\n### attributeDamageModifiers\r\n\r\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.\r\n\r\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.\r\n\r\n### attributeDamageReductionModifiers\r\n\r\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.\r\n\r\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.\r\n\r\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`."
}