mirror of
https://github.com/Threnklyn/dungeon-sheets.git
synced 2026-05-18 20:23:27 +02:00
Fixed tests: needed defaults for making character sheets for NPCs (e.g. GM notes).
This commit is contained in:
@@ -467,11 +467,11 @@ class Character(Creature):
|
|||||||
@property
|
@property
|
||||||
def spellcasting_classes_excluding_warlock(self):
|
def spellcasting_classes_excluding_warlock(self):
|
||||||
return [c for c in self.spellcasting_classes if not type(c) == classes.Warlock]
|
return [c for c in self.spellcasting_classes if not type(c) == classes.Warlock]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_spellcaster(self):
|
def is_spellcaster(self):
|
||||||
return len(self.spellcasting_classes) > 0
|
return len(self.spellcasting_classes) > 0
|
||||||
|
|
||||||
def spell_slots(self, spell_level):
|
def spell_slots(self, spell_level):
|
||||||
warlock_slots = 0
|
warlock_slots = 0
|
||||||
for c in self.spellcasting_classes:
|
for c in self.spellcasting_classes:
|
||||||
|
|||||||
@@ -105,7 +105,6 @@ class Content(ABC):
|
|||||||
attrs = {"name": mechanic_name, "__doc__": msg, "source": "Unknown"}
|
attrs = {"name": mechanic_name, "__doc__": msg, "source": "Unknown"}
|
||||||
Mechanic = type(class_name, (SuperClass,), attrs)
|
Mechanic = type(class_name, (SuperClass,), attrs)
|
||||||
return Mechanic
|
return Mechanic
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Creature(Content):
|
class Creature(Content):
|
||||||
@@ -213,3 +212,7 @@ class Creature(Content):
|
|||||||
self.medicine, self.nature, self.perception,
|
self.medicine, self.nature, self.perception,
|
||||||
self.performance, self.persuasion, self.religion,
|
self.performance, self.persuasion, self.religion,
|
||||||
self.sleight_of_hand, self.stealth, self.survival]
|
self.sleight_of_hand, self.stealth, self.survival]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_spellcaster(self):
|
||||||
|
raise NotImplementedError
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import re
|
|||||||
from jinja2 import Environment, PackageLoader
|
from jinja2 import Environment, PackageLoader
|
||||||
|
|
||||||
|
|
||||||
from dungeonsheets.stats import mod_str, ability_mod_str, stat_abbreviation
|
from dungeonsheets.stats import mod_str, ability_mod_str, stat_abbreviation, str_to_list
|
||||||
from dungeonsheets.encounter import xp_thresholds
|
from dungeonsheets.encounter import xp_thresholds
|
||||||
from dungeonsheets.monsters import challenge_rating_to_xp
|
from dungeonsheets.monsters import challenge_rating_to_xp
|
||||||
|
|
||||||
@@ -37,4 +37,5 @@ def jinja_environment():
|
|||||||
jinja_env.filters["stat_abbreviation"] = stat_abbreviation
|
jinja_env.filters["stat_abbreviation"] = stat_abbreviation
|
||||||
jinja_env.filters["challenge_rating_to_xp"] = challenge_rating_to_xp
|
jinja_env.filters["challenge_rating_to_xp"] = challenge_rating_to_xp
|
||||||
jinja_env.filters["xp_thresholds"] = xp_thresholds
|
jinja_env.filters["xp_thresholds"] = xp_thresholds
|
||||||
|
jinja_env.filters["str_to_list"] = str_to_list
|
||||||
return jinja_env
|
return jinja_env
|
||||||
|
|||||||
@@ -49,7 +49,7 @@
|
|||||||
<dt>Current Hit Points</dt>
|
<dt>Current Hit Points</dt>
|
||||||
<dd>[[ character.hp_current ]] </dd>
|
<dd>[[ character.hp_current ]] </dd>
|
||||||
<dt>Temporary Hit Points</dt>
|
<dt>Temporary Hit Points</dt>
|
||||||
<dd>[% if character.hp_temp > 0 %][[ character.hp_temp ]][% endif %] </dd>
|
<dd>[[ character | selectattr('hp_temp', 0) ]] </dd>
|
||||||
<dt>Hit Dice Total</dt>
|
<dt>Hit Dice Total</dt>
|
||||||
<dd>[[ character.hit_dice ]]</dd>
|
<dd>[[ character.hit_dice ]]</dd>
|
||||||
|
|
||||||
@@ -126,12 +126,10 @@
|
|||||||
<li>[[ character.ep ]] EP</li>
|
<li>[[ character.ep ]] EP</li>
|
||||||
<li>[[ character.gp ]] GP</li>
|
<li>[[ character.gp ]] GP</li>
|
||||||
<li>[[ character.pp ]] PP</li>
|
<li>[[ character.pp ]] PP</li>
|
||||||
[% set inventory_items = character.magic_items_text.split(',') %]
|
[% for item in character | str_to_list('magic_items_text') %]
|
||||||
[% for item in inventory_items %]
|
|
||||||
<li>[[ item ]]</li>
|
<li>[[ item ]]</li>
|
||||||
[% endfor %]
|
[% endfor %]
|
||||||
[% set inventory_items = character.equipment.split(',') %]
|
[% for item in character | str_to_list('equipment') %]
|
||||||
[% for item in inventory_items %]
|
|
||||||
<li>[[ item ]]</li>
|
<li>[[ item ]]</li>
|
||||||
[% endfor %]
|
[% endfor %]
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@@ -387,12 +387,12 @@ def make_character_content(
|
|||||||
content_suffix=content_format,
|
content_suffix=content_format,
|
||||||
use_dnd_decorations=fancy_decorations))
|
use_dnd_decorations=fancy_decorations))
|
||||||
# Create a list of subcasses, features, spells, etc
|
# Create a list of subcasses, features, spells, etc
|
||||||
if character.subclasses:
|
if len(getattr(character, 'subclasses', [])) > 0:
|
||||||
content.append(create_subclasses_content(character,
|
content.append(create_subclasses_content(character,
|
||||||
content_suffix=content_format,
|
content_suffix=content_format,
|
||||||
use_dnd_decorations=fancy_decorations)
|
use_dnd_decorations=fancy_decorations)
|
||||||
)
|
)
|
||||||
if character.features:
|
if len(getattr(character, 'features', [])) > 0:
|
||||||
content.append(
|
content.append(
|
||||||
create_features_content(character, content_suffix=content_format, use_dnd_decorations=fancy_decorations)
|
create_features_content(character, content_suffix=content_format, use_dnd_decorations=fancy_decorations)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -106,3 +106,7 @@ class Monster(Creature, metaclass=SpellFactory):
|
|||||||
|
|
||||||
def has_feature(self, *args, **kwargs):
|
def has_feature(self, *args, **kwargs):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_spellcaster(self):
|
||||||
|
return len(self.spells) > 0
|
||||||
|
|||||||
+37
-1
@@ -32,7 +32,43 @@ log = logging.getLogger(__name__)
|
|||||||
|
|
||||||
def mod_str(modifier):
|
def mod_str(modifier):
|
||||||
"""Converts a modifier to a string, eg 2 -> '+2'."""
|
"""Converts a modifier to a string, eg 2 -> '+2'."""
|
||||||
return "{:+d}".format(modifier)
|
try:
|
||||||
|
s = "{:+d}".format(modifier)
|
||||||
|
except TypeError:
|
||||||
|
s = "N/A"
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
def str_to_list(obj, attr: str, sep: str = ","):
|
||||||
|
"""Find the string *obj.attr* if it exists, and returns it as a
|
||||||
|
list.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
==========
|
||||||
|
obj
|
||||||
|
Any python object, presumably with an attribute *attr*.
|
||||||
|
attr
|
||||||
|
The name of the attribute to look up.
|
||||||
|
sep
|
||||||
|
The separator to use for splitting the string.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
=======
|
||||||
|
items
|
||||||
|
A sequence of the items retrieved from *obj.attr* string. If
|
||||||
|
*obj.attr* does not exist, an empty list will be returned. If
|
||||||
|
*obj.attr* is not a string, then it will be presumed to be a
|
||||||
|
sequence already and returned as is.
|
||||||
|
|
||||||
|
"""
|
||||||
|
string = getattr(obj, attr, [])
|
||||||
|
if hasattr(string, "split"):
|
||||||
|
# Convert the string to a list
|
||||||
|
lst = [s.strip() for s in string.split(sep)]
|
||||||
|
else:
|
||||||
|
# A non-string attribute was given, so just return it
|
||||||
|
lst = string
|
||||||
|
return lst
|
||||||
|
|
||||||
|
|
||||||
def ability_mod_str(character, ability):
|
def ability_mod_str(character, ability):
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ monsters, etc.
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from dungeonsheets import mechanics, monsters
|
from dungeonsheets import mechanics, monsters as _monsters
|
||||||
|
|
||||||
dungeonsheets_version = "0.14.0"
|
dungeonsheets_version = "0.14.0"
|
||||||
|
|
||||||
@@ -18,6 +18,6 @@ haryk_omanie = mechanics.Character(
|
|||||||
name="Haryk Omanie",
|
name="Haryk Omanie",
|
||||||
)
|
)
|
||||||
|
|
||||||
party = ["rogue1.py", "paladin2.py", haryk_omanie, monsters.Veteran]
|
party = ["rogue1.py", "paladin2.py", haryk_omanie, _monsters.Veteran]
|
||||||
|
|
||||||
random_tables = ["conjure animals"]
|
random_tables = ["conjure animals"]
|
||||||
|
|||||||
@@ -8,6 +8,19 @@ class TestStats(TestCase):
|
|||||||
self.assertEqual(stats.mod_str(-3), "-3")
|
self.assertEqual(stats.mod_str(-3), "-3")
|
||||||
self.assertEqual(stats.mod_str(0), "+0")
|
self.assertEqual(stats.mod_str(0), "+0")
|
||||||
self.assertEqual(stats.mod_str(2), "+2")
|
self.assertEqual(stats.mod_str(2), "+2")
|
||||||
|
self.assertEqual(stats.mod_str(None), "N/A")
|
||||||
|
|
||||||
|
def test_str_to_list(self):
|
||||||
|
char = character.Character(equipment="a, b, c")
|
||||||
|
# Regular string
|
||||||
|
self.assertEqual(stats.str_to_list(char, "equipment"), ["a", "b", "c"])
|
||||||
|
# Alternate separator
|
||||||
|
char.equipment = "a; b; c"
|
||||||
|
self.assertEqual(stats.str_to_list(char, "equipment", sep=";"), ["a", "b", "c"])
|
||||||
|
# No attribute
|
||||||
|
self.assertEqual(stats.str_to_list(char, "inventory"), [])
|
||||||
|
# Not a string
|
||||||
|
self.assertEqual(stats.str_to_list(char, "hp_max"), char.hp_max)
|
||||||
|
|
||||||
def test_saving_throw(self):
|
def test_saving_throw(self):
|
||||||
# Try it with an ST proficiency
|
# Try it with an ST proficiency
|
||||||
|
|||||||
Reference in New Issue
Block a user