feat(combat): area-of-effect spells
This commit is contained in:
@@ -54,7 +54,22 @@ class BuffEffect:
|
||||
duration_rounds: int
|
||||
|
||||
|
||||
SpellEffect = DamageEffect | ConditionEffect | HealEffect | BuffEffect
|
||||
@dataclass(frozen=True)
|
||||
class AreaEffect:
|
||||
"""Area of effect spell (burst only for Phase 0).
|
||||
|
||||
- shape: only "burst" supported (circle around target point)
|
||||
- radius_ft: radius in feet (e.g., 20 for fireball)
|
||||
- effects: the effects applied to each creature in the area
|
||||
- save_for_half: if True, successful save halves damage
|
||||
"""
|
||||
shape: Literal["burst"] = "burst"
|
||||
radius_ft: int = 20
|
||||
effects: tuple[SpellEffect, ...] = ()
|
||||
save_for_half: bool = True
|
||||
|
||||
|
||||
SpellEffect = DamageEffect | ConditionEffect | HealEffect | BuffEffect | AreaEffect
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@@ -111,10 +126,15 @@ def _parse_effect(data: dict[str, Json]) -> SpellEffect:
|
||||
)
|
||||
for m in cast("list[dict[str, Json]]", data["modifiers"])
|
||||
),
|
||||
duration_rounds=int(data["duration_rounds"]), # type: ignore[arg-type]
|
||||
duration_rounds=int(data.get("duration_rounds", 0)), # type: ignore[arg-type]
|
||||
)
|
||||
msg = f"Unknown effect type: {effect_type}"
|
||||
raise ValueError(msg)
|
||||
if effect_type == "area":
|
||||
return AreaEffect(
|
||||
radius_ft=int(data.get("radius_ft", 20)), # type: ignore[arg-type]
|
||||
effects=tuple(_parse_effect(e) for e in data["effects"]), # type: ignore[index]
|
||||
save_for_half=bool(data.get("save_for_half", True)),
|
||||
)
|
||||
raise ValueError(f"Unknown effect type: {effect_type}")
|
||||
|
||||
|
||||
def load_spell(path: str | Path) -> SpellSpec:
|
||||
|
||||
Reference in New Issue
Block a user