Concepts → XCOM 2 outcome model
The XCOM 2 outcome model — hit / crit / graze / miss
XCOM 2 splits each shot into four explicit outcomes. The displayed hit-chance is one of three probability buckets, not a binary hit/miss split. Once graze is on the table, the variance of low-percentage shots looks materially different from what the tooltip suggests.
The 4-way split
Each shot rolls against four buckets:
-
Crit — full damage doubled. Conditional on
a hit:
P(crit) = P(hit) · crit_chance. Cannot fire on a graze (RAW). -
Hit (non-crit) — full damage in the
weapon's range.
P(hit non-crit) = P(hit) - P(crit). - Graze — half damage (floor). Eats into the miss probability — graze is a partial outcome that competes with miss, not with hit.
-
Miss — zero damage.
P(miss) = 1 - P(hit) - P(graze).
Engine syntax: 1d3+4 @ hit 65 crit 10 graze 15
writes a 5-7 damage assault rifle shot at 65% hit, 10%
crit-on-hit, 15% graze. The engine computes the exact-rational
mean and full PMF.
Where graze actually shows up in the math
A 65% hit / 15% graze build looks like "you hit 65% of the time" in the tooltip but actually splits as:
- P(crit) = 0.65 · 0.10 =
9.75%(= 39/400) - P(non-crit hit) = 0.65 - 0.0975 =
55.25%(= 221/400) - P(graze) =
15%(= 60/400) - P(true miss) = 1 - 0.65 - 0.15 =
20%(= 80/400)
So the chance you deal some damage is 80%, not 65%. That's the graze contribution — soaking the bottom of the miss bucket into a half-damage outcome.
Side-by-side, same Assault Rifle shot without and with the graze model:
1d3+4 @ hit 65 crit 10
- 0 35.00%
- 1 0.00%
- 2 0.00%
- 3 0.00%
- 4 0.00%
- 5 19.50%
- 6 20.22%
- 7 20.94%
- 8 2.17%
- 9 1.44%
- 10 0.72%
1d3+4 @ hit 65 crit 10 graze 15
- 0 20.00%
- 1 0.00%
- 2 5.00%
- 3 10.00%
- 4 0.00%
- 5 19.50%
- 6 20.22%
- 7 20.94%
- 8 2.17%
- 9 1.44%
- 10 0.72%
The mean shifts up modestly (graze contributes 0.15 ·
E[floor(dmg/2)]), but the bigger story is the 0-bar
shrinking from 35% to 20%. For chained shots and per-mission
momentum, "do I deal any damage at all" matters more than
mean DPR.
The crit picture differs from D&D
In D&D 5e, crit is a face-range on the same d20 — nat 20 (or 19-20 with Champion) auto-hits and doubles dice. The same roll decides hit, miss, and crit.
In XCOM 2, crit is a separate post-hit roll. So:
- You can't crit a graze (different bucket entirely).
- You can't crit a miss (the hit roll has to succeed first).
- P(crit) is genuinely conditional — increasing hit chance also increases the crit rate, not just the hit rate.
Comparing a clean Squadsight Sniper Sharpshooter shot vs. a low-percentage flank attempt:
1d3+7 @ hit 35 crit 15
- 0 65.00%
- 1 0.00%
- 2 0.00%
- 3 0.00%
- 4 0.00%
- 5 0.00%
- 6 0.00%
- 7 0.00%
- 8 9.92%
- 9 10.50%
- 10 11.08%
- 11 1.75%
- 12 1.17%
- 13 0.58%
1d3+4 @ hit 95 crit 25
- 0 5.00%
- 1 0.00%
- 2 0.00%
- 3 0.00%
- 4 0.00%
- 5 23.75%
- 6 26.39%
- 7 29.03%
- 8 7.92%
- 9 5.28%
- 10 2.64%
The 95%-hit Squadsight shot has a much tighter distribution with a real damage floor; the 35%-hit flank is a long-tail Hail Mary with most of its mass at zero. Mean comparisons miss this entirely — the per-mission variance picture is what decides whether the shot is worth taking.
What the engine doesn't model (yet)
Two important XCOM 2 mechanics that this Tier-3a substrate doesn't capture:
-
Miss-streak protection — XCOM 2 fudges its
RNG to reduce frustrating multi-miss runs. The displayed
hit-chance is the long-run frequency, but per-encounter the
actual P(hit_n) depends on misses 1..n-1. State-carrying
Markov-chain extension is scoped (see
docs/engine-extensions-queue-and-reactions.mdin the repo) but not yet implemented. -
Damage-roll variance per bullet — XCOM 2's
damage range comes from a uniform integer roll (5-7 = pick
one of
{5, 6, 7}uniformly), modeled here as1d3+4. That's exact for the displayed range. Some weapon perks add bonus dice — those compose with the engine's standard+ NdMgrammar.
Phase 1 ships the percentage-attack family with hit / crit / graze. Phase 4 (open-ended) extends to stateful Markov chains for the streak-protection / Hard West Luck-pool family.
Build your own shot
The grammar for percentage attacks:
NdM[+K] @ hit <p>[%] [crit <p>[%]] [graze <p>[%]] [rider <expr>]
Trailing % sign is optional. Hit + graze must be
≤ 100. Examples:
-
1d3+4 @ hit 65 crit 10— vanilla XCOM 2 assault rifle, no graze model. -
1d4+5 @ hit 50 crit 10 graze 30— shotgun through half cover. -
1d3+7 @ hit 95 crit 25— Squadsight Sniper with full overwatch chain.
See the XCOM 2 weapons page for pre-baked panels covering common loadouts. Full grammar reference at /syntax.
Common questions
- Why is graze worth half-damage instead of a partial miss?
- XCOM 2's design intent is to soften the variance of low-percentage shots without rewarding them as much as a clean hit. Mechanically, P(graze) eats into the miss probability — so a 65% hit / 15% graze build has 80% chance of dealing some damage, vs. 65% if graze didn't exist. The variance picture: graze adds a low-damage mass that smooths the per-shot distribution, particularly valuable when chaining shots where a 0-damage round breaks momentum.
- How does P(crit) interact with hit chance?
- Crit is a separate roll conditional on a full hit. So `P(crit) = P(hit) × crit_chance` — never independent of hit. A 65% hit / 15% crit-on-hit build has P(crit) = 0.65 · 0.15 = 9.75% of all shots, P(non-crit hit) = 0.65 - 0.0975 = 55.25%, P(graze) = whatever you set, and P(true miss) = the rest. Crit cannot fire on a graze (RAW).
- What's different from D&D's d20 attack model?
- Two things. First, hit chance is a single percentage — no d20 enumeration. Second, crit is its own conditional roll on hit, not a d20-face range. The 5e crit rule (nat 20 always crits regardless of AC) doesn't apply: in XCOM, missing the hit roll means no crit, full stop. The graze bucket has no D&D analogue — D&D has a 3-way outcome (hit / crit / miss); XCOM 2 has 4-way.
- Does the engine model XCOM's miss-streak protection or Hard West's Luck pool?
- Not yet. Streak protection is a stateful mechanic — `P(hit_n)` depends on the outcome of shots 1..n-1, not just an independent draw. The current engine assumes per-strike independence, which is the right model for the displayed XCOM 2 hit chance but loses the actual game's RNG-fudging adjustment. A state-carrying Markov-chain extension is scoped (see /docs/engine-extensions in the repo) but not in Phase 1.