save function now works for a character... need to add defaults if options dont exist

This commit is contained in:
Ben Cook
2018-12-20 10:35:50 -05:00
parent b93b1ac6d7
commit 2b1f5981b4
10 changed files with 116 additions and 50 deletions
+7 -1
View File
@@ -1,2 +1,8 @@
from . import weapons, character
from . import weapons, character, features, race, background, spells
import os
def read(fname):
return open(os.path.join(os.path.dirname(__file__), fname)).read()
__version__ = read('../VERSION')
+4
View File
@@ -7,6 +7,8 @@ class Shield():
def __str__(self):
return self.name
def __repr__(self):
return "\"{:s}\"".format(self.name)
class WoodenShield(Shield):
name = 'Wooden shield'
@@ -55,6 +57,8 @@ class Armor():
def __str__(self):
return self.name
def __repr__(self):
return "\"{:s}\"".format(self.name)
class NoArmor(Armor):
name = "No armor"
+42 -7
View File
@@ -5,11 +5,14 @@ import os
import warnings
from . import exceptions
import importlib.util
import jinja2
import subprocess
from .stats import Ability, Skill, findattr
from .dice import read_dice_str
from . import (weapons, race, background, spells, armor, monsters,
exceptions, classes, features)
from .__init__ import __version__
from .weapons import Weapon
from .armor import Armor, NoArmor, Shield, NoShield
@@ -49,6 +52,7 @@ class Character():
class_name = ""
player_name = ""
alignment = "Neutral"
dungeonsheets_version = __version__
class_list = []
race = None
background = None
@@ -111,7 +115,8 @@ class Character():
spells = tuple()
spells_prepared = tuple()
# Features IN MAJOR DEVELOPMENT
other_features = ()
custom_features = ()
feature_choices = ()
def __init__(self, **attrs):
"""Takes a bunch of attrs and passes them to ``set_attrs``"""
@@ -150,6 +155,11 @@ class Character():
@property
def class_initialized(self):
return (self.num_classes > 0)
@property
def classes_levels(self):
return [c.class_name.lower() + ' ' + str(c.class_level)
for c in self.class_list]
@property
def primary_class(self):
@@ -176,7 +186,7 @@ class Character():
@property
def features(self):
fts = set(self.other_features)
fts = set(self.custom_features)
if not self.class_initialized:
return fts
for c in self.class_list:
@@ -190,6 +200,10 @@ class Character():
if self.background is not None:
fts |= set(getattr(self.background, 'features', ()))
return tuple(fts)
@property
def custom_features_text(self):
return tuple([f.name for f in self.custom_features])
@property
def saving_throw_proficiencies(self):
@@ -279,7 +293,7 @@ class Character():
name=f, source='Unknown',
__doc__="""Unknown Feature. Add to features.py"""))
warnings.warn(msg)
self.other_features = tuple(F() for F in _features)
self.custom_features = tuple(F() for F in _features)
elif (attr == 'spells') or (attr == 'spells_prepared'):
# Create a list of actual spell objects
_spells = []
@@ -300,8 +314,8 @@ class Character():
# Instantiate them all for the spells list
self.spells = tuple(S() for S in _spells)
else:
# this is a list of spell classes
self.spells_prepared = tuple(_spells)
# Instantiate them all for the spells list
self.spells_prepared = tuple(S() for S in _spells)
else:
if not hasattr(self, attr):
warnings.warn(f"Setting unknown character attribute {attr}",
@@ -401,7 +415,7 @@ class Character():
directly.
"""
if shield not in ('', None):
if shield not in ('', 'None', None):
try:
NewShield = findattr(armor, shield)
except AttributeError:
@@ -519,7 +533,7 @@ class Character():
raise ValueError(
'level was not recognizable as an int: {:s}'.format(lvl))
params = {}
params['feature_choices'] = char_props.pop('feature_choices', [])
params['feature_choices'] = char_props.get('feature_choices', [])
class_list += [this_class(this_level, subclass=sub, **params)]
# accept backwards compatability for single-class characters
if len(class_list) == 0:
@@ -532,7 +546,28 @@ class Character():
char = cls(**char_props)
return char
def save(self, filename, template_file='character_template.txt'):
# Create the template context
context = dict(
char=self,
)
# Render the template
src_path = os.path.dirname(__file__)
text = jinja2.Environment(
loader=jinja2.FileSystemLoader(src_path or './')
).get_template(template_file).render(context)
# Save the file
with open(filename, mode='w') as f:
f.write(text)
def to_pdf(self, filename, **kwargs):
char_file = filename.replace('pdf', 'py')
self.save(char_file,
template_file=kwargs.get('template_file',
'character_template.txt'))
subprocess.call(['makesheets', char_file])
def read_character_file(filename):
"""Create a character object from the given definition file.
+32 -25
View File
@@ -5,14 +5,13 @@ sheet by running ``makesheets`` from the command line.
"""
dungeonsheets_version = "{{ dungeonsheets_version }}"
dungeonsheets_version = "{{ char.dungeonsheets_version }}"
name = '{{ char.name }}'
character_class = '{{ char.class_name }}'
player_name = '{{ char.player_name }}'
name = "{{ char.name }}"
classes_levels = {{ char.classes_levels }}
player_name = "{{ char.player_name }}"
background = "{{ char.background.name }}"
race = "{{ char.race.name }}"
level = {{ char.level }}
alignment = "{{ char.alignment }}"
xp = {{ char.xp }}
hp_max = {{ char.hp_max }}
@@ -24,10 +23,23 @@ constitution = {{ char.constitution.value }}
intelligence = {{ char.intelligence.value }}
wisdom = {{ char.wisdom.value }}
charisma = {{ char.charisma.value }}
# Select what skills you're proficient with
skill_proficiencies = {{ char.skill_proficiencies }}
# Named features / feats that aren't part of your classes,
# race, or background.
# Example:
# features = ('Tavern Brawler',) # take the optional Feat from PHB
features = {{ char.custom_features }}
# If selecting among multiple feature options: ex Fighting Style
# Example (Fighting Style):
# feature_choices = ('Archery',)
feature_choices = {{ char.feature_choices }}
# Proficiencies and languages
languages = "{{ char.languages }}"
languages = """{{ char.languages }}"""
# Inventory
# TODO: Get yourself some money
@@ -38,35 +50,30 @@ gp = 0
pp = 0
# TODO: Put your equipped weapons and armor here
weapons = () # Example: ('shortsword', 'longsword')
armor = "" # Eg "light leather armor"
shield = "" # Eg "shield"
weapons = {{ char.weapons }} # Example: ('shortsword', 'longsword')
armor = "{{ char.armor }}" # Eg "light leather armor"
shield = "{{ char.shield }}" # Eg "shield"
equipment = "TODO: Describe your equipment from your {{ char.class_name }} class and {{ char.background.name }} background."
equipment = """{{ char.equipment }}"""
attacks_and_spellcasting = "TODO: Describe specifics for how your {{ char.class_name }} attacks."
attacks_and_spellcasting = """{{ char.attacks_and_spellcasting }}"""
# List of known spells
# Example: spells = ('magic missile', 'mage armor')
spells = () # Todo: Learn some spells
spells = {{ char.spells }} # Todo: Learn some spells
# Which spells have been prepared (not including cantrips)
spells_prepared = ()
spells_prepared = {{ char.spells_prepared }}
# Backstory
# TODO: Describe your backstory here
personality_traits = """I am a leaf on the wind,
watch how I...
"""
# Describe your backstory here
personality_traits = """{{ char.personality_traits}}"""
ideals = """
"""
ideals = """{{ char.ideals }}"""
bonds = """
"""
bonds = """{{ char.bonds }}"""
flaws = """
"""
flaws = """{{ char.flaws }}"""
features_and_traits = """
"""
features_and_traits = """{{ char.features_and_traits }}"""
+1 -1
View File
@@ -51,4 +51,4 @@ class Ranger(CharClass):
# Custom Classes
class Revisedranger(Ranger):
class_name = 'Revised Ranger'
class_name = 'Revisedranger'
+13 -13
View File
@@ -14,7 +14,7 @@ import subprocess
import npyscreen
import jinja2
from dungeonsheets import character, race, dice, background
from dungeonsheets import character, race, dice, background, classes
def read_version():
@@ -24,18 +24,18 @@ def read_version():
char_classes = {
'Barbarian': character.Barbarian,
'Bard': character.Bard,
'Cleric': character.Cleric,
'Druid': character.Druid,
'Fighter': character.Fighter,
'Monk': character.Monk,
'Paladin': character.Paladin,
'Ranger': character.Ranger,
'Rogue': character.Rogue,
'Sorceror': character.Sorceror,
'Warlock': character.Warlock,
'Wizard': character.Wizard
'Barbarian': classes.Barbarian,
'Bard': classes.Bard,
'Cleric': classes.Cleric,
'Druid': classes.Druid,
'Fighter': classes.Fighter,
'Monk': classes.Monk,
'Paladin': classes.Paladin,
'Ranger': classes.Ranger,
'Rogue': classes.Rogue,
'Sorceror': classes.Sorceror,
'Warlock': classes.Warlock,
'Wizard': classes.Wizard
}
races = {
+3
View File
@@ -37,6 +37,9 @@ class Feature():
def __str__(self):
return self.name
def __repr__(self):
return "\"{:s}\"".format(self.name)
def weapon_func(self, weapon: weapons.Weapon, **kwargs):
"""
+1 -1
View File
@@ -175,7 +175,7 @@ def create_spells_pdf(char, basename, flatten=False):
prep_names = tuple(f'Check Box {i}' for i in prep_numbers[level])
for spell, field, chk_field in zip(spells, field_names, prep_names):
fields[field] = str(spell)
is_prepared = any([isinstance(spell, Spl)
is_prepared = any([spell == Spl
for Spl in char.spells_prepared])
fields[chk_field] = CHECKBOX_ON if is_prepared else CHECKBOX_OFF
# # Uncomment to post field names instead:
+7 -2
View File
@@ -14,7 +14,9 @@ def create_spell(**params):
NewSpell
New spell class, subclass of ``Spell``, with given params.
"""
NewSpell = type('UnknownSpell', (Spell,), params)
NewSpell = Spell
NewSpell.name = params.get('name', 'Unknown Spell')
NewSpell.level = params.get('level', 9)
return NewSpell
@@ -41,8 +43,11 @@ class Spell():
return s
def __repr__(self):
return f'<{self.name}>'
return "\"{:s}\"".format(self.name)
def __eq__(self, other):
return (self.name == other.name) and (self.level == other.level)
@property
def component_string(self):
s = f'{", ".join(self.components)}'
+6
View File
@@ -24,6 +24,12 @@ class Weapon():
def is_ranged(self):
return ('range' in self.properties.lower()) and ('thrown' not in self.properties.lower())
def __str__(self):
return self.name
def __repr__(self):
return "\"{:s}\"".format(self.name)
class Club(Weapon):
name = "Club"