mirror of
https://github.com/Threnklyn/dungeon-sheets.git
synced 2026-06-06 21:01:26 +02:00
Added party stats for the GM notes sheet.
This commit is contained in:
+6
-1
@@ -25,7 +25,7 @@ interpreted as a character sheet.
|
|||||||
Basic Info
|
Basic Info
|
||||||
==========
|
==========
|
||||||
|
|
||||||
Currently, only two attributes are supported: ``monsters`` and
|
Currently, these attributes are supported: ``monsters`` and
|
||||||
``session_title``. More attributes will be added in the future, but if
|
``session_title``. More attributes will be added in the future, but if
|
||||||
there's something specific you have a need for, please consider
|
there's something specific you have a need for, please consider
|
||||||
`contributing`_ an issue or pull-request.
|
`contributing`_ an issue or pull-request.
|
||||||
@@ -34,9 +34,14 @@ there's something specific you have a need for, please consider
|
|||||||
|
|
||||||
session_title = "Objects in Space"
|
session_title = "Objects in Space"
|
||||||
monsters = ["ogre", "giant eagle"]
|
monsters = ["ogre", "giant eagle"]
|
||||||
|
party = ["rogue1.py", "paladin2.py"]
|
||||||
|
|
||||||
``monsters`` should be a list of either strings or subclasses of
|
``monsters`` should be a list of either strings or subclasses of
|
||||||
:py:class:`Monster`. These entries will then by listed on the
|
:py:class:`Monster`. These entries will then by listed on the
|
||||||
resulting PDF with their stat block and features.
|
resulting PDF with their stat block and features.
|
||||||
|
|
||||||
|
``party`` contains a list of filenames for the characters in the
|
||||||
|
party. These will produce a summary table of the attributes of your
|
||||||
|
party.
|
||||||
|
|
||||||
.. _contributing: https://github.com/canismarko/dungeon-sheets/blob/master/CONTRIBUTING.rst
|
.. _contributing: https://github.com/canismarko/dungeon-sheets/blob/master/CONTRIBUTING.rst
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
\section*{Party}
|
||||||
|
|
||||||
|
[% if use_dnd_decorations %]
|
||||||
|
\begin{DndTable}[header=Nice Table]{l c c c c c c c c}
|
||||||
|
& AC & Str & Dex & Con & Int & Wis & Cha \\
|
||||||
|
[% for member in party %]
|
||||||
|
[[ member.name[:14] ]]
|
||||||
|
& [[ member.armor_class ]]
|
||||||
|
& [[ member.strength.modifier | mod_str ]]
|
||||||
|
& [[ member.dexterity.modifier | mod_str ]]
|
||||||
|
& [[ member.constitution.modifier | mod_str ]]
|
||||||
|
& [[ member.intelligence.modifier | mod_str ]]
|
||||||
|
& [[ member.wisdom.modifier | mod_str ]]
|
||||||
|
& [[ member.charisma.modifier | mod_str ]]
|
||||||
|
\\
|
||||||
|
[% endfor %]
|
||||||
|
\end{DndTable}
|
||||||
|
[% else %]
|
||||||
|
\begin{tabular}{l | c c c c c c c}
|
||||||
|
& AC & Str & Dex & Con & Int & Wis & Cha \\
|
||||||
|
\hline\hline
|
||||||
|
[% for member in party %]
|
||||||
|
[[ member.name[:10] ]]
|
||||||
|
& [[ member.armor_class ]]
|
||||||
|
& [[ member.strength.modifier | mod_str ]]
|
||||||
|
& [[ member.dexterity.modifier | mod_str ]]
|
||||||
|
& [[ member.constitution.modifier | mod_str ]]
|
||||||
|
& [[ member.intelligence.modifier | mod_str ]]
|
||||||
|
& [[ member.wisdom.modifier | mod_str ]]
|
||||||
|
& [[ member.charisma.modifier | mod_str ]]
|
||||||
|
\\
|
||||||
|
[% endfor %]
|
||||||
|
\end{tabular}
|
||||||
|
[% endif %]
|
||||||
@@ -9,7 +9,7 @@ import re
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from multiprocessing import Pool, cpu_count
|
from multiprocessing import Pool, cpu_count
|
||||||
from itertools import product
|
from itertools import product
|
||||||
from typing import Union, Mapping, Sequence
|
from typing import Union, Mapping, Sequence, Optional
|
||||||
|
|
||||||
from jinja2 import Environment, PackageLoader
|
from jinja2 import Environment, PackageLoader
|
||||||
|
|
||||||
@@ -20,6 +20,7 @@ from dungeonsheets.fill_pdf_template import (
|
|||||||
create_spells_pdf_template,
|
create_spells_pdf_template,
|
||||||
)
|
)
|
||||||
from dungeonsheets.character import Character
|
from dungeonsheets.character import Character
|
||||||
|
from dungeonsheets.entity import Entity
|
||||||
|
|
||||||
"""Program to take character definitions and build a PDF of the
|
"""Program to take character definitions and build a PDF of the
|
||||||
character sheet."""
|
character sheet."""
|
||||||
@@ -89,6 +90,14 @@ def create_monsters_tex(
|
|||||||
return template.render(monsters=monsters, use_dnd_decorations=use_dnd_decorations)
|
return template.render(monsters=monsters, use_dnd_decorations=use_dnd_decorations)
|
||||||
|
|
||||||
|
|
||||||
|
def create_party_summary_tex(
|
||||||
|
party: Sequence[Entity],
|
||||||
|
use_dnd_decorations: bool = False,
|
||||||
|
) -> str:
|
||||||
|
template = jinja_env.get_template("party_summary_template.tex")
|
||||||
|
return template.render(party=party, use_dnd_decorations=use_dnd_decorations)
|
||||||
|
|
||||||
|
|
||||||
def create_spellbook_tex(
|
def create_spellbook_tex(
|
||||||
character: Character,
|
character: Character,
|
||||||
use_dnd_decorations: bool = False,
|
use_dnd_decorations: bool = False,
|
||||||
@@ -138,20 +147,17 @@ def make_sheet(
|
|||||||
"""
|
"""
|
||||||
# Parse the file
|
# Parse the file
|
||||||
sheet_file = Path(sheet_file)
|
sheet_file = Path(sheet_file)
|
||||||
base_name = sheet_file.stem
|
|
||||||
sheet_props = readers.read_sheet_file(sheet_file)
|
sheet_props = readers.read_sheet_file(sheet_file)
|
||||||
# Create the sheet
|
# Create the sheet
|
||||||
if sheet_props.get("sheet_type", "") == "gm":
|
if sheet_props.get("sheet_type", "") == "gm":
|
||||||
ret = make_gm_sheet(
|
ret = make_gm_sheet(
|
||||||
basename=base_name,
|
gm_file=sheet_file,
|
||||||
gm_props=sheet_props,
|
|
||||||
fancy_decorations=fancy_decorations,
|
fancy_decorations=fancy_decorations,
|
||||||
debug=debug,
|
debug=debug,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
ret = make_character_sheet(
|
ret = make_character_sheet(
|
||||||
basename=base_name,
|
char_file=sheet_file,
|
||||||
character_props=sheet_props,
|
|
||||||
flatten=flatten,
|
flatten=flatten,
|
||||||
fancy_decorations=fancy_decorations,
|
fancy_decorations=fancy_decorations,
|
||||||
debug=debug,
|
debug=debug,
|
||||||
@@ -160,8 +166,7 @@ def make_sheet(
|
|||||||
|
|
||||||
|
|
||||||
def make_gm_sheet(
|
def make_gm_sheet(
|
||||||
basename: str,
|
gm_file: Union[str, Path],
|
||||||
gm_props: Mapping,
|
|
||||||
fancy_decorations: bool = False,
|
fancy_decorations: bool = False,
|
||||||
debug: bool = False,
|
debug: bool = False,
|
||||||
):
|
):
|
||||||
@@ -169,10 +174,8 @@ def make_gm_sheet(
|
|||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
basename
|
gm_file
|
||||||
The basename for saving files.
|
The file with the gm_sheet definitions.
|
||||||
gm_props
|
|
||||||
Properties for creating the GM notes.
|
|
||||||
fancy_decorations
|
fancy_decorations
|
||||||
Use fancy page layout and decorations for extra sheets, namely
|
Use fancy page layout and decorations for extra sheets, namely
|
||||||
the dnd style file: https://github.com/rpgtex/DND-5e-LaTeX-Template.
|
the dnd style file: https://github.com/rpgtex/DND-5e-LaTeX-Template.
|
||||||
@@ -180,12 +183,33 @@ def make_gm_sheet(
|
|||||||
Provide extra info and preserve temporary files.
|
Provide extra info and preserve temporary files.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
# Parse the GM file and filename
|
||||||
|
gm_file = Path(gm_file)
|
||||||
|
basename = gm_file.stem
|
||||||
|
gm_props = readers.read_sheet_file(gm_file)
|
||||||
|
# Create the intro tex
|
||||||
tex = [
|
tex = [
|
||||||
jinja_env.get_template("preamble.tex").render(
|
jinja_env.get_template("preamble.tex").render(
|
||||||
use_dnd_decorations=fancy_decorations,
|
use_dnd_decorations=fancy_decorations,
|
||||||
title=gm_props["session_title"],
|
title=gm_props["session_title"],
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
# Add the party stats table
|
||||||
|
party = []
|
||||||
|
for char_file in gm_props.get("party", []):
|
||||||
|
# Resolve the file path
|
||||||
|
char_file = Path(char_file)
|
||||||
|
if not char_file.is_absolute():
|
||||||
|
char_file = gm_file.parent / char_file
|
||||||
|
char_file = char_file.resolve()
|
||||||
|
# Load the character file
|
||||||
|
character_props = readers.read_sheet_file(char_file)
|
||||||
|
member = _char.Character.load(character_props)
|
||||||
|
party.append(member)
|
||||||
|
if len(party) > 0:
|
||||||
|
tex.append(
|
||||||
|
create_party_summary_tex(party, use_dnd_decorations=fancy_decorations)
|
||||||
|
)
|
||||||
# Add the monsters
|
# Add the monsters
|
||||||
monsters_ = [findattr(monsters, m)() for m in gm_props.get("monsters", [])]
|
monsters_ = [findattr(monsters, m)() for m in gm_props.get("monsters", [])]
|
||||||
if len(monsters_) > 0:
|
if len(monsters_) > 0:
|
||||||
@@ -212,9 +236,8 @@ def make_gm_sheet(
|
|||||||
|
|
||||||
|
|
||||||
def make_character_sheet(
|
def make_character_sheet(
|
||||||
basename: str,
|
char_file: Union[str, Path],
|
||||||
character_props: Mapping,
|
character: Optional[Character] = None,
|
||||||
character: Character = None,
|
|
||||||
flatten: bool = False,
|
flatten: bool = False,
|
||||||
fancy_decorations: bool = False,
|
fancy_decorations: bool = False,
|
||||||
debug: bool = False,
|
debug: bool = False,
|
||||||
@@ -225,8 +248,6 @@ def make_character_sheet(
|
|||||||
----------
|
----------
|
||||||
basename
|
basename
|
||||||
The basename for saving files (PDFs, etc).
|
The basename for saving files (PDFs, etc).
|
||||||
character_props
|
|
||||||
Properties to load character from.
|
|
||||||
character
|
character
|
||||||
If provided, will not load from the character file, just use
|
If provided, will not load from the character file, just use
|
||||||
file for PDF name
|
file for PDF name
|
||||||
@@ -240,10 +261,12 @@ def make_character_sheet(
|
|||||||
Provide extra info and preserve temporary files.
|
Provide extra info and preserve temporary files.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
# Load properties from file
|
||||||
if character is None:
|
if character is None:
|
||||||
|
character_props = readers.read_sheet_file(char_file)
|
||||||
character = _char.Character.load(character_props)
|
character = _char.Character.load(character_props)
|
||||||
|
|
||||||
# Set the fields in the FDF
|
# Set the fields in the FDF
|
||||||
|
basename = char_file.stem
|
||||||
char_base = basename + "_char"
|
char_base = basename + "_char"
|
||||||
sheets = [char_base + ".pdf"]
|
sheets = [char_base + ".pdf"]
|
||||||
pages = []
|
pages = []
|
||||||
|
|||||||
@@ -11,4 +11,6 @@ sheet_type = "gm"
|
|||||||
|
|
||||||
session_title = "Objects in Space"
|
session_title = "Objects in Space"
|
||||||
|
|
||||||
|
party = ["rogue1.py", "paladin2.py"]
|
||||||
|
|
||||||
monsters = ["wolf", "giant eagle"]
|
monsters = ["wolf", "giant eagle"]
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ class TexCreatorTestCase(unittest.TestCase):
|
|||||||
|
|
||||||
def new_character(self):
|
def new_character(self):
|
||||||
char = character.Character(
|
char = character.Character(
|
||||||
|
name="Dr. Who",
|
||||||
classes=["Monk", "Druid", "Artificer"],
|
classes=["Monk", "Druid", "Artificer"],
|
||||||
levels=[1, 1, 1],
|
levels=[1, 1, 1],
|
||||||
subclasses=["way of the open hand", None, None],
|
subclasses=["way of the open hand", None, None],
|
||||||
@@ -128,3 +129,10 @@ class TexCreatorTestCase(unittest.TestCase):
|
|||||||
monsters_ = [monsters.GiantEagle()]
|
monsters_ = [monsters.GiantEagle()]
|
||||||
tex = make_sheets.create_monsters_tex(monsters=monsters_)
|
tex = make_sheets.create_monsters_tex(monsters=monsters_)
|
||||||
self.assertIn(r"Giant Eagle", tex)
|
self.assertIn(r"Giant Eagle", tex)
|
||||||
|
|
||||||
|
def test_create_party_summary_tex(self):
|
||||||
|
char = self.new_character()
|
||||||
|
tex = make_sheets.create_party_summary_tex(party=[char])
|
||||||
|
self.assertIn(r"\section*{Party}", tex)
|
||||||
|
self.assertIn(char.name, tex)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user