mirror of
https://github.com/Threnklyn/dungeon-sheets.git
synced 2026-05-18 20:23:27 +02:00
Create character now does class skills and saves the results.
This commit is contained in:
@@ -40,6 +40,8 @@ class Character():
|
|||||||
charisma = Ability()
|
charisma = Ability()
|
||||||
saving_throw_proficiencies = []
|
saving_throw_proficiencies = []
|
||||||
skill_proficiencies = tuple()
|
skill_proficiencies = tuple()
|
||||||
|
class_skill_choices = tuple()
|
||||||
|
num_skill_choices = 2
|
||||||
weapon_proficiencies = tuple()
|
weapon_proficiencies = tuple()
|
||||||
proficiencies_extra = tuple()
|
proficiencies_extra = tuple()
|
||||||
languages = ""
|
languages = ""
|
||||||
@@ -304,6 +306,8 @@ class Barbarian(Character):
|
|||||||
_proficiencies_text = ('light armor', 'medium armor', 'shields',
|
_proficiencies_text = ('light armor', 'medium armor', 'shields',
|
||||||
'simple weapons', 'martial weapons')
|
'simple weapons', 'martial weapons')
|
||||||
weapon_proficiencies = (weapons.simple_weapons + weapons.martial_weapons)
|
weapon_proficiencies = (weapons.simple_weapons + weapons.martial_weapons)
|
||||||
|
class_skill_choices = ('Animal Handling', 'Athletics',
|
||||||
|
'Intimidation', 'Nature', 'Perception', 'Survival')
|
||||||
|
|
||||||
|
|
||||||
class Bard(Character):
|
class Bard(Character):
|
||||||
@@ -316,6 +320,12 @@ class Bard(Character):
|
|||||||
weapon_proficiencies = ((weapons.HandCrossbow, weapons.Longsword,
|
weapon_proficiencies = ((weapons.HandCrossbow, weapons.Longsword,
|
||||||
weapons.Rapier, weapons.Shortsword) +
|
weapons.Rapier, weapons.Shortsword) +
|
||||||
weapons.simple_weapons)
|
weapons.simple_weapons)
|
||||||
|
class_skill_choices = ('Acrobatics', 'Animal Handling', 'Arcana',
|
||||||
|
'Athletics', 'Deception', 'History', 'Insight',
|
||||||
|
'Intimidation', 'Investigation', 'Medicine', 'Nature',
|
||||||
|
'Perception', 'Performance', 'Persuasion', 'Religion',
|
||||||
|
'Sleight of Hand', 'Stealth', 'Survival')
|
||||||
|
num_skill_choices = 3
|
||||||
|
|
||||||
|
|
||||||
class Cleric(Character):
|
class Cleric(Character):
|
||||||
@@ -325,6 +335,8 @@ class Cleric(Character):
|
|||||||
_proficiencies_text = ('light armor', 'medium armor', 'shields',
|
_proficiencies_text = ('light armor', 'medium armor', 'shields',
|
||||||
'all simple weapons')
|
'all simple weapons')
|
||||||
weapon_proficiencies = weapons.simple_weapons
|
weapon_proficiencies = weapons.simple_weapons
|
||||||
|
class_skill_choices = ('History', 'Insight', 'Medicine',
|
||||||
|
'Persuasion', 'Religion')
|
||||||
|
|
||||||
|
|
||||||
class Druid(Character):
|
class Druid(Character):
|
||||||
@@ -339,6 +351,8 @@ class Druid(Character):
|
|||||||
weapon_proficiencies = (weapons.Club, weapons.Dagger, weapons.Dart,
|
weapon_proficiencies = (weapons.Club, weapons.Dagger, weapons.Dart,
|
||||||
weapons.Javelin, weapons.Mace, weapons.Quarterstaff,
|
weapons.Javelin, weapons.Mace, weapons.Quarterstaff,
|
||||||
weapons.Scimitar, weapons.Sickle, weapons.Sling, weapons.Spear)
|
weapons.Scimitar, weapons.Sickle, weapons.Sling, weapons.Spear)
|
||||||
|
class_skill_choices = ('Arcana', 'Animal Handling', 'Insight',
|
||||||
|
'Medicine', 'Nature', 'Perception', 'Religion', 'Survival')
|
||||||
|
|
||||||
|
|
||||||
class Fighter(Character):
|
class Fighter(Character):
|
||||||
@@ -347,6 +361,9 @@ class Fighter(Character):
|
|||||||
saving_throw_proficiencies = ('strength', 'constitution')
|
saving_throw_proficiencies = ('strength', 'constitution')
|
||||||
_proficiencies_text = ('All armar', 'shields', 'simple weapons', 'martial weapons')
|
_proficiencies_text = ('All armar', 'shields', 'simple weapons', 'martial weapons')
|
||||||
weapon_proficiencies = weapons.simple_weapons + weapons.martial_weapons
|
weapon_proficiencies = weapons.simple_weapons + weapons.martial_weapons
|
||||||
|
class_skill_choices = ('Acrobatics', 'Animal Handling',
|
||||||
|
'Athletics', 'History', 'Insight', 'Intimidation', 'Perception',
|
||||||
|
'Survival')
|
||||||
|
|
||||||
|
|
||||||
class Monk(Character):
|
class Monk(Character):
|
||||||
@@ -357,7 +374,7 @@ class Monk(Character):
|
|||||||
'simple weapons', 'shortswords',
|
'simple weapons', 'shortswords',
|
||||||
"one type of artisan's tools or one musical instrument")
|
"one type of artisan's tools or one musical instrument")
|
||||||
weapon_proficiencies = (weapons.Shortsword,) + weapons.simple_weapons
|
weapon_proficiencies = (weapons.Shortsword,) + weapons.simple_weapons
|
||||||
|
class_skill_choices = ('Acrobatics', 'Athletics', 'History', 'Insight', 'Religion', 'Stealth')
|
||||||
|
|
||||||
class Paladin(Character):
|
class Paladin(Character):
|
||||||
class_name = 'Paladin'
|
class_name = 'Paladin'
|
||||||
@@ -366,6 +383,8 @@ class Paladin(Character):
|
|||||||
_proficiencies_text = ('All armor', 'shields', 'simple weapons',
|
_proficiencies_text = ('All armor', 'shields', 'simple weapons',
|
||||||
'martial weapons')
|
'martial weapons')
|
||||||
weapon_proficiencies = weapons.simple_weapons + weapons.martial_weapons
|
weapon_proficiencies = weapons.simple_weapons + weapons.martial_weapons
|
||||||
|
class_skill_choices = ("Athletics", 'Insight', 'Intimidation',
|
||||||
|
'Medicine', 'Persuasion', 'Religion')
|
||||||
|
|
||||||
|
|
||||||
class Ranger(Character):
|
class Ranger(Character):
|
||||||
@@ -375,6 +394,9 @@ class Ranger(Character):
|
|||||||
_proficiencies_text = ("light armor", "medium armor", "shields",
|
_proficiencies_text = ("light armor", "medium armor", "shields",
|
||||||
"simple weapons", "martial weapons")
|
"simple weapons", "martial weapons")
|
||||||
weapon_proficiencies = weapons.simple_weapons + weapons.martial_weapons
|
weapon_proficiencies = weapons.simple_weapons + weapons.martial_weapons
|
||||||
|
class_skill_choices = ('Animal Handling', 'Athletics', 'Insight',
|
||||||
|
'Investigation', 'Nature', 'Perception', 'Stealth', 'Survival')
|
||||||
|
num_skill_choices = 3
|
||||||
|
|
||||||
|
|
||||||
class Rogue(Character):
|
class Rogue(Character):
|
||||||
@@ -386,6 +408,9 @@ class Rogue(Character):
|
|||||||
'rapiers', 'shortswords', "thieves' tools")
|
'rapiers', 'shortswords', "thieves' tools")
|
||||||
weapon_proficiencies = (weapons.HandCrossbow, weapons.Longsword,
|
weapon_proficiencies = (weapons.HandCrossbow, weapons.Longsword,
|
||||||
weapons.Rapier, weapons.Shortsword) + weapons.simple_weapons
|
weapons.Rapier, weapons.Shortsword) + weapons.simple_weapons
|
||||||
|
class_skill_choices = ('Acrobatics', 'Athletics', 'Deception',
|
||||||
|
'Insight', 'Intimidation', 'Investigation', 'Perception',
|
||||||
|
'Performance', 'Persuasion', 'Sleight of Hand', 'Stealth')
|
||||||
|
|
||||||
|
|
||||||
class Sorceror(Character):
|
class Sorceror(Character):
|
||||||
@@ -397,6 +422,8 @@ class Sorceror(Character):
|
|||||||
weapon_proficiencies = (weapons.Dagger, weapons.Dart,
|
weapon_proficiencies = (weapons.Dagger, weapons.Dart,
|
||||||
weapons.Sling, weapons.Quarterstaff,
|
weapons.Sling, weapons.Quarterstaff,
|
||||||
weapons.LightCrossbow)
|
weapons.LightCrossbow)
|
||||||
|
class_skill_choices = ('Arcana', 'Deception', 'Insight',
|
||||||
|
'Intimidation' ,'Persuasion', 'Religion')
|
||||||
|
|
||||||
|
|
||||||
class Warlock(Character):
|
class Warlock(Character):
|
||||||
@@ -404,6 +431,8 @@ class Warlock(Character):
|
|||||||
hit_dice_faces = 8
|
hit_dice_faces = 8
|
||||||
saving_throw_proficiencies = ('wisdom', 'charisma')
|
saving_throw_proficiencies = ('wisdom', 'charisma')
|
||||||
_proficiencies_text = ("light Armor", "simple weapons")
|
_proficiencies_text = ("light Armor", "simple weapons")
|
||||||
|
class_skill_choices = ('Arcana', 'Deception', 'History',
|
||||||
|
'Intimidation', 'Investigation', 'Nature', 'Religion')
|
||||||
weapon_proficiencies = weapons.simple_weapons
|
weapon_proficiencies = weapons.simple_weapons
|
||||||
spellcasting_ability = 'charisma'
|
spellcasting_ability = 'charisma'
|
||||||
spell_slots_by_level = {
|
spell_slots_by_level = {
|
||||||
@@ -439,6 +468,8 @@ class Wizard(Character):
|
|||||||
weapon_proficiencies = (weapons.Dagger, weapons.Dart,
|
weapon_proficiencies = (weapons.Dagger, weapons.Dart,
|
||||||
weapons.Sling, weapons.Quarterstaff,
|
weapons.Sling, weapons.Quarterstaff,
|
||||||
weapons.LightCrossbow)
|
weapons.LightCrossbow)
|
||||||
|
class_skill_choices = ('Arcana', 'History', 'Investigation',
|
||||||
|
'Medicine', 'Religion')
|
||||||
spellcasting_ability = 'intelligence'
|
spellcasting_ability = 'intelligence'
|
||||||
spell_slots_by_level = {
|
spell_slots_by_level = {
|
||||||
# char_lvl: (cantrips, 1st, 2nd, 3rd, ...)
|
# char_lvl: (cantrips, 1st, 2nd, 3rd, ...)
|
||||||
|
|||||||
@@ -0,0 +1,94 @@
|
|||||||
|
name = '{{ char.name }}'
|
||||||
|
character_class = '{{ char.class_name }}'
|
||||||
|
player_name = '{{ char.player_name }}'
|
||||||
|
background = "{{ char.background }}"
|
||||||
|
race = "{{ char.race.name }}"
|
||||||
|
level = {{ char.level }}
|
||||||
|
alignment = "{{ char.alignment }}"
|
||||||
|
xp = {{ char.xp }}
|
||||||
|
hp_max = {{ char.hp_max }}
|
||||||
|
|
||||||
|
# Ability Scores
|
||||||
|
strength = {{ char.strength.value }}
|
||||||
|
dexterity = {{ char.dexterity.value }}
|
||||||
|
constitution = {{ char.constitution.value }}
|
||||||
|
intelligence = {{ char.intelligence.value }}
|
||||||
|
wisdom = {{ char.wisdom.value }}
|
||||||
|
charisma = {{ char.charisma.value }}
|
||||||
|
skill_proficiencies = (
|
||||||
|
# Put your skill proficiencies here, including the {{ char.race }} race.
|
||||||
|
)
|
||||||
|
|
||||||
|
# Proficiencies and languages
|
||||||
|
languages = "Common, Elvish, Draconic, Dwarvish, Goblin."
|
||||||
|
|
||||||
|
# Inventory
|
||||||
|
cp = 0
|
||||||
|
sp = 0
|
||||||
|
ep = 0
|
||||||
|
gp = 0
|
||||||
|
pp = 0
|
||||||
|
weapons = ('shortsword', 'longsword')
|
||||||
|
equipment = (
|
||||||
|
"""Gallon of ale, red cloak, shortsword, longsword, jar of salt, vodka
|
||||||
|
(500mL), potion of vitality, wand of magic missiles (7/7),
|
||||||
|
component pouch, spellbook, backpack, bottle of ink, ink pen, 10
|
||||||
|
sheets of parchment, small knife, tome of historical lore, holy
|
||||||
|
symbol, prayer book, set of common clothes, pouch.""")
|
||||||
|
|
||||||
|
# List of known spells
|
||||||
|
spells = ('blindness deafness', 'burning hands', 'detect magic',
|
||||||
|
'false life', 'mage armor', 'mage hand', 'magic missile',
|
||||||
|
'prestidigitation', 'ray of frost', 'ray of sickness', 'shield',
|
||||||
|
'shocking grasp', 'sleep', 'some other spell')
|
||||||
|
# Which spells have been prepared (not including cantrips)
|
||||||
|
spells_prepared = ('blindness deafness', 'false life', 'mage armor',
|
||||||
|
'ray of sickness', 'shield', 'sleep',)
|
||||||
|
|
||||||
|
# Backstory
|
||||||
|
personality_traits = """I use polysyllabic words that convey the impression of
|
||||||
|
erudition. Also, I’ve spent so long in the temple that I have little
|
||||||
|
experience dealing with people on a casual basis."""
|
||||||
|
|
||||||
|
ideals = """Knowledge. The path to power and self-improvement is through
|
||||||
|
knowledge."""
|
||||||
|
|
||||||
|
bonds = """The tome I carry with me is the record of my life’s work so far,
|
||||||
|
and no vault is secure enough to keep it safe."""
|
||||||
|
|
||||||
|
flaws = """I’ll do just about anything to uncover historical secrets that
|
||||||
|
would add to my research."""
|
||||||
|
|
||||||
|
features_and_traits = (
|
||||||
|
"""Spellcasting Ability: Intelligence is your spellcasting ability for
|
||||||
|
your spells. The saving throw DC to resist a spell you cast is
|
||||||
|
13. Your attack bonus when you make an attack with a spell is
|
||||||
|
+5. See the rulebook for rules on casting your spells.
|
||||||
|
|
||||||
|
Arcane Recovery: You can regain some of your magical energy by
|
||||||
|
studying your spellbook. Once per day during a short rest, you can
|
||||||
|
choose to recover expended spell slots with a combined level equal
|
||||||
|
to or less than half your wizard level (rounded up).
|
||||||
|
|
||||||
|
Darkvision: You see in dim light within a 60-foot radius of you as
|
||||||
|
if it were bright light, and in darkness in that radius as if it
|
||||||
|
were dim light. You can’t discern color in darkness, only shades
|
||||||
|
of gray.
|
||||||
|
|
||||||
|
Fey Ancestry: You have advantage on saving throws against being
|
||||||
|
charmed, and magic can’t put you to sleep.
|
||||||
|
|
||||||
|
Trance: Elves don’t need to sleep. They meditate deeply, remaining
|
||||||
|
semiconscious, for 4 hours a day and gain the same benefit a human
|
||||||
|
does from 8 hours of sleep.
|
||||||
|
|
||||||
|
Shelter of the Faithful: As a servant of Oghma, you command the
|
||||||
|
respect of those who share your faith, and you can perform the
|
||||||
|
rites of Oghma. You and your companions can expect to receive free
|
||||||
|
healing and care at a temple, shrine, or other established
|
||||||
|
presence of Oghma’s faith. Those who share your religion will
|
||||||
|
support you (and only you) at a modest lifestyle. You also have
|
||||||
|
ties to the temple of Oghma in Neverwinter, where you have a
|
||||||
|
residence. When you are in Neverwinter, you can call upon the
|
||||||
|
priests there for assistance that won’t endanger them.""")
|
||||||
|
|
||||||
@@ -7,9 +7,11 @@ logging.basicConfig(filename='character_creater.log', level=logging.DEBUG)
|
|||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
import math
|
import math
|
||||||
|
import os
|
||||||
|
from random import randint
|
||||||
|
|
||||||
import npyscreen
|
import npyscreen
|
||||||
from random import randint
|
import jinja2
|
||||||
|
|
||||||
from dungeonsheets import character, race, dice
|
from dungeonsheets import character, race, dice
|
||||||
|
|
||||||
@@ -48,11 +50,24 @@ races = {
|
|||||||
|
|
||||||
|
|
||||||
class App(npyscreen.NPSAppManaged):
|
class App(npyscreen.NPSAppManaged):
|
||||||
# STARTING_FORM = 'CLASS'
|
# STARTING_FORM = 'SKILLS'
|
||||||
character = None
|
character = None
|
||||||
|
|
||||||
def save_character(self):
|
def save_character(self):
|
||||||
pass
|
# Create the template context
|
||||||
|
context = dict(
|
||||||
|
char=self.character
|
||||||
|
)
|
||||||
|
# Render the template
|
||||||
|
src_path = os.path.dirname(__file__)
|
||||||
|
src_filename = 'character_template.txt'
|
||||||
|
text = jinja2.Environment(
|
||||||
|
loader=jinja2.FileSystemLoader(src_path or './')
|
||||||
|
).get_template(src_filename).render(context)
|
||||||
|
# Save the file
|
||||||
|
filename = self.getForm("SAVE").filename.value
|
||||||
|
with open(filename, mode='w') as f:
|
||||||
|
f.write(text)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def character_class(self, *args, **kwargs):
|
def character_class(self, *args, **kwargs):
|
||||||
@@ -87,15 +102,44 @@ class App(npyscreen.NPSAppManaged):
|
|||||||
max_hp_fld.value = str(max_hp)
|
max_hp_fld.value = str(max_hp)
|
||||||
|
|
||||||
def onStart(self):
|
def onStart(self):
|
||||||
|
self.character = character.Character()
|
||||||
self.addForm("MAIN", BasicInfoForm, name="Basic Info:")
|
self.addForm("MAIN", BasicInfoForm, name="Basic Info:")
|
||||||
self.addForm("CLASS", CharacterClassForm, name="Select your character's class:")
|
self.addForm("CLASS", CharacterClassForm, name="Select your character's class:")
|
||||||
self.addForm("RACE", RaceForm, name="Select your character's race:")
|
self.addForm("RACE", RaceForm, name="Select your character's race:")
|
||||||
self.addForm("ALIGNMENT", AlignmentForm, name="Select your character's alignment:")
|
self.addForm("ALIGNMENT", AlignmentForm, name="Select your character's alignment:")
|
||||||
self.addForm("ABILITIES", AbilityScoreForm, name="Choose ability scores:")
|
self.addForm("ABILITIES", AbilityScoreForm, name="Choose ability scores:")
|
||||||
self.addForm("BACKGROUND", BackgroundForm, name="Choose background:")
|
self.addForm("BACKGROUND", BackgroundForm, name="Choose background:")
|
||||||
|
self.addForm("SKILLS", SkillForm, name="Choose skill proficiencies")
|
||||||
self.addForm("SAVE", SaveForm, name="Save character:")
|
self.addForm("SAVE", SaveForm, name="Save character:")
|
||||||
|
|
||||||
|
|
||||||
|
class SkillForm(npyscreen.ActionForm):
|
||||||
|
|
||||||
|
def while_editing(self):
|
||||||
|
self.skill_proficiencies.set_values(self.parentApp.character.class_skill_choices)
|
||||||
|
self.update_remaining()
|
||||||
|
|
||||||
|
def update_remaining(self, widget=None):
|
||||||
|
remaining = self.parentApp.character.num_skill_choices - len(self.skill_proficiencies.value)
|
||||||
|
log.debug(f'Remaining: {remaining}')
|
||||||
|
self.remaining.value = str(remaining)
|
||||||
|
self.display()
|
||||||
|
|
||||||
|
def create(self):
|
||||||
|
self.remaining = self.add(
|
||||||
|
npyscreen.TitleText, name="Remaining:",
|
||||||
|
value=0, editable=False)
|
||||||
|
self.skill_proficiencies = self.add(
|
||||||
|
npyscreen.TitleMultiSelect, name="Skill Proficiencies:",
|
||||||
|
values=self.parentApp.character.class_skill_choices,
|
||||||
|
value_changed_callback=self.update_remaining)
|
||||||
|
|
||||||
|
def on_ok(self):
|
||||||
|
self.parentApp.setNextForm('SAVE')
|
||||||
|
|
||||||
|
def on_cancel(self):
|
||||||
|
self.parentApp.setNextForm('BACKGROUND')
|
||||||
|
|
||||||
class AbilityScoreForm(npyscreen.ActionForm):
|
class AbilityScoreForm(npyscreen.ActionForm):
|
||||||
def roll_dice(self):
|
def roll_dice(self):
|
||||||
"""Get six ability scores that can then be assigned to abilities."""
|
"""Get six ability scores that can then be assigned to abilities."""
|
||||||
@@ -194,7 +238,7 @@ class BackgroundForm(npyscreen.ActionForm):
|
|||||||
background = self.backgrounds[self.background.value]
|
background = self.backgrounds[self.background.value]
|
||||||
self.parentApp.character.background = background
|
self.parentApp.character.background = background
|
||||||
log.debug("Selected character background: %s", background)
|
log.debug("Selected character background: %s", background)
|
||||||
self.parentApp.setNextForm('SAVE')
|
self.parentApp.setNextForm('SKILLS')
|
||||||
|
|
||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
self.parentApp.setNextForm('ABILITIES')
|
self.parentApp.setNextForm('ABILITIES')
|
||||||
@@ -260,7 +304,7 @@ class BasicInfoForm(npyscreen.ActionForm):
|
|||||||
self.parentApp.setNextForm('CLASS')
|
self.parentApp.setNextForm('CLASS')
|
||||||
|
|
||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
self.parentApp.setNextForm('SAVE')
|
self.parentApp.setNextForm(None)
|
||||||
|
|
||||||
|
|
||||||
class SaveForm(npyscreen.ActionForm):
|
class SaveForm(npyscreen.ActionForm):
|
||||||
@@ -273,7 +317,7 @@ class SaveForm(npyscreen.ActionForm):
|
|||||||
self.parentApp.setNextForm(None)
|
self.parentApp.setNextForm(None)
|
||||||
|
|
||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
self.parentApp.setNextForm('BACKGROUND')
|
self.parentApp.setNextForm('SKILLS')
|
||||||
|
|
||||||
|
|
||||||
my_app = App()
|
my_app = App()
|
||||||
|
|||||||
@@ -1,2 +1,4 @@
|
|||||||
certifi>=2018.1.18
|
certifi>=2018.1.18
|
||||||
fdfgen>=0.16
|
fdfgen>=0.16
|
||||||
|
npyscreen
|
||||||
|
jinja
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ setup(name='dungeonsheets',
|
|||||||
'dungeonsheets': ['blank-character-sheet-default.pdf', 'blank-spell-sheet-default.pdf']
|
'dungeonsheets': ['blank-character-sheet-default.pdf', 'blank-spell-sheet-default.pdf']
|
||||||
},
|
},
|
||||||
install_requires=[
|
install_requires=[
|
||||||
'fdfgen', 'npyscreen',
|
'fdfgen', 'npyscreen', 'jinja',
|
||||||
],
|
],
|
||||||
entry_points={
|
entry_points={
|
||||||
'console_scripts': [
|
'console_scripts': [
|
||||||
|
|||||||
Reference in New Issue
Block a user