The card is assembled the same way every action card is (see
sohl.document.chat.buildActionCard): a body template
(attack-card.hbs) plus a buttons array. Transparency-by-design — the
attacker's choices (Aim, Aspect) and the resolved Attack Mastery Level ride in
the body data for everyone to see.
All four defense buttons are emitted (when there is a target); each is a
self-sufficient defense-resume action addressed to the defender's combatant
(so the click resolves on the defender's client), carrying the evaluated attack
in its scope (revived by the resume flows as context.scope.attackResult).
Per-defender capability gating (Block/Counterstrike/Dodge) still happens later,
at render time, in sohl.document.chat.gateAutomatedDefenseButtons. With
no target the card is informational (no buttons).
Build the sohl.document.chat.ActionCardSpec for the automated-combat attack card from an evaluated sohl.entity.result.AttackResult. Pure and Foundry-free.
The card is assembled the same way every action card is (see sohl.document.chat.buildActionCard): a body template (
attack-card.hbs) plus abuttonsarray. Transparency-by-design — the attacker's choices (Aim, Aspect) and the resolved Attack Mastery Level ride in the bodydatafor everyone to see.All four defense buttons are emitted (when there is a target); each is a self-sufficient defense-resume action addressed to the defender's combatant (so the click resolves on the defender's client), carrying the evaluated attack in its
scope(revived by the resume flows ascontext.scope.attackResult). Per-defender capability gating (Block/Counterstrike/Dodge) still happens later, at render time, in sohl.document.chat.gateAutomatedDefenseButtons. With no target the card is informational (no buttons).