diff options
Diffstat (limited to 'macros/latex/contrib/rpg-module/basic-stats.sty')
-rw-r--r-- | macros/latex/contrib/rpg-module/basic-stats.sty | 399 |
1 files changed, 399 insertions, 0 deletions
diff --git a/macros/latex/contrib/rpg-module/basic-stats.sty b/macros/latex/contrib/rpg-module/basic-stats.sty new file mode 100644 index 0000000000..a2f2fb134d --- /dev/null +++ b/macros/latex/contrib/rpg-module/basic-stats.sty @@ -0,0 +1,399 @@ +%% basic-stats.sty +% +% Basic stat blocks for the Role-Playing Game Module class +% +% Copyright 2016 Michael C. Davis +% +% LICENSE FOR THE WORK +% +% This work consists of the following files: +% rpg-module.cls +% basic-stats.sty +% basic-stats.def +% doc/rpg-module.tex +% +% This work may be distributed and/or modified under the conditions of the LaTeX +% Project Public License, either version 1.3 of this license or (at your option) +% any later version. The latest version of this license can be found at: +% http://www.latex-project.org/lppl.txt +% and version 1.3 or later is part of all distributions of LaTeX version +% 2005/12/01 or later. +% +% This work has the LPPL maintenance status `author-maintained'. +% +% The Author and Maintainer of this work is Michael C. Davis +% +% +% LICENSE FOR COMPILED WORKS +% +% You may distribute compiled works generated using the work as specified in +% Clause 3 of the LaTeX Project Public License. If you incorporate Open Gaming +% Content into the compiled work, you must also comply with the terms of that +% license. +% +% +% USAGE +% +% See the file rpg-module.pdf (source file doc/rpg-module.tex) for documentation. +% There are a number of worked examples in the examples/ directory. +% +% Technical support is provided on Dragonsfoot Forums: +% +% http://www.dragonsfoot.org/forums/viewtopic.php?f=87&t=73823 + +\ProvidesPackage{basic-stats}[2016/04/25 Basic Stat Blocks for the Role-Playing Game Module class] + +\RequirePackage{tabularx} + + + +% Redefine which environment will be displayed +\includecomment{ifbasicstats} + +% Armour class macro +% +% The default for Basic stats is to use the same descending AC that is used in +% the Basic rulebook. However, three alternative styles are defined: ascending +% AC style, B1 style and Swords & Wizardry style. Thanks to Zenopus archives +% for pointing out that the B1 style is an early form of ascending AC, see: +% +% http://zenopusarchives.blogspot.com/2014/02/ascending-ac-in-holmes-basic.html + +\newcounter{acasc@module} % Counter for AC calculations + +\newcommand\ac@module[1]{% + \@ifundefined{acstyle@module}{\gdef\acstyle@module{desc}}{}% % Default AC style is descending + \ifnum\pdfstrcmp{\acstyle@module}{desc}=\z@ % Display descending AC + #1\ignorespaces + \else\ifnum\pdfstrcmp{#1}{---}=\z@ + #1\ignorespaces + \else% + \setcounter{acasc@module}{19}% + \IfSubStr{#1}{\,}{\StrBefore{#1}{\,}[\tmpac]}{\def\tmpac{#1}}% + \IfBeginWith{\tmpac}{\minus}{% + \StrBehind{\tmpac}{\minus}[\tmpac]% + \addtocounter{acasc@module}{\tmpac}% + }{% + \addtocounter{acasc@module}{-\tmpac}% + }% + \ifnum\pdfstrcmp{\acstyle@module}{asc}=\z@ % Display ascending AC + \theacasc@module\ignorespaces + \else\ifnum\pdfstrcmp{\acstyle@module}{b1}=\z@ % Display AC using B1 notation + #1/\theacasc@module\ignorespaces + \else\ifnum\pdfstrcmp{\acstyle@module}{sw}=\z@ % Display AC using Swords & Wizardry notation + #1\,(\theacasc@module)\ignorespaces + \else + Unknown AC style \acstyle@module + \fi\fi\fi + \fi\fi +} + +% Hit Dice : convert short form to long form for stat blocks + +\newcommand\hd@module[1]{\IfBeginWith{#1}{\half}{#1 (1-4 hp)}{#1}} + +% Saving throws : convert long form to short form for stat blocks + +\newcommand\sv@module[1]{\StrLeft{#1}{1}[\first]\StrBehind{#1}{ }[\second]\IfInteger{\second}{}{\StrLeft{\second}{1}[\second]}\first\second} + +% Morale macro : convert long form to short form for stat blocks + +\newcommand\ml@module[1]{\IfSubStr{#1}{ }{\StrBefore{#1}{ }}{#1}} + +% Alignment macro : convert long form to short form for stat blocks + +\newcommand\al@module[1]{% + \ifnum\pdfstrcmp{\pgfkeysvalueof{/#1/AL}}{Any}=\z@ + N % For monsters with variable alignment, assume Neutral unless we specify with changealignment + \else + \StrLeft{\pgfkeysvalueof{/#1/AL}}{1} + \fi +} + +% Change alignment macro, for monsters with Alignment ``Any'' or ``Variable'' + +\newcommand{\changealignment}[2]{\pgfkeys{/#1/AL = {#2}}} + + + +% Basic stat block key-value pairs + +\newcommand{\setstatbasic}[2]{% + \ifcase\thecurrentstat + \pgfkeys{/#1/Type/.initial = {#2}} + \or + \pgfkeys{/#1/SilverMagic/.initial = {#2}} + \or + \pgfkeys{/#1/AC/.initial = \ac@module{#2}} + \or + \pgfkeys{/#1/HD/.initial = {#2}} + \pgfkeys{/#1/HDlong/.initial = \hd@module{#2}} + \or + \pgfkeys{/#1/MVturn/.initial = {#2}} + \or + \pgfkeys{/#1/MVrd/.initial = {#2}} + \or + \pgfkeys{/#1/MVspec/.initial = {#2}} + \or + \pgfkeys{/#1/MVspec_turn/.initial = {#2}} + \or + \pgfkeys{/#1/MVspec_rd/.initial = {#2}} + \or + \pgfkeys{/#1/Attshort/.initial = {#2}} + \or + \pgfkeys{/#1/Attlong/.initial = {#2}} + \or + \pgfkeys{/#1/Dmg/.initial = {#2}} + \or + \pgfkeys{/#1/Dmglong/.initial = {#2}} + \or + \pgfkeys{/#1/SV/.initial = \sv@module{#2}} + \pgfkeys{/#1/SVlong/.initial = {#2}} + \or + \pgfkeys{/#1/ML/.initial = \ml@module{#2}} + \pgfkeys{/#1/MLlong/.initial = {#2}} + \or + \pgfkeys{/#1/AL/.initial = {#2}} + \or + \pgfkeys{/#1/NoAppear/.initial = {#2}} + \or + \pgfkeys{/#1/NoInLair/.initial = {#2}} + \or + \pgfkeys{/#1/TT/.initial = {#2}} + \or + \pgfkeys{/#1/XP/.initial = {#2}} + \fi +} + +% Define monsters using \setstatbasic + +\def\scan@stats#1|{% + \ifnum\pdfstrcmp{#1}{\relax}=\z@ + \let\next\relax + \else + \setstatbasic{\currentmonster}{#1}\let\next\scan@stats + \stepcounter{currentstat} + \fi\next +} + + + +% Display monster stats inline +% +% Usage: \stats[monster name]{monster key}{no. appearing}{hit points} + +\newcommand{\stats}[4][default]{% + \ifnum\pdfstrcmp{#1}{default}=\z@ + \ifnum\pdfstrcmp{#3}{1}=\z@ + \pgfkeys{/#2/SingleName}: % Use the generic name defined for this monster (single instance) + \else + \pgfkeys{/#2/PluralName} (#3): % Use the generic name defined for this monster (plural + number appearing) + \fi + \else + #1 % Override the generic name with the optional argument + \fi + AC~\pgfkeys{/#2/AC}, + HD~\pgfkeys{/#2/HD}, + hp~#4, + MV~\pgfkeys{/#2/MVturn}\thinspacebrk(\pgfkeys{/#2/MVrd}), +\ifnum\pdfstrcmp{\pgfkeysvalueof{/#2/MVspec}}{}=\z@\else + \pgfkeys{/#2/MVspec}~\pgfkeys{/#2/MVspec_turn}\thinspacebrk(\pgfkeys{/#2/MVspec_rd}), +\fi + Att~\pgfkeys{/#2/Attlong}, + D~\pgfkeys{/#2/Dmglong}, + Save~\pgfkeys{/#2/SV}, + ML~\pgfkeys{/#2/ML}, + AL~\al@module{#2}, + XP~\pgfkeys{/#2/XP}% +} + +% Display monster stats in a stat block +% +% Usage: \statblock[monster name]{monster key}{no. appearing}{hit points} + +\newcommand{\statblock}[4][default]{% + \begin{statblockfreestyle} + \stats[#1]{#2}{#3}{#4} + \end{statblockfreestyle} +} + + + +% Table display format for wandering monsters + +\newcounter{wandering@module} + + +\newenvironment{wanderingmonsters}[1][c]{\begin{center}\begin{tabular}{clccccccccc} +\setcounter{wandering@module}{0}% +\tableheader[#1]{Die Roll & Wandering Monster & No. & AC & HD & MV & Attacks & Damage & Save & ML & AL}} +{\end{tabular}\end{center}} + +% Usage: \wanderitem[die roll]{monster key}{no. appearing} +% +% Leave no. appearing blank to use the value from the monster stats + +\newcommand{\wanderitem}[3][default]{% + \ifnum\pdfstrcmp{#1}{default}=\z@ + \stepcounter{wandering@module}\thewandering@module + \else + \IfInteger{#1}{\setcounter{wandering@module}{#1}\thewandering@module}{#1} + \fi & + \IfStrEq{#3}{}{% + \if\pgfkeysvalueof{/#2/NoAppear}\string 1\pgfkeys{/#2/SingleName}\else\pgfkeys{/#2/PluralName}\fi & \pgfkeys{/#2/NoAppear} & + }{% + \ifnum\pdfstrcmp{#3}{1}=\z@\pgfkeys{/#2/SingleName}\else\pgfkeys{/#2/PluralName}\fi & #3 & + } + \pgfkeys{/#2/AC} & \pgfkeys{/#2/HD} & \pgfkeys{/#2/MVrd}% +\ifnum\pdfstrcmp{\pgfkeysvalueof{/#2/MVspec}}{}=\z@\else + /\pgfkeys{/#2/MVspec_rd}% +\fi + & \pgfkeys{/#2/Attshort} & \pgfkeys{/#2/Dmg} & \pgfkeys{/#2/SV} & \pgfkeys{/#2/ML} & \al@module{#2}\\ +} + + + +% Table display format for monster roster + +\newenvironment{monsterroster}[1][c]{\begin{center}\begin{tabular}{clcccccccccc} +\tableheader[#1]{Room & Monster & No. & AC & HD & hp & MV & Attacks & Damage & Save & ML & AL}} +{\end{tabular}\end{center}} + +% Usage: \rosteritem{room key}{monster key}{no. appearing}{hit points} +% +% If the room key is provided as a reference, the class will create a hyperlink from the monster +% roster to the room description + +\newcommand{\rosteritem}[4]{% + #1 & + \ifnum\pdfstrcmp{#3}{1}=\z@ + \pgfkeys{/#2/SingleName} & + \else + \pgfkeys{/#2/PluralName} & + \fi + #3 & \pgfkeys{/#2/AC} & \pgfkeys{/#2/HD} & #4 & \pgfkeys{/#2/MVrd}% +\ifnum\pdfstrcmp{\pgfkeysvalueof{/#2/MVspec}}{}=\z@\else + /\pgfkeys{/#2/MVspec_rd}% +\fi + & \pgfkeys{/#2/Attshort} & \pgfkeys{/#2/Dmg} & \pgfkeys{/#2/SV} & \pgfkeys{/#2/ML} & \al@module{#2}\\ +} + + + +% +% New Monster environment +% + +\newcommand{\newmonsterfont}{\Large\bfseries} +\newcommand{\newmonsterbottomskip}{\topskip} + +\newcommand{\longname}[1]{% + \ifnum\pdfstrcmp{\pgfkeysvalueof{/#1/Type}}{}=\z@ + \pgfkeysvalueof{/#1/SingleName}% + \else\ifnum\pdfstrcmp{\pgfkeysvalueof{/#1/Type}}{\pgfkeysvalueof{/#1/SingleName}}=\z@ + \pgfkeysvalueof{/#1/SingleName}% + \else + \pgfkeysvalueof{/#1/Type}, \texorpdfstring{\protect\StrDel{\pgfkeysvalueof{/#1/SingleName}}{ \pgfkeysvalueof{/#1/Type}}}{}% + \fi\fi +} + +\newenvironment{newmonster}[1]{% +\@afterindentfalse\@afterheading\vspace{\topskip} +\begin{tabularx}{\linewidth}{@{}l>{\raggedright\arraybackslash}Xl>{\raggedright\arraybackslash}X@{}} +\multicolumn{4}{l}{\hspace{-\tabcolsep}\newmonsterfont\longname{#1}\pgfkeys{/#1/SilverMagic}% +\phantomsection\addcontentsline{toc}{section}{\longname{#1}}}\\[\topskip] +\ArmourClass: & \pgfkeys{/#1/AC} & No. Appearing: & \pgfkeys{/#1/NoAppear} (\pgfkeys{/#1/NoInLair})\\ +Hit Dice: & \pgfkeys{/#1/HDlong} & Save As: & \pgfkeys{/#1/SVlong}\\ +Move: & \pgfkeys{/#1/MVturn} (\pgfkeys{/#1/MVrd}) & Morale: & \pgfkeys{/#1/MLlong}\\ +\ifnum\pdfstrcmp{\pgfkeysvalueof{/#1/MVspec}}{}=\z@\else +\hspace{1em}\pgfkeys{/#1/MVspec}: & \pgfkeys{/#1/MVspec_turn} (\pgfkeys{/#1/MVspec_rd})\\ +\fi +Attacks: & \pgfkeys{/#1/Attlong} & Treasure Type: & \pgfkeys{/#1/TT}\\ +Damage: & \pgfkeys{/#1/Dmglong} & Alignment: & \pgfkeys{/#1/AL}\\ +\end{tabularx}\par\vspace{\newmonsterbottomskip}\noindent\ignorespaces}{\vspace{\newmonsterbottomskip}\par\aftergroup\@afterindentfalse\aftergroup\@afterheading} + +% Two-column version + +\newenvironment{newmonster2*}[4]{% +\@afterindentfalse\@afterheading\vspace{\topskip} +\begin{tabularx}{\linewidth}{@{}X>{\raggedright\arraybackslash}>{\raggedright\arraybackslash}X>{\raggedright\arraybackslash}X@{}} +\ifnum\pdfstrcmp{#3}{}=\z@\else +\multicolumn{3}{l}{\hspace{-\tabcolsep}\newmonsterfont#3#4% +\phantomsection\addcontentsline{toc}{section}{#3}}\\[\newmonsterbottomskip] +\fi + & \ifnum\pdfstrcmp{\pgfkeysvalueof{/#1/Type}}{\pgfkeysvalueof{/#1/SingleName}}=\z@ + Normal +\fi\pgfkeys{/#1/SingleName} & \pgfkeys{/#2/SingleName}\\ +\cmidrule(l{\tabcolsep}r{\tabcolsep}){2-2} +\cmidrule(l{\tabcolsep}r{\tabcolsep}){3-3} +\ArmourClass: & \pgfkeys{/#1/AC} & \pgfkeys{/#2/AC}\\ +Hit Dice: & \pgfkeys{/#1/HDlong} & \pgfkeys{/#2/HDlong}\\ +Move: & \pgfkeys{/#1/MVturn} (\pgfkeys{/#1/MVrd}) & \pgfkeys{/#2/MVturn} (\pgfkeys{/#2/MVrd})\\ +\ifnum\pdfstrcmp{\pgfkeysvalueof{/#1/MVspec}}{}=\z@\else +\hspace{1em}\pgfkeys{/#1/MVspec}: & \pgfkeys{/#1/MVspec_turn} (\pgfkeys{/#1/MVspec_rd}) & \pgfkeys{/#2/MVspec_turn} (\pgfkeys{/#2/MVspec_rd})\\ +\fi +Attacks: & \pgfkeys{/#1/Attlong} & \pgfkeys{/#2/Attlong}\\ +Damage: & \pgfkeys{/#1/Dmglong} & \pgfkeys{/#2/Dmglong}\\ +No. Appearing: & \pgfkeys{/#1/NoAppear} (\pgfkeys{/#1/NoInLair}) & \pgfkeys{/#2/NoAppear} (\pgfkeys{/#2/NoInLair})\\ +Save As: & \pgfkeys{/#1/SVlong} & \pgfkeys{/#2/SVlong}\\ +Morale: & \pgfkeys{/#1/MLlong} & \pgfkeys{/#2/MLlong}\\ +Treasure Type: & \pgfkeys{/#1/TT} & \pgfkeys{/#2/TT}\\ +Alignment: & \pgfkeys{/#1/AL} & \pgfkeys{/#2/AL}\\ +\end{tabularx}\par\vspace{\newmonsterbottomskip}\noindent\ignorespaces}{\vspace{\newmonsterbottomskip}\par\aftergroup\@afterindentfalse\aftergroup\@afterheading} + +\newenvironment{newmonster2}[2]{\begin{newmonster2*}{#1}{#2}{\pgfkeysvalueof{/#1/Type}}{\pgfkeysvalueof{/#1/SilverMagic}}}{\end{newmonster2*}} + +% Three-column version + +\newenvironment{newmonster3*}[5]{% +\@afterindentfalse\@afterheading\vspace{\topskip} +\begin{tabularx}{\linewidth}{@{}>{\raggedright\arraybackslash}X>{\raggedright\arraybackslash}X>{\raggedright\arraybackslash}X>{\raggedright\arraybackslash}X@{}} +\ifnum\pdfstrcmp{#4}{}=\z@\else +\multicolumn{4}{l}{\hspace{-\tabcolsep}\newmonsterfont#4#5% +\phantomsection\addcontentsline{toc}{section}{#4}}\\[\newmonsterbottomskip] +\fi + & \ifnum\pdfstrcmp{\pgfkeysvalueof{/#1/Type}}{\pgfkeysvalueof{/#1/SingleName}}=\z@ + Normal +\fi\pgfkeys{/#1/SingleName} & \pgfkeys{/#2/SingleName} & \pgfkeys{/#3/SingleName}\\ +\cmidrule(l{\tabcolsep}r{\tabcolsep}){2-2} +\cmidrule(l{\tabcolsep}r{\tabcolsep}){3-3} +\cmidrule(l{\tabcolsep}r{\tabcolsep}){4-4} +\ArmourClass: & \pgfkeys{/#1/AC} & \pgfkeys{/#2/AC} & \pgfkeys{/#3/AC}\\ +Hit Dice: & \pgfkeys{/#1/HDlong} & \pgfkeys{/#2/HDlong} & \pgfkeys{/#3/HDlong}\\ +Move: & \pgfkeys{/#1/MVturn} (\pgfkeys{/#1/MVrd}) + & \pgfkeys{/#2/MVturn} (\pgfkeys{/#2/MVrd}) + & \pgfkeys{/#3/MVturn} (\pgfkeys{/#3/MVrd})\\ +\ifnum\pdfstrcmp{\pgfkeysvalueof{/#1/MVspec}}{}=\z@\else +\hspace{1em}\pgfkeys{/#1/MVspec}: & \pgfkeys{/#1/MVspec_turn} (\pgfkeys{/#1/MVspec_rd}) + & \pgfkeys{/#2/MVspec_turn} (\pgfkeys{/#2/MVspec_rd}) + & \pgfkeys{/#3/MVspec_turn} (\pgfkeys{/#3/MVspec_rd})\\ +\fi +Attacks: & \pgfkeys{/#1/Attlong} & \pgfkeys{/#2/Attlong} & \pgfkeys{/#3/Attlong}\\ +Damage: & \pgfkeys{/#1/Dmglong} & \pgfkeys{/#2/Dmglong} & \pgfkeys{/#3/Dmglong}\\ +No. Appearing: & \pgfkeys{/#1/NoAppear} (\pgfkeys{/#1/NoInLair}) + & \pgfkeys{/#2/NoAppear} (\pgfkeys{/#2/NoInLair}) + & \pgfkeys{/#3/NoAppear} (\pgfkeys{/#3/NoInLair})\\ +Save As: & \pgfkeys{/#1/SVlong} & \pgfkeys{/#2/SVlong} & \pgfkeys{/#3/SVlong}\\ +Morale: & \pgfkeys{/#1/MLlong} & \pgfkeys{/#2/MLlong} & \pgfkeys{/#3/MLlong}\\ +Treasure Type: & \pgfkeys{/#1/TT} & \pgfkeys{/#2/TT} & \pgfkeys{/#3/TT}\\ +Alignment: & \pgfkeys{/#1/AL} & \pgfkeys{/#2/AL} & \pgfkeys{/#3/AL}\\ +\end{tabularx}\par\vspace{\newmonsterbottomskip}\noindent\ignorespaces}{\vspace{\newmonsterbottomskip}\par\aftergroup\@afterindentfalse\aftergroup\@afterheading} + +\newenvironment{newmonster3}[3]{\begin{newmonster3*}{#1}{#2}{#3}{\pgfkeysvalueof{/#1/Type}}{\pgfkeysvalueof{/#1/SilverMagic}}}{\end{newmonster3*}} + + + +% A few special macros for stat blocks + +\newcommand\x{$\times$} % Text-mode multiplication symbol +\newcommand\minus{$-$} % Text-mode minus sign +\newcommand{\?}{\discretionary{/}{}{/}} % Breaking slash +\newcommand{\+}{\discretionary{\,+}{}{\,+\,}} % Breaking + with 1/6 em space either side + + + +% +% Load pre-defined monster stats +% + +\input{basic-stats.def} |