from DnD_5e.combatant import Combatant
from DnD_5e.utility_methods_dnd import cr_to_xp, proficency_bonus_by_cr
[docs]
class Creature(Combatant):
"""
This class represents creatures, monsters, etc. - basically anything that isn't a character
"""
def __init__(self, **kwargs):
"""
Validate the input and set the instance variables
:param kwargs: keyword arguments. Uses all keyword arguments from superclass, plus these:
:param cr: the challenge rating
:type cr: non-negative number
:param xp: the experience points for *self*. If no value is provided, xp will be calculated based on *cr*
:type xp: non-negative integer
:param creature_type: the type of creature *self* is
:type creature_type: one of these strings: "aberration", "beast", "celestial", "construct",
"dragon", "elemental", "fey", "fiend", "giant", "monstrosity", "ooze", "plant", "undead", or something containing "humanoid"
:raise: ValueError if input is invalid
"""
self._cr = kwargs.get("cr", 0)
if not isinstance(self._cr, (int, float)) or self._cr <= 0:
# no logging yet because logger is created in superclass
raise ValueError("Challenge rating must be a non-negative number")
self._xp = kwargs.get("xp", cr_to_xp(self._cr))
proficiency_mod = proficency_bonus_by_cr(self._cr)
kwargs.update({"proficiency_mod": proficiency_mod})
self._creature_type = kwargs.get("creature_type")
if self._creature_type not in ["aberration", "beast", "celestial", "construct", "dragon", "elemental", "fey",
"fiend", "giant", "monstrosity", "ooze", "plant", "undead"]:
if not isinstance(self._creature_type, str) or "humanoid" not in self._creature_type:
# no logging yet because logger is created in superclass
raise ValueError(f'Invalid creature type: {self._creature_type}. Valid types are "aberration", '
f'"beast", "celestial", "construct", "dragon", "elemental", "fey", "fiend", "giant", '
f'"monstrosity", "ooze", "plant", "undead", and various types of "humanoid"')
name = kwargs.get("name", type(self))
kwargs.update(name=name)
super().__init__(**kwargs)
def __eq__(self, other) -> bool:
"""
Check equality based on superclass method and these attributes:
:py:attr:`cr`, :py:attr:`xp`, and :py:attr:`creature_type`
:param other: the Creature to compare
:return: True if *self* equals *other*, False otherwise
"""
return super().__eq__(other) \
and self.get_cr() == other.get_cr() \
and self.get_xp() == other.get_xp() \
and self.get_creature_type() == other.get_creature_type()
[docs]
def get_cr(self) -> int:
"""
:return: challenge rating
:rtype: non-negative integer
"""
return self._cr
[docs]
def get_xp(self) -> int:
"""
:return: xp
:rtype: non-negative integer
"""
return self._xp
[docs]
def get_creature_type(self) -> str:
"""
:return: creature type
:rtype: str
"""
return self._creature_type
[docs]
def become_unconscious(self):
"""
Creatures don't have death saves. If something happens that would make you unconscious, just die.
:return:
"""
self.die()