artificer is now fully usable

Now user can pick Artificer and it works as it should.
This commit adds spell slot calculations for multiclassing with
Artificer.
This commit is contained in:
Robert Kubosz
2020-05-12 14:51:33 +02:00
parent 9a526278b3
commit 8b56d5c651
4 changed files with 37 additions and 7 deletions
+27 -2
View File
@@ -6,11 +6,13 @@ import os
import re import re
import subprocess import subprocess
import warnings import warnings
import math
import jinja2 import jinja2
from dungeonsheets import (armor, background, classes, exceptions, features, from dungeonsheets import (armor, background, classes, exceptions, features,
magic_items, monsters, race, spells, weapons) infusions, magic_items, monsters, race, spells,
weapons)
from dungeonsheets.armor import Armor, NoArmor, NoShield, Shield from dungeonsheets.armor import Armor, NoArmor, NoShield, Shield
from dungeonsheets.dice import read_dice_str from dungeonsheets.dice import read_dice_str
from dungeonsheets.stats import (Ability, ArmorClass, Initiative, Skill, Speed, from dungeonsheets.stats import (Ability, ArmorClass, Initiative, Skill, Speed,
@@ -27,7 +29,7 @@ __version__ = read('../VERSION').strip()
dice_re = re.compile('(\d+)d(\d+)') dice_re = re.compile('(\d+)d(\d+)')
__all__ = ('Barbarian', 'Bard', 'Cleric', 'Druid', 'Fighter', 'Monk', __all__ = ('Artificer', 'Barbarian', 'Bard', 'Cleric', 'Druid', 'Fighter', 'Monk',
'Paladin', 'Ranger', 'Rogue', 'Sorcerer', 'Warlock', 'Wizard', ) 'Paladin', 'Ranger', 'Rogue', 'Sorcerer', 'Warlock', 'Wizard', )
multiclass_spellslots_by_level = { multiclass_spellslots_by_level = {
@@ -128,6 +130,7 @@ class Character():
spellcasting_ability = None spellcasting_ability = None
_spells = list() _spells = list()
_spells_prepared = list() _spells_prepared = list()
infusions = list()
# Features IN MAJOR DEVELOPMENT # Features IN MAJOR DEVELOPMENT
custom_features = list() custom_features = list()
feature_choices = list() feature_choices = list()
@@ -171,6 +174,7 @@ class Character():
self._proficiencies_text = list() self._proficiencies_text = list()
self._spells = list() self._spells = list()
self._spells_prepared = list() self._spells_prepared = list()
self.infusions = list()
self.custom_features = list() self.custom_features = list()
self.feature_choices = list() self.feature_choices = list()
@@ -417,6 +421,8 @@ class Character():
eff_level += c.level // 2 eff_level += c.level // 2
elif type(c) in [classes.Fighter, classes.Rogue]: elif type(c) in [classes.Fighter, classes.Rogue]:
eff_level += c.level // 3 eff_level += c.level // 3
elif type(c) is classes.Artificer:
eff_level += math.ceil(c.level / 2)
if eff_level == 0: if eff_level == 0:
return 0 return 0
else: else:
@@ -516,6 +522,18 @@ class Character():
else: else:
# Instantiate them all for the spells list # Instantiate them all for the spells list
self._spells_prepared = tuple(S() for S in _spells) self._spells_prepared = tuple(S() for S in _spells)
elif attr == 'infusions':
if hasattr(self, 'Artificer'):
_infusions = []
for infusion_name in val:
try:
_infusions.append(findattr(infusions, infusion_name))
except AttributeError:
msg = (f'Infusion "{infusion_name}" not defined. '
f'Please add it to ``infusions.py``')
warnings.warn(msg)
_infusions.sort(key=lambda infusion: infusion.name)
self.infusions = tuple(I() for I in _infusions)
else: else:
if not hasattr(self, attr): if not hasattr(self, attr):
warnings.warn(f"Setting unknown character attribute {attr}", warnings.warn(f"Setting unknown character attribute {attr}",
@@ -788,6 +806,13 @@ def read_character_file(filename):
# Add backwards compatability for tests # Add backwards compatability for tests
class Artificer(Character):
def __init__(self, level=1, **attrs):
attrs['classes'] = ['Artificer']
attrs['levels'] = [level]
super().__init__(**attrs)
class Barbarian(Character): class Barbarian(Character):
def __init__(self, level=1, **attrs): def __init__(self, level=1, **attrs):
attrs['classes'] = ['Barbarian'] attrs['classes'] = ['Barbarian']
+1
View File
@@ -84,6 +84,7 @@ class Artificer(CharClass):
"Light armor", "Medium armor", "Shields", "Light armor", "Medium armor", "Shields",
"Thieve's tools", "Tinker's tools") "Thieve's tools", "Tinker's tools")
weapon_proficiencies = (weapons.SimpleWeapon,) weapon_proficiencies = (weapons.SimpleWeapon,)
infusions = []
class_skill_choices = ( class_skill_choices = (
'Arcana', 'History', 'Investigation', 'Arcana', 'History', 'Investigation',
'Medicine', 'Nature', 'Perception', 'Sleight of Hand') 'Medicine', 'Nature', 'Perception', 'Sleight of Hand')
+8 -4
View File
@@ -10,7 +10,7 @@
[% endif %] [% endif %]
\title{Infusion Descriptions} \title{Infusion Descriptions}
\author{[[ character.name ]]} \author{[[ character.name ]] (Artificer [[ character.Artificer.level ]] level)}
\date{} \date{}
\begin{document} \begin{document}
@@ -22,13 +22,17 @@
\section*{[[ inf.name ]]} \section*{[[ inf.name ]]}
[% if inf.prerequisite %]% [% if inf.prerequisite %]%
\noindent
\textit{Prerequisite: [[ inf.prerequisite ]]}% \textit{Prerequisite: [[ inf.prerequisite ]]}%
[% endif %]% [% endif %]%
[% if inf.item %]% [% if inf.item %]%
\textit{Item: [[ inf.item ]]}%
[% endif %]%
%% \noindent \noindent
\textit{Item: [[ inf.item ]]}%
[% endif %]%
[[ inf.__doc__|rst_to_latex ]] [[ inf.__doc__|rst_to_latex ]]
+1 -1
View File
@@ -9,7 +9,7 @@ class Infusion():
def __str__(self): def __str__(self):
indicator = ('$', self.special_material) indicator = ('$', self.special_material)
if indicator: if indicator:
return self.name += f' ({"".join(indicator)})' return self.name + f' ({"".join(indicator)})'
else: else:
return self.name return self.name