From 6cab3b289a087a1480c13ba4711df0631567b190 Mon Sep 17 00:00:00 2001 From: David Kruger Date: Tue, 20 May 2025 22:13:17 -0700 Subject: [PATCH] Parsing the spell attack type and area type --- dnd5etools/db/spells.py | 52 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/dnd5etools/db/spells.py b/dnd5etools/db/spells.py index 3775fb6..cb7d666 100644 --- a/dnd5etools/db/spells.py +++ b/dnd5etools/db/spells.py @@ -55,13 +55,35 @@ class Duration(typing.NamedTuple): ) +class SpellAttackType(enum.StrEnum): + Melee = "M" + Ranged = "R" + Other = "O" + + +class SpellAreaType(enum.StrEnum): + SingleTarget = "ST" + MultipleTargets = "MT" + Cube = "C" + Cone = "N" + Cylinder = "Y" + Sphere = "S" + Circle = "R" + Square = "Q" + Line = "L" + Hemisphere = "H" + Wall = "W" + + class Spell(typing.NamedTuple): name: str source: str description: str ability_check: typing.Set[Ability] duration: typing.List[Duration] - # remaining: 'affectsCreatureType', 'alias', 'areaTags', 'basicRules2024', 'components', 'conditionImmune', 'conditionInflict', 'damageImmune', 'damageInflict', 'damageResist', 'damageVulnerable', 'entriesHigherLevel', 'hasFluffImages', 'level', 'meta', 'miscTags', 'page', 'range', 'savingThrow', 'scalingLevelDice', 'school', 'spellAttack', 'srd52', 'time' + attack_type: typing.Set[SpellAttackType] + area_type: typing.Set[SpellAreaType] + # remaining: 'affectsCreatureType', 'alias', 'basicRules2024', 'components', 'conditionImmune', 'conditionInflict', 'damageImmune', 'damageInflict', 'damageResist', 'damageVulnerable', 'entriesHigherLevel', 'hasFluffImages', 'level', 'meta', 'miscTags', 'page', 'range', 'savingThrow', 'scalingLevelDice', 'school', 'srd52', 'time' @classmethod def from_json(cls, json_data) -> typing.Self: @@ -79,19 +101,43 @@ class Spell(typing.NamedTuple): duration = cls.duration_from_json(json_data) except Exception as e: raise Exception(f"Unable to parse duration for {name}: {e}") + try: + attack_type = cls.attack_type_from_json(json_data) + except Exception as e: + raise Exception(f"Unable to parse spellAttack for {name}: {e}") + try: + area_type = cls.area_type_from_json(json_data) + except Exception as e: + raise Exception(f"Unable to parse areaTags for {name}: {e}") return cls( name=name, source=source, description=description, ability_check=ability_check, duration=duration, + attack_type=attack_type, + area_type=area_type, ) @classmethod def ability_check_from_json(cls, json_data) -> typing.Set[Ability]: - if "abilityCheck" not in json_data: + return cls.json_str_enum_list(json_data, "abilityCheck", Ability) + + @classmethod + def attack_type_from_json(cls, json_data) -> typing.Set[SpellAttackType]: + return cls.json_str_enum_list(json_data, "spellAttack", SpellAttackType) + + @classmethod + def area_type_from_json(cls, json_data) -> typing.Set[SpellAreaType]: + return cls.json_str_enum_list(json_data, "areaTags", SpellAreaType) + + @classmethod + def json_str_enum_list( + cls, json_data, key: str, enum_cls: typing.Type[enum.StrEnum] + ) -> typing.Set[enum.StrEnum]: + if key not in json_data: return set() - return {Ability(c) for c in json_data["abilityCheck"]} + return {enum_cls(c) for c in json_data[key]} @classmethod def description_from_json(cls, json_data) -> str: