mirror of
https://github.com/Threnklyn/dungeon-sheets.git
synced 2026-05-24 06:38:28 +02:00
90 lines
2.3 KiB
Python
90 lines
2.3 KiB
Python
from dungeonsheets import spells
|
|
|
|
|
|
def all_spells():
|
|
"""Generate all the valid spell classes so far defined."""
|
|
for spell_name, spell in spells.__dict__.items():
|
|
# Check if it's (a) a class and (b) a subclass of ``Spell``
|
|
if isinstance(spell, type) and issubclass(spell, Spell):
|
|
yield spell
|
|
|
|
|
|
def create_spell(**params):
|
|
"""Create a new subclass of ``Spell`` with given default parameters.
|
|
|
|
Useful for spells that haven't been entered into the ``spells.py``
|
|
file yet.
|
|
|
|
Parameters
|
|
----------
|
|
params : optional
|
|
Saved as attributes of the new class.
|
|
|
|
Returns
|
|
-------
|
|
NewSpell
|
|
New spell class, subclass of ``Spell``, with given params.
|
|
"""
|
|
NewSpell = Spell
|
|
NewSpell.name = params.get("name", "Unknown Spell")
|
|
NewSpell.level = params.get("level", 9)
|
|
return NewSpell
|
|
|
|
|
|
class Spell:
|
|
"""A magical spell castable by a player character."""
|
|
|
|
level = 0
|
|
name = "Unknown spell"
|
|
casting_time = "1 action"
|
|
casting_range = "60 ft"
|
|
components = ()
|
|
materials = ""
|
|
duration = "instantaneous"
|
|
ritual = False
|
|
_concentration = False
|
|
magic_school = ""
|
|
classes = ()
|
|
|
|
def __str__(self):
|
|
s = self.name
|
|
requirements = list(self.components)
|
|
# Indicate if this is a ritual or a concentration
|
|
indicators = [
|
|
("R", self.ritual),
|
|
("C", self.concentration),
|
|
("$", self.special_material),
|
|
]
|
|
requirements.extend([letter for letter, is_active in indicators if is_active])
|
|
if len(requirements):
|
|
s += f' ({"/".join(requirements)})'
|
|
return s
|
|
|
|
def __repr__(self):
|
|
return f"{self.level} {self.name}"
|
|
|
|
def __eq__(self, other):
|
|
return (self.name == other.name) and (self.level == other.level)
|
|
|
|
def __hash__(self):
|
|
return 0
|
|
|
|
@property
|
|
def component_string(self):
|
|
s = f'{", ".join(self.components)}'
|
|
if "M" in self.components:
|
|
s += f" ({self.materials})"
|
|
return s
|
|
|
|
@property
|
|
def concentration(self):
|
|
return ("concentration" in self.duration.lower()) or self._concentration
|
|
|
|
@concentration.setter
|
|
def concentration(self, val: bool):
|
|
self._concentration = val
|
|
|
|
@property
|
|
def special_material(self):
|
|
return "worth" in self.materials.lower()
|