fix(combat): deed range gating

This commit is contained in:
2026-09-04 22:56:05 +02:00
parent c5f31c30d1
commit 83a5250ca6
2 changed files with 57 additions and 17 deletions
+26 -17
View File
@@ -1568,30 +1568,35 @@ class CombatEngine:
"""Execute a gunslinger deed (up_close_and_deadly, quick_clear)."""
if deed_name not in ("up_close_and_deadly", "quick_clear"):
return
if not state.spend_resource("grit", 1):
self._log(
f"round {self._current_round} {state.combatant.id}: deed failed (no grit)"
)
return
if deed_name == "up_close_and_deadly":
# Up Close and Deadly: +1d6 damage within 30ft
if target is None or not target.active:
return
dist_ft = self._grid.distance(state.pos, target.pos) * _SQUARE_FT
if dist_ft <= _UP_CLOSE_RANGE_FT:
# Apply +1d6 damage to next attack this round
state.deed_up_close_and_deadly = True
self._log(
f"round {self._current_round} {state.combatant.id}: "
f"deed Up Close and Deadly activated (+1d6 dmg within 30ft)"
)
else:
if dist_ft > _UP_CLOSE_RANGE_FT:
self._log(
f"round {self._current_round} {state.combatant.id}: deed Up Close "
f"and Deadly - target out of range"
)
return
if not state.spend_resource("grit", 1):
self._log(
f"round {self._current_round} {state.combatant.id}: deed failed (no grit)"
)
return
# Apply +1d6 damage to next attack this round
state.deed_up_close_and_deadly = True
self._log(
f"round {self._current_round} {state.combatant.id}: "
f"deed Up Close and Deadly activated (+1d6 dmg within 30ft)"
)
elif deed_name == "quick_clear":
# Quick Clear: swift action, clears misfire
if not state.spend_resource("grit", 1):
self._log(
f"round {self._current_round} {state.combatant.id}: deed failed (no grit)"
)
return
self._log(
f"round {self._current_round} {state.combatant.id}: "
f"deed Quick Clear - firearm cleared"
@@ -2534,7 +2539,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(state, target)
swift_bonus = _swift_bonus_actions(engine, state, target)
return (*swift_bonus, *normal) if swift_bonus else normal
@@ -2597,13 +2602,17 @@ def _spell_combat_actions(
def _swift_bonus_actions(
state: CombatantState, target: CombatantState
engine: CombatEngine, state: CombatantState, target: CombatantState
) -> 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.
if state.resources_left.get("grit", 0) > 0:
# Deed (tammara): swift/free action, emitted alongside the normal action only
# when the target is within Up Close and Deadly range (30 ft).
if (
state.resources_left.get("grit", 0) > 0
and engine.grid.distance(state.pos, target.pos) * _SQUARE_FT <= _UP_CLOSE_RANGE_FT
):
bonus.append(
Action(
kind="deed",