Cairn 2e — Blood Elk horns vs armored PC
At the table
Cairn (2e) combat is swingy and armor matters. Attacks automatically hit; the attacker rolls weapon damage, the defender subtracts Armor, and whatever is left comes off HP.
This recipe models one hit from a Blood Elk (horns d8) against a typical front-line PC:
| Stat | Value |
|---|---|
| HP | 4 |
| STR | 11 (for critical damage saves) |
| Armor | 2 (1 worn + 1 shield) |
Damage steps:
- Roll d8, subtract 2 Armor (results below 0 count as 0).
- Subtract damage from HP.
- If HP lands on exactly 0, the PC takes a Scar keyed to how much HP that hit removed (after armor). Here that only happens on 4 damage—Scar entry #4 (Broken Limb).
- If damage would push HP below 0, the leftover comes off STR instead. The PC immediately rolls a STR save (d20 ≤ STR after the loss; 1 always succeeds, 20 always fails). Failing means Critical Damage—out of the fight and dying without aid. A Blood Elk that inflicts Critical Damage is especially nasty: it gores the victim (fiction + Warden fallout).
So on a single elk charge you might see: the horns glance off armor (no HP loss), hit protection chipped away (HP loss that reads more like guard fatigue than lasting injury), a Scar at 0 HP, STR loss but still fighting after a passed save, or Critical Damage after a failed save.
Try it
In the playground, open this recipe in the playground and click Run.
The script
↗HP = 4
ARMOR = 2
STR = 11
Scale = (
scale()
.step("NO_EFFECT")
.step("HIT_PROTECTION_LOSS")
.step("SCAR")
.step("STR_DOWN_OK")
.step("CRITICAL_DAMAGE")
)
def damage(horn):
d = horn - ARMOR
if d < 0:
return 0
return d
def blood_elk_hit(horn, save):
dmg = damage(horn)
if dmg == 0:
return "NO_EFFECT"
if dmg < HP:
return "HIT_PROTECTION_LOSS"
if dmg == HP:
return "SCAR"
overflow = dmg - HP
new_str = STR - overflow
if save == 1:
return "STR_DOWN_OK"
if save == 20:
return "CRITICAL_DAMAGE"
if save <= new_str:
return "STR_DOWN_OK"
return "CRITICAL_DAMAGE"
out = joint_classify(d(8), d(20), Scale, blood_elk_hit)
output("blood_elk_horns", out)
output("p_protection_loss_or_worse", out.p_at_least("HIT_PROTECTION_LOSS"))
output("p_scar_or_worse", out.p_at_least("SCAR"))
output("p_critical_damage", out.p_at_least("CRITICAL_DAMAGE"))
blood_elk_horns · Outcomes
| outcome | % | frac | X/160 |
|---|---|---|---|
| NO_EFFECT | 25.0 | 1/4 | 40 |
| HIT_PROTECTION_LOSS | 37.5 | 3/8 | 60 |
| SCAR | 12.5 | 1/8 | 20 |
| STR_DOWN_OK | 11.9 | 19/160 | 19 |
| CRITICAL_DAMAGE | 13.1 | 21/160 | 21 |
p_protection_loss_or_worse · Prob
| outcome | % | frac | X/160 |
|---|---|---|---|
| p_protection_loss_or_worse | 75.0 | 3/4 | 120 |
p_scar_or_worse · Prob
| outcome | % | frac | X/160 |
|---|---|---|---|
| p_scar_or_worse | 37.5 | 3/8 | 60 |
p_critical_damage · Prob
| outcome | % | frac | X/160 |
|---|---|---|---|
| p_critical_damage | 13.1 | 21/160 | 21 |