Anatomy of a defence: AC, saves, DR and the martial panel

From logic/ui-character-sheet.json (Kingmaker.UI.MVVM._VM.ServiceWindows.CharacterInfo) cross-checked against damage-model.json, difficulty-presets.json and unit-resistances.jsonl — build 20212986, patch 2.7.0x.

Anatomy of a hit follows the arrow on its way in. This one is the shield: what the character sheet's defence numbers are actually made of when Owlcat's rules compute them.

Everything on the sheet is a ModifiableValue

AC, the three saves, BAB, CMB, CMD — each is a Stats.* ModifiableValue: a base plus a stack of named modifiers whose per-descriptor breakdown the tooltip renders live (StatModifiersBreakdown). Nothing is precomputed: the sheet value you see is recomputed from the same modifier stacks the rules use, which is why buffs and gear never disagree with the maths.

Two sheet details worth knowing:

  • HP already contains the difficulty scaling. HitPoints.ModifiedValue folds in the active preset's enemy stat-adjustment HPMultiplier — the ×0.4–×1.0 multiplier table from difficulty settings.
  • Prereq checks read BaseValue, not the modified value — a temporary buff cannot unlock a feat (prerequisite system).

RuleCalculateAC: the situational matrix

Situational AC lives in RuleCalculateAC. The states the rules engine encodes:

| state | melee | ranged | |---|---|---| | prone | −4 | +4 | | helpless | −4 | −4 | | blindness | −2 | −2 |

And one weapon property with special authority: brilliant energy strips armor and shield bonuses from the target's AC entirely — the touch-attack cousin of ignoring enhancement.

The three visible AC flavours (normal/touch/flat-footed) are projections of the same modifier stack with different descriptors included.

Saves are three values, not a subsystem

Fortitude, Reflex and Will are plain ModifiableValues (SaveFortitude/SaveReflex/SaveWill) — same stacking grammar as AC, which is why buff-layer effects that add SavingThrowBonus descriptors compose with gear without special cases.

BAB, iteratives and the grapple twins

  • BAB sums class progression tables — every class's table contributes (multiclass addition), prestige included.
  • Iterative attacks are derived, not stored: attack count comes from RuleCalculateAttacksCount at one extra iterative per full 5 BAB.
  • CMB/CMD come from RuleCalculateCMB/RuleCalculateCMD over the same stats — they are computations on the sheet, not separate progressions.

Per-weapon attack bonus is assembled per swing: RuleCalculateAttackBonusWithoutTarget = BAB − iterative penalty + attack stat + enhancement + aggregated modifiers. Crit chance/multiplier come from RuleCalculateWeaponStats — the other half of anatomy of a hit.

DR and energy resistance

Damage reduction is a unit part, not a stat: UnitPartDamageReduction collects DR entries from feats, buffs and items, and the damage pipeline applies them post-roll (the resistance/hardness step of the damage model). Energy resistances follow the same pattern via their own stats — the numbers the bestiary census counts across monsters.

One UI quirk with rules weight: kinetic blade wielders get their damage block swapped at the UI layer (WeaponKineticBladeAbilityKineticist.CollectUIDamageInfo) — the sheet shows blast math, not the weapon's nominal dice.

What this explains

  • Why a buff's AC bonus can be stripped by a single weapon property (brilliant energy removes whole descriptor groups).
  • Why enemies hit absurdly hard on Unfair but don't have more HP than the multiplier says: the preset table only carries what it carries — see enemy brains for how they decide to swing.
  • Why feat prerequisites ignore your buffed stats while combat does not: two different reads of the same value object.

Related database section: Classes — e.g. Dragon.