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
+3
View File
@@ -242,6 +242,9 @@ def load_combatant(path: Path) -> Combatant:
The ``armor_spell_failure`` percent and the ``arcane_caster`` flag
(SRD "Arcane Spells and Armor") are plain fields of the schema (defaults
``0`` and ``false``), so their JSON keys load directly as well.
The ``carried_items`` list (APG "Steal" — non-wielded, stealable gear) is
a plain ``tuple[str, ...]`` field of the schema (default empty), so a JSON
``carried_items`` key loads directly too.
"""
try:
raw = path.read_text(encoding="utf-8")