mirror of
https://github.com/Threnklyn/dungeon-sheets.git
synced 2026-06-05 12:29:39 +02:00
Merge pull request #71 from 94d90b08-c4ef-416c-bf7b-b6c5b7275e6a/master
hp_max basic auto-calculation, boolean inspiration
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
install:
|
install:
|
||||||
python setup.py install
|
python setup.py install
|
||||||
@echo "\n\n================="
|
@echo ""
|
||||||
|
@echo "================="
|
||||||
@echo "For optimal performance we highly recommend installing PDFTK: https://www.pdflabs.com/tools/pdftk-the-pdf-toolkit/"
|
@echo "For optimal performance we highly recommend installing PDFTK: https://www.pdflabs.com/tools/pdftk-the-pdf-toolkit/"
|
||||||
@echo "If installing on OSX >= 10.11, see here: https://stackoverflow.com/questions/32505951/pdftk-server-on-os-x-10-11/33248310#33248310"
|
@echo "If installing on OSX >= 10.11, see here: https://stackoverflow.com/questions/32505951/pdftk-server-on-os-x-10-11/33248310#33248310"
|
||||||
|
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ class Character():
|
|||||||
_background = None
|
_background = None
|
||||||
xp = 0
|
xp = 0
|
||||||
# Hit points
|
# Hit points
|
||||||
hp_max = 10
|
hp_max = None
|
||||||
# Base stats (ability scores)
|
# Base stats (ability scores)
|
||||||
strength = Ability()
|
strength = Ability()
|
||||||
dexterity = Ability()
|
dexterity = Ability()
|
||||||
@@ -82,7 +82,7 @@ class Character():
|
|||||||
armor_class = ArmorClass()
|
armor_class = ArmorClass()
|
||||||
initiative = Initiative()
|
initiative = Initiative()
|
||||||
speed = Speed()
|
speed = Speed()
|
||||||
inspiration = 0
|
inspiration = False
|
||||||
_saving_throw_proficiencies = tuple() # use to overwrite class proficiencies
|
_saving_throw_proficiencies = tuple() # use to overwrite class proficiencies
|
||||||
other_weapon_proficiencies = tuple() # add to class/race proficiencies
|
other_weapon_proficiencies = tuple() # add to class/race proficiencies
|
||||||
skill_proficiencies = list()
|
skill_proficiencies = list()
|
||||||
@@ -161,6 +161,7 @@ class Character():
|
|||||||
self.background = attrs.pop('background', None)
|
self.background = attrs.pop('background', None)
|
||||||
# parse all other attributes
|
# parse all other attributes
|
||||||
self.set_attrs(**attrs)
|
self.set_attrs(**attrs)
|
||||||
|
self.__set_max_hp(attrs.get('hp_max', None))
|
||||||
|
|
||||||
def clear(self):
|
def clear(self):
|
||||||
# reset class-definied items
|
# reset class-definied items
|
||||||
@@ -317,6 +318,25 @@ class Character():
|
|||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def __set_max_hp(self, hp_max):
|
||||||
|
"""
|
||||||
|
Set maximum HP based on value in charlist py or calc from classes
|
||||||
|
"""
|
||||||
|
if hp_max:
|
||||||
|
assert isinstance(hp_max, int)
|
||||||
|
self.hp_max = hp_max
|
||||||
|
else:
|
||||||
|
const_mod = self.constitution.modifier
|
||||||
|
level_one_hp = self.primary_class.hit_dice_faces + const_mod
|
||||||
|
self.hp_max = level_one_hp
|
||||||
|
for char_cls in self.class_list:
|
||||||
|
hp_per_lvl = char_cls.hit_dice_faces/2 + 1 + const_mod
|
||||||
|
levels = char_cls.level
|
||||||
|
if char_cls == self.primary_class:
|
||||||
|
levels -= 1
|
||||||
|
assert levels >= 0
|
||||||
|
self.hp_max += int(hp_per_lvl * levels)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def weapon_proficiencies(self):
|
def weapon_proficiencies(self):
|
||||||
wp = set(self.other_weapon_proficiencies)
|
wp = set(self.other_weapon_proficiencies)
|
||||||
@@ -451,8 +471,10 @@ class Character():
|
|||||||
return sorted(tuple(spells), key=(lambda x: (x.name)))
|
return sorted(tuple(spells), key=(lambda x: (x.name)))
|
||||||
|
|
||||||
def set_attrs(self, **attrs):
|
def set_attrs(self, **attrs):
|
||||||
"""Bulk setting of attributes. Useful for loading a character from a
|
"""
|
||||||
dictionary."""
|
Bulk setting of attributes
|
||||||
|
Useful for loading a character from a dictionary
|
||||||
|
"""
|
||||||
for attr, val in attrs.items():
|
for attr, val in attrs.items():
|
||||||
if attr == 'dungeonsheets_version':
|
if attr == 'dungeonsheets_version':
|
||||||
pass # Maybe we'll verify this later?
|
pass # Maybe we'll verify this later?
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ alignment = "{{ char.alignment }}"
|
|||||||
|
|
||||||
xp = {{ char.xp }}
|
xp = {{ char.xp }}
|
||||||
hp_max = {{ char.hp_max }}
|
hp_max = {{ char.hp_max }}
|
||||||
inspiration = {{ char.inspiration }} # integer inspiration value
|
inspiration = {{ char.inspiration }} # boolean inspiration value
|
||||||
|
|
||||||
# Ability Scores
|
# Ability Scores
|
||||||
strength = {{ char.strength.value }}
|
strength = {{ char.strength.value }}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ alignment = "{{ char.alignment }}"
|
|||||||
|
|
||||||
xp = {{ char.xp }}
|
xp = {{ char.xp }}
|
||||||
hp_max = {{ char.hp_max }}
|
hp_max = {{ char.hp_max }}
|
||||||
inspiration = {{ char.inspiration }} # integer inspiration value
|
inspiration = {{ char.inspiration }} # boolean inspiration value
|
||||||
|
|
||||||
# Ability Scores
|
# Ability Scores
|
||||||
strength = {{ char.strength.value }}
|
strength = {{ char.strength.value }}
|
||||||
|
|||||||
@@ -289,7 +289,7 @@ def create_character_pdf(character, basename, flatten=False):
|
|||||||
'Race ': str(character.race),
|
'Race ': str(character.race),
|
||||||
'Alignment': character.alignment,
|
'Alignment': character.alignment,
|
||||||
'XP': str(character.xp),
|
'XP': str(character.xp),
|
||||||
'Inspiration': str(character.inspiration),
|
'Inspiration': str('Yes' if character.inspiration else 'No'),
|
||||||
# Abilities
|
# Abilities
|
||||||
'ProfBonus': mod_str(character.proficiency_bonus),
|
'ProfBonus': mod_str(character.proficiency_bonus),
|
||||||
'STRmod': str(character.strength.value),
|
'STRmod': str(character.strength.value),
|
||||||
@@ -400,11 +400,13 @@ def create_character_pdf(character, basename, flatten=False):
|
|||||||
fields[atk_field] = '{:+d}'.format(weapon.attack_modifier)
|
fields[atk_field] = '{:+d}'.format(weapon.attack_modifier)
|
||||||
fields[dmg_field] = f'{weapon.damage}/{weapon.damage_type}'
|
fields[dmg_field] = f'{weapon.damage}/{weapon.damage_type}'
|
||||||
# Other attack information
|
# Other attack information
|
||||||
attack_str = f'Armor: {character.armor}'
|
attack = []
|
||||||
attack_str += '\n \n'
|
if character.armor:
|
||||||
attack_str += f'Shield: {character.shield}'
|
attack.append(f'Armor: {character.armor}')
|
||||||
attack_str += '\n \n'
|
if character.shield:
|
||||||
attack_str += character.attacks_and_spellcasting
|
attack.append(f'Shield: {character.shield}')
|
||||||
|
attack.append(character.attacks_and_spellcasting)
|
||||||
|
attack_str = '\n\n'.join(attack)
|
||||||
fields['AttacksSpellcasting'] = text_box(attack_str)
|
fields['AttacksSpellcasting'] = text_box(attack_str)
|
||||||
# Other proficiencies and languages
|
# Other proficiencies and languages
|
||||||
prof_text = "Proficiencies:\n" + text_box(character.proficiencies_text)
|
prof_text = "Proficiencies:\n" + text_box(character.proficiencies_text)
|
||||||
|
|||||||
Regular → Executable
+10
-1
@@ -21,7 +21,11 @@ class TestCharacter(TestCase):
|
|||||||
char.level = 2
|
char.level = 2
|
||||||
char.hit_dice_faces = 10
|
char.hit_dice_faces = 10
|
||||||
self.assertEqual(char.hit_dice, '2d10')
|
self.assertEqual(char.hit_dice, '2d10')
|
||||||
|
|
||||||
|
def test_max_hp(self):
|
||||||
|
char = Wizard(level=3, constitution=12)
|
||||||
|
self.assertEqual(char.hp_max, 17)
|
||||||
|
|
||||||
def test_set_attrs(self):
|
def test_set_attrs(self):
|
||||||
char = Character()
|
char = Character()
|
||||||
char.set_attrs(name='Inara')
|
char.set_attrs(name='Inara')
|
||||||
@@ -37,6 +41,11 @@ class TestCharacter(TestCase):
|
|||||||
# Check that race gets set to an object
|
# Check that race gets set to an object
|
||||||
char.set_attrs(race='high elf')
|
char.set_attrs(race='high elf')
|
||||||
self.assertIsInstance(char.race, race.HighElf)
|
self.assertIsInstance(char.race, race.HighElf)
|
||||||
|
# Check inspiration works
|
||||||
|
char.set_attrs(inspiration=True)
|
||||||
|
self.assertTrue(char.inspiration)
|
||||||
|
char.set_attrs(inspiration=False)
|
||||||
|
self.assertFalse(char.inspiration)
|
||||||
|
|
||||||
def test_wield_weapon(self):
|
def test_wield_weapon(self):
|
||||||
char = Character()
|
char = Character()
|
||||||
|
|||||||
Reference in New Issue
Block a user