fix(combat): witch hex trigger uses the SRD close range scaled by caster level (25 ft + 5 ft per 2 levels, extracted as spells.close_range_ft and shared with spell_range_ft) instead of the fixed _HEX_RANGE_FT 25 - a level-5 witch reaches 35 ft; + scaling regression test
This commit is contained in:
@@ -141,6 +141,7 @@ from pf1e_simulator.spells import (
|
||||
SaveType,
|
||||
SpellEffect,
|
||||
SummonEffect,
|
||||
close_range_ft,
|
||||
save_descriptors_for_effects,
|
||||
spell_range_ft,
|
||||
spell_save_descriptors,
|
||||
@@ -8884,7 +8885,6 @@ def _normal_actions(
|
||||
|
||||
|
||||
_GROUPED_ENEMY_COUNT = 2
|
||||
_HEX_RANGE_FT = 25
|
||||
|
||||
|
||||
def _emit_channel_energy(
|
||||
@@ -8910,12 +8910,17 @@ def _emit_channel_energy(
|
||||
def _emit_hex(
|
||||
engine: CombatEngine, state: CombatantState, target: CombatantState | None
|
||||
) -> bool:
|
||||
"""True when nairda should hex: resource available and target within close range."""
|
||||
"""True when nairda should hex: resource available and target within close range.
|
||||
|
||||
APG hexes carry a close range, which scales with the caster level
|
||||
(SRD, Magic - Range: "Close - 25 ft. + 5 ft. per 2 caster levels").
|
||||
"""
|
||||
if state.resources_left.get("hexes", 0) <= 0:
|
||||
return False
|
||||
if target is None or not target.active:
|
||||
return False
|
||||
return engine.creature_distance(state, target) * _SQUARE_FT <= _HEX_RANGE_FT
|
||||
dist_ft = engine.creature_distance(state, target) * _SQUARE_FT
|
||||
return dist_ft <= close_range_ft(state.combatant.level)
|
||||
|
||||
|
||||
def _spell_combat_actions(
|
||||
|
||||
@@ -368,13 +368,19 @@ class SpellSpec:
|
||||
description: str = ""
|
||||
|
||||
|
||||
def close_range_ft(caster_level: int) -> int:
|
||||
"""PF1e (SRD, Magic — Range): "Close — 25 ft. + 5 ft. per 2 caster levels".
|
||||
Shared by spell ranges and class features with a close range (witch hexes)."""
|
||||
return 25 + 5 * (caster_level // 2)
|
||||
|
||||
|
||||
def spell_range_ft(spell: SpellSpec, caster_level: int) -> int:
|
||||
if spell.range == "personal":
|
||||
return 0
|
||||
if spell.range == "touch":
|
||||
return 5
|
||||
if spell.range == "close":
|
||||
return 25 + 5 * (caster_level // 2)
|
||||
return close_range_ft(caster_level)
|
||||
if spell.range == "medium":
|
||||
return 100 + 10 * caster_level
|
||||
return 400 + 40 * caster_level
|
||||
|
||||
Reference in New Issue
Block a user