fix(rules): Extend Spell doubles SummonEffect duration (SRD extend-spell: lasts twice as long; summon's 1 round/level is neither instantaneous, concentration nor permanent)

This commit is contained in:
2026-09-19 11:55:30 +02:00
parent 65a5e24609
commit 22724f583f
2 changed files with 84 additions and 2 deletions
+67
View File
@@ -335,3 +335,70 @@ class TestSummonDurationScalesWithCasterLevel:
effect = spell.effects[0]
assert isinstance(effect, SummonEffect)
assert effect.duration_rounds_per_level == 1
class TestExtendSpellOnSummon:
"""SRD feats/extend-spell.md: "An extended spell lasts twice as long as
normal. A spell with a duration of concentration, instantaneous, or
permanent is not affected" - summon monster's "1 round/level (D)" is
none of those, so Extend must double it."""
def test_extend_doubles_the_per_level_summon_duration(self) -> None:
# Given: a level 5 caster who knows Extend Spell
# When: summoning with Extend Spell (1 round/level -> 2 rounds/level)
# Then: the wolf is bound for 10 rounds, and the level-3 slot burns.
caster = _make_caster().model_copy(
update={
"metamagic_feats": ["Extend Spell"],
"spell_slots": {1: 3, 2: 3, 3: 3},
}
)
enemy = _make_enemy()
c = CombatantState(combatant=caster, side="players", pos=(0, 0), hp=caster.hp_max)
e = CombatantState(combatant=enemy, side="monsters", pos=(5, 0), hp=enemy.hp_max)
spell = SpellSpec(
name="Summon Monster II",
level=2,
school="conjuration",
range="close",
effects=(
SummonEffect(
creature="data/monsters/celestial_wolf.json",
duration_rounds=1,
duration_rounds_per_level=1,
),
),
)
legend = {".": TerrainType(type="floor", move_cost=1)}
spec = MapSpec(name="test", terrain=tuple(["." * 12] * 12), legend=legend)
engine = CombatEngine(
SeededRng(1), Grid.from_spec(spec), [c, e],
spell_registry={"Summon Monster II": spell},
)
engine._cast_spell(c, e, "Summon Monster II", metamagic=("Extend Spell",))
wolf = next(s for s in engine._states if s.combatant.id == "celestial_wolf")
assert wolf.summon_duration == 10
assert c.spell_slots_left[3] == 2 # extended: level-3 slot
def test_extend_doubles_a_fixed_summon_duration(self) -> None:
# Given: a summon with only a fixed duration (per_level = 0)
# When: the summon is cast extended (feat applied to this cast)
# Then: the fixed rounds double (2 -> 4).
caster = _make_caster().model_copy(
update={
"metamagic_feats": ["Extend Spell"],
"spell_slots": {1: 3, 2: 3, 3: 3},
}
)
enemy = _make_enemy()
c = CombatantState(combatant=caster, side="players", pos=(0, 0), hp=caster.hp_max)
e = CombatantState(combatant=enemy, side="monsters", pos=(5, 0), hp=enemy.hp_max)
reg = {"Summon Monster II": _make_summon_spell(duration_rounds=2)}
legend = {".": TerrainType(type="floor", move_cost=1)}
spec = MapSpec(name="test", terrain=tuple(["." * 12] * 12), legend=legend)
engine = CombatEngine(
SeededRng(1), Grid.from_spec(spec), [c, e], spell_registry=reg
)
engine._cast_spell(c, e, "Summon Monster II", metamagic=("Extend Spell",))
wolf = next(s for s in engine._states if s.combatant.id == "celestial_wolf")
assert wolf.summon_duration == 4