fix(rules): summon duration scales with caster level (SRD summon-monster: 1 round/level (D)) - SummonEffect gains duration_rounds_per_level resolved at cast time, summon_monster_i/ii JSON updated
This commit is contained in:
@@ -7220,6 +7220,15 @@ class CombatEngine:
|
||||
_spell_name: str,
|
||||
) -> str:
|
||||
"""Apply a summoning effect - create a summoned creature."""
|
||||
# PF1e (SRD spells/summon-monster-1.md): "Duration 1 round/level (D)"
|
||||
# - a per-level duration resolves against the caster's level at cast
|
||||
# time, mirroring the ConditionEffect convention; a fixed duration is
|
||||
# the pre-conformance fallback.
|
||||
duration = effect.duration_rounds
|
||||
if effect.duration_rounds_per_level > 0:
|
||||
duration = max(
|
||||
1, state.combatant.level * effect.duration_rounds_per_level
|
||||
)
|
||||
# Load the summoned creature
|
||||
try:
|
||||
summoned_combatant = load_combatant(Path(effect.creature))
|
||||
@@ -7256,7 +7265,7 @@ class CombatEngine:
|
||||
self._states.insert(caster_idx + 1, summoned_state)
|
||||
|
||||
# Set expiration
|
||||
summoned_state.summon_duration = effect.duration_rounds
|
||||
summoned_state.summon_duration = duration
|
||||
summoned_state.summon_caster_id = state.combatant.id
|
||||
self._apply_simple_monster_death(summoned_state)
|
||||
|
||||
@@ -7265,7 +7274,7 @@ class CombatEngine:
|
||||
|
||||
self._log(
|
||||
f"round {self._current_round} {state.combatant.id}: "
|
||||
f"summon {summoned_combatant.id} at {spawn_pos} ({effect.duration_rounds}r)"
|
||||
f"summon {summoned_combatant.id} at {spawn_pos} ({duration}r)"
|
||||
)
|
||||
return f"summoned {summoned_combatant.id}"
|
||||
|
||||
|
||||
@@ -296,10 +296,17 @@ class SummonEffect:
|
||||
"""Summoning spell effect.
|
||||
|
||||
- creature: path to the creature JSON file (e.g., "data/monsters/celestial_wolf.json")
|
||||
- duration_rounds: how long the summoned creature stays
|
||||
- duration_rounds: fixed rounds the summoned creature stays, used when
|
||||
``duration_rounds_per_level`` is 0
|
||||
- duration_rounds_per_level: PF1e "1 round/level" summoning duration
|
||||
(SRD spells/summon-monster-1.md: "Duration 1 round/level (D)") - when
|
||||
> 0 the rounds resolve at cast time as
|
||||
``max(1, caster_level * duration_rounds_per_level)``, mirroring
|
||||
``ConditionEffect``'s field of the same name.
|
||||
"""
|
||||
creature: str
|
||||
duration_rounds: int
|
||||
duration_rounds_per_level: int = 0
|
||||
|
||||
|
||||
SpellEffect = (
|
||||
@@ -690,6 +697,9 @@ def _parse_summon_effect(effect: dict[str, Json]) -> SummonEffect:
|
||||
return SummonEffect(
|
||||
creature=_as_str(effect["creature"]),
|
||||
duration_rounds=_as_int(effect["duration_rounds"]),
|
||||
duration_rounds_per_level=_as_int(
|
||||
effect.get("duration_rounds_per_level", 0)
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user