fix(combat): _swift_bonus_actions emits up_close_and_deadly only when the turn will actually fire a firearm attack within 30 ft - the deed burns 1 grit at execution and its +1d6 rides only a firearm attack, so emitting it alongside a melee swing or a spell cast wasted grit for a lost bonus; + 2 policy tests, deed test now uses a firearm-only tammara

This commit is contained in:
2026-09-19 18:55:17 +02:00
parent e8b7a73d1f
commit f93c55b3fb
2 changed files with 71 additions and 12 deletions
+17 -4
View File
@@ -8857,7 +8857,7 @@ def default_policy(engine: CombatEngine, state: CombatantState) -> tuple[Action,
return spell_combat
# Deed (tammara) and inspire_courage (misty melee fallback): swift/free bonuses.
swift_bonus = _swift_bonus_actions(engine, state, target)
swift_bonus = _swift_bonus_actions(engine, state, target, normal)
return (*swift_bonus, *normal) if swift_bonus else normal
@@ -8930,17 +8930,30 @@ def _spell_combat_actions(
)
_DEED_ATTACK_KINDS: frozenset[str] = frozenset({"attack", "full_attack"})
def _swift_bonus_actions(
engine: CombatEngine, state: CombatantState, target: CombatantState
engine: CombatEngine,
state: CombatantState,
target: CombatantState,
normal: tuple[Action, ...],
) -> tuple[Action, ...]:
"""Swift/free class-ability actions (deed, inspire_courage) to prepend to the turn."""
bonus: list[Action] = []
# Deed (tammara): swift/free action, emitted alongside the normal action only
# when the target is within Up Close and Deadly range (30 ft).
# Deed (tammara): Up Close and Deadly spends 1 grit up front and its +1d6
# rides the FIRST resolved attack, firearm-only within 30 ft (Ultimate
# Combat). Emitting it when the normal action resolves no such attack
# (melee swing, spell cast) burns grit for nothing, so gate on the weapon
# the turn will actually fire and on the sequence containing an attack.
weapon = engine.weapon_for(state, target)
if (
state.resources_left.get("grit", 0) > 0
and engine.creature_distance(state, target) * _SQUARE_FT <= _UP_CLOSE_RANGE_FT
and weapon is not None
and weapon.firearm
and any(a.kind in _DEED_ATTACK_KINDS for a in normal)
):
bonus.append(
Action(