feat(rules): carried items + real steal transfers, unarmed-disarm auto-pickup

- Combatant.carried_items (APG Steal: non-wielded, non-closely-worn gear),
  loaded from JSON, seeded into CombatantState, exposed in the snapshot.
- _maneuver_steal: success transfers the first carried item victim -> thief
  (logged); empty list keeps the documented nothing-stealable behaviour.
- _maneuver_disarm: unarmed attacker's success auto-picks the dropped weapon
  into its carried_items (SRD Disarm); armed disarms unchanged. Dropped-weapon
  recovery via retrieve_weapon (move action) verified + pinned by tests.
- data/pcs: gear transcribed from Foundry sheet inventories (esha 13,
  jeanne 3, misty 9, nairda 7, oni 6, tammara 20); harvie/ierlieth/
  esha_mount and all monsters empty (no stealable inventory), noted in README.
This commit is contained in:
2026-09-20 16:05:07 +02:00
parent 74f5d64c43
commit d0f7f3a107
14 changed files with 260 additions and 22 deletions
+12
View File
@@ -382,6 +382,18 @@ class Combatant(_FrozenModel):
# PF1e two-axis alignment (SRD "Alignment"): law-good axis codes, one of
# LG/NG/CG/LN/N/CN/LE/NE/CE. Default "N" (true neutral).
alignment: str = "N"
# PF1e (APG "Steal"): carried items that are NEITHER wielded in a hand
# NOR closely worn - potions, scrolls, tools, pouches, keys, rations...
# "This maneuver can be used in melee to take any item that is neither
# held nor hidden in a bag or pack [...] Items that are closely worn
# (such as armor, backpacks, boots, clothing, or rings) cannot be taken
# with this maneuver. Items held in the hands (such as wielded weapons
# or wands) also cannot be taken with the steal maneuver - you must use
# the disarm combat maneuver instead." Wielded weapons live in
# ``attacks``; closely worn gear is not modeled (the AC in the JSON is
# a final value), so this list holds only stealable carried items.
# rules/advanced-players-guide/steal.md
carried_items: tuple[str, ...] = ()
@field_validator("alignment")
@classmethod