\RequirePackage {keycommand} \ExplSyntaxOn \NewDocumentCommand{\RpgDeprecate}{ mmm } { \__rpg_deprecated:nnn {#1} {#2} {#3} } \ExplSyntaxOff % Either hilariously, or infuriatingly, the \ifcommandkey % implementation is buggy. Here is a re-implementation % from tex.stackexchange. \begingroup \makeatletter \catcode`\/=8 % \@firstofone { \endgroup \renewcommand{\ifcommandkey}[1]{% \csname @\expandafter \expandafter \expandafter \expandafter \expandafter \expandafter \expandafter \kcmd@nbk \commandkey {#1}//{first}{second}//oftwo\endcsname } } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % rpgcolors.sty - to be removed in version 1.0.0 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Sets the themecolor and colors for all themed elements % If called without the optional color, resets the color of all themed elements to the current themecolor \newcommand{\setthemecolor}[1][themecolor]{% \RpgDeprecate{\noexpand\setthemecolor}{1.0.0}{Use \noexpand\RpgSetThemeColor to set the theme color.}% \colorlet{themecolor}{#1} \colorlet{commentcolor}{#1} \colorlet{sidebarcolor}{#1} \colorlet{tablecolor}{#1} } % Backwards-compatible aliases and colours \colorlet {commentgreen} {PhbLightGreen} \colorlet {itemtablepink} {DmgCoral} \colorlet {monstertan} {statblockbg} \definecolor {monstertandark} {HTML} {F0DBB5} % Old interface \colorlet {commentboxcolor} {commentcolor} \colorlet {paperboxcolor} {sidebarcolor} \colorlet {quoteboxcolor} {readaloudcolor} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % rpgcomment.sty - to be removed in version 1.0.0 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %Usage \begin{commentbox}[options]{title}[color] \ExplSyntaxOn \DeclareTColorBox{commentbox}{O{} m O{commentboxcolor}}{% before~upper={% \bool_if:NT \l__rpg_layout_bool { \bool_if:NF \l__rpg_justified_bool { \RaggedRight } } }, code={\RpgDeprecate{\noexpand\commentbox}{1.0.0}{Use~\noexpand\RpgComment~for~breakable~comment~boxes.}\linespread{.9}}, frame~hidden, boxrule=0pt, breakable, enhanced, before~skip=13pt plus 4pt minus 4pt, toptitle=2pt, boxsep=3pt, left=6pt, right=6pt, top=0pt, bottom=2pt, sharp~corners, fonttitle=\RpgFontCommentTitle, fontupper=\RpgFontCommentBody, fontlower=\RpgFontCommentBody, title={#2}, parbox=false, colback=#3, colbacktitle=#3, coltitle=black, after~skip=13pt plus 4pt minus 4pt, #1 } \ExplSyntaxOff %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % rpgmonster.sty - to be removed in version 1.0.0 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Fancy DnD 5e stat block rule \newcommand{\rpgline}{% \RpgDeprecate{\noexpand\rpgline}{1.0.0}{Use \noexpand\RpgMonsterLine for stat block rules.}% \noindent \begin{tikzpicture}[] \draw [rulered, fill=rulered] (0, 0) --(0,0.1) -- (\textwidth, 0.05); \end{tikzpicture}% \par% } \RequirePackage{fp} \RequirePackage{xstring} % Macro to print stats with auto-computed modifier % e.g. \stat{12} prints "12 (+1)" \newcommand{\stat}[1]{% \RpgDeprecate{\noexpand\stat}{1.0.0}{Use \noexpand\RpgMonsterAbilityScores for the stat block ability score table.}% \FPeval{\mod}{(#1 - 10)/2}% \FPifpos\mod% \FPeval{\mod}{clip(trunc(mod,0))}#1\ (+\mod)% \else% \FPeval{\mod}{clip(abs(trunc(mod-0.5,0)))}#1\ (--\mod)% \fi% } % Macro to print avarage dice based value % e.g. \dice{2d6+3} prints "10 (2d6 + 3)" \newcommand{\dice}[1]{% \RpgDeprecate{\noexpand\dice}{1.0.0}{Use \noexpand\RpgDice to typeset a dice roll with the average value.}% \StrSubstitute{#1}{ }{}[\DiceArg]% strip whitespaces \StrCut{\DiceArg}{d}\DiceNum\DiceSides% split string \StrCut{\DiceSides}{+}\DiceSides\DiceAddMod% \StrCut{\DiceSides}{-}\DiceSides\DiceSubMod% \FPeval{\DiceAvg}{(\DiceSides+1)/2*\DiceNum}% calculate avg roll \IfInteger{\DiceAddMod}{% \FPadd{\DiceAvg}{\DiceAvg}{\DiceAddMod}% add value \def\DiceMod{ + \DiceAddMod}% }{% \IfInteger{\DiceSubMod}{% \FPsub{\DiceAvg}{\DiceAvg}{\DiceSubMod}% subtract value \def\DiceMod{ -- \DiceSubMod}% }{% \def\DiceMod{}% }% }% \FPtrunc{\DiceAvg}{\DiceAvg}{0}% round down \FPprint{\DiceAvg\ (\DiceNum \dname\DiceSides\DiceMod)}% } % Stat block without the background \newtcolorbox{monsterboxnobg}[2][]{ enhanced, code={\RpgDeprecate{\noexpand\monsterboxnobg}{1.0.0}{Use \noexpand\RpgMonsterNoBg for stat blocks without a background.}}, frame hidden, boxrule=0pt, breakable, parbox=false, boxsep=0pt, toptitle=3mm, left=0pt, right=0pt, sharp corners, opacityback=0, colframe=titlered, fonttitle=\RpgFontStatBlockTitle, fontupper=\RpgFontStatBlockBody, fontlower=\RpgFontStatBlockBody, title=#2, coltitle=titlered, #1 } % Stat block with background \newtcolorbox{monsterboxbg}[2][]{ enhanced, code={\RpgDeprecate{\noexpand\monsterboxbg}{1.0.0}{Use \noexpand\RpgMonsterBg for stat blocks with a background.}}, frame hidden, before skip=12pt plus 3pt minus 3pt, boxrule=0pt, breakable, parbox=false, boxsep=2pt, toptitle=8pt, top=0pt, left=2pt, right=2pt, bottom=7pt, sharp corners, oversize=0pt, borderline north={3pt}{0pt}{titlered}, borderline north={2pt}{0.5pt}{statblockribbon}, borderline south={3pt}{0pt}{titlered}, borderline south={2pt}{0.5pt}{statblockribbon}, colback=statblockbg, colbacktitle=statblockbg, colframe=titlered, fonttitle=\RpgFontStatBlockTitle, coltitle=titlered, fontupper=\RpgFontStatBlockBody, fontlower=\RpgFontStatBlockBody, title=#2, #1 } \ExplSyntaxOn \bool_if:NTF \l__rpg_show_background_bool { \let\monsterbox\monsterboxbg% \let\endmonsterbox\endmonsterboxbg% } { \let\monsterbox\monsterboxnobg% \let\endmonsterbox\endmonsterboxnobg% } \ExplSyntaxOff % Define Monster subsection header style \newcommand{\monstersection}[1]{% \RpgDeprecate{\noexpand\monstersection}{1.0.0}{Use \noexpand\RpgMonsterSection for stat blocks sections.}% \begingroup \par\medskip\noindent \RpgFontStatBlockSection #1 % \rule is a horizontal command, so placing it under the title incurs extra % line spacing. Use \hrule (a vertical command) instead. \vspace{3pt} \hrule height 0.6pt \vspace{2pt} \endgroup% } \NewDocumentEnvironment{monsteraction}{o}{% \RpgDeprecate{\noexpand\monsteraction}{1.0.0}{Use \noexpand\RpgMonsterAction for stat block actions.}% \IfValueTF{#1}{% \par\medskip\noindent\emph{\textbf{#1.}}% }{\unskip}% }{\par} % A description variant used to list creature attributes. \newlist{rpg@monsterattrs}{description}{1} \ExplSyntaxOn \setlist[rpg@monsterattrs]{ before=\color{titlered}, font=\RpgFontStatBlockBody, labelsep=\l__rpg_space_dim, noitemsep, nosep, } \ExplSyntaxOff % A rpg@monsterattrs helper macro that always displays an attribute. \newcommand{\rpg@monsterattr}[2]{% \item[#2] \commandkey{#1} } % A rpg@monsterattrs helper macro that displays an attribute if the user defined % it. \newcommand{\rpg@ifmonsterattr}[2]{% \ifcommandkey{#1}{% \item[#2] \commandkey{#1} }{}% } % % Macros for use within the monster environment % \newkeycommand\basics[armorclass=0, hitpoints=0, speed=0]{% \RpgDeprecate{\noexpand\basics}{1.0.0}{Use \noexpand\RpgMonsterBasics for stat block AC, HP, and speed.}% \begin{rpg@monsterattrs} \rpg@monsterattr{armorclass}{\armorclassname} \rpg@monsterattr{hitpoints}{\hitpointsname} \rpg@monsterattr{speed}{\speedname} \end{rpg@monsterattrs}% } % Taubular enviornment for stats-block \newkeycommand\stats[% STR=\stat{10}, DEX=\stat{10}, CON=\stat{10}, INT=\stat{10}, WIS=\stat{10}, CHA=\stat{10}]{% \RpgDeprecate{\noexpand\stats}{1.0.0}{Use \noexpand\RpgMonsterAbilityScores for the stat block ability score table.}% \begingroup% \color{titlered}% \par\vspace{5pt}\noindent% \begin{tabularx}{\linewidth}{YYYYYY} \textbf{\strstatname} & \textbf{\dexstatname} & \textbf{\constatname} & \textbf{\intstatname} & \textbf{\wisstatname} & \textbf{\chastatname} \\ \commandkey{STR} & \commandkey{DEX} & \commandkey{CON} & \commandkey{INT} & \commandkey{WIS} & \commandkey{CHA} \end{tabularx}% \par\vspace{4pt}% \endgroup% } \newkeycommand\details[ skills=, damageimmunities=, savingthrows=, conditionimmunities=, damageresistances=, damagevulnerabilities=, senses=---, languages=---, challenge=1, ]{% \RpgDeprecate{\noexpand\details}{1.0.0}{Use \noexpand\RpgMonsterDetails for stat block details like resistances and CR.}% \begin{rpg@monsterattrs} \rpg@ifmonsterattr{savingthrows}{\savesname} \rpg@ifmonsterattr{skills}{\skillsname} \rpg@ifmonsterattr{damagevulnerabilities}{\dvulname} \rpg@ifmonsterattr{damageresistances}{\dresname} \rpg@ifmonsterattr{damageimmunities}{\dimmname} \rpg@ifmonsterattr{conditionimmunities}{\cimmname} \rpg@monsterattr{senses}{\sensesname} \rpg@monsterattr{languages}{\languagesname} \item[\challengename] \RpgCRExp{\commandkey{challenge}} \end{rpg@monsterattrs}% } \ExplSyntaxOn \newcommand{\rpg@hit}[1]{% \__rpg_caption:nn {\tohitname} {#1} } \ExplSyntaxOff \newcommand{\rpg@damage}[2]{% \commandkey{#1}\ \commandkey{#2}\ \damagename% } \newcommand{\rpg@ifplusdmg}[2]{% \ifcommandkey{#1}{% { }\plusname\ \commandkey{#1}\ \commandkey{#2}\ \damagename% }{}% } \newcommand{\rpg@ifordmg}[5]{% \ifcommandkey{#1}{% , \orname\ \commandkey{#1}\ \commandkey{#2}\ \damagename\rpg@ifplusdmg{#4}{#5}\ \commandkey{#3}% }{}% } \newkeycommand+[\|]\monstermelee[ name=Club, mod=+0, reach=5, targets=\defaulttargetsname, dmg=\dice{1d4}, dmgtype=bludgeoning, plusdmg=, plusdmgtype=, ordmg=, ordmgwhen=, extra=, ]{% |\monsterattack|[ name={\commandkey{name}}, type=melee, mod={\commandkey{mod}}, reach={\commandkey{reach}}, targets={\commandkey{targets}}, dmg={\commandkey{dmg}}, dmgtype={\commandkey{dmgtype}}, plusdmg={\commandkey{plusdmg}}, plusdmgtype={\commandkey{plusdmgtype}}, ordmg={\commandkey{ordmg}}, ordmgwhen={\commandkey{ordmgwhen}}, extra={\commandkey{extra}}, ] } \newkeycommand+[\|]\monsterranged[ name=Shortbow, mod=+0, range=80/320, targets=\defaulttargetsname, dmg=\dice{1d6}, dmgtype=piercing, plusdmg=, plusdmgtype=, ordmg=, ordmgwhen=, extra=, ]{% |\monsterattack|[ name={\commandkey{name}}, type=ranged, mod={\commandkey{mod}}, range={\commandkey{range}}, targets={\commandkey{targets}}, dmg={\commandkey{dmg}}, dmgtype={\commandkey{dmgtype}}, plusdmg={\commandkey{plusdmg}}, plusdmgtype={\commandkey{plusdmgtype}}, ordmg={\commandkey{ordmg}}, ordmgwhen={\commandkey{ordmgwhen}}, extra={\commandkey{extra}}, ] } \newkeycommand\monsterattack[ name=Dagger, enum* type={both,melee,ranged}, mod=+0, reach=5, range=20/60, targets=\defaulttargetsname, dmg=\dice{1d4}, dmgtype=piercing, plusdmg=, plusdmgtype=, ordmg=, ordmgwhen=, extra=, ]{% \RpgDeprecate{\noexpand\monsterattack}{1.0.0}{Use \noexpand\RpgMonsterMelee, \noexpand\RpgMonsterRanged, or \noexpand\RpgMonsterAttack for attacks that are melee, ranged, or both, respectively.}% \begin{monsteraction}[\commandkey{name}] \IfStrEqCase{\commandkey{type}}{% {melee}{\textit{\RpgCaption{\meleeattackname}{\weaponname}:} \rpg@hit{mod}, \reachname\ \commandkey{reach} \unitsname}% {ranged}{\textit{\RpgCaption{\rangedattackname}{\weaponname}:} \rpg@hit{mod}, \rangename\ \commandkey{range} \unitsname}% {both}{\textit{\RpgCaption{\meleeorrangedattackname}{\weaponname}:} \rpg@hit{mod}, \reachname\ \commandkey{reach} \unitsname\ \orname\ \rangename\ \commandkey{range} \unitsname}% }[]% , \commandkey{targets}. \textit{\hitname:} \rpg@damage{dmg}{dmgtype}% \rpg@ifplusdmg{plusdmg}{plusdmgtype}% \rpg@ifordmg{ordmg}{dmgtype}{ordmgwhen}{plusdmg}{plusdmgtype}% \ifcommandkey{extra}{\commandkey{extra}}{}. \end{monsteraction} } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % rpgpaperbox.sty - to be removed in version 1.0.0 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %Usage \begin{paperbox}[options]{title}[color] \ExplSyntaxOn \DeclareTColorBox{paperbox}{O{} m O{paperboxcolor}}{% before~upper={% \bool_if:NT \l__rpg_layout_bool { \bool_if:NF \l__rpg_justified_bool {\RaggedRight} } }, code={\RpgDeprecate{\noexpand\paperbox}{1.0.0}{Use \noexpand\RpgSidebar for sidebars.}\linespread{.9}}, frame~hidden, boxrule=0pt, enhanced, before~skip=13pt plus 4pt minus 4pt, toptitle=2pt, boxsep=3pt, left=6pt, right=6pt, top=0pt, bottom=3pt, fonttitle=\RpgFontSidebarTitle, fontupper=\RpgFontSidebarBody, fontlower=\RpgFontSidebarBody, title={#2}, sharp~corners, parbox=false, borderline~north={1pt}{-0.5pt}{black}, borderline~south={1pt}{-0.5pt}{black}, colback=#3, colbacktitle=#3, coltitle=black, fuzzy~shadow={0mm}{-3.5pt}{-0.5pt}{0.4mm}{black!60!white}, overlay={% \fill[black] (frame.south~west) -- ++ (7pt,0) -- ++ (0,-5pt) -- cycle; \fill[black] (frame.north~west) -- ++ (7pt,0) -- ++ (0,5pt) -- cycle; \fill[black] (frame.north~east) -- ++ (-7pt,0) -- ++ (0,5pt) -- cycle; \fill[black] (frame.south~east) -- ++ (-7pt,0) -- ++ (0,-5pt) -- cycle; }, after~skip=14pt plus 4pt minus 4pt, #1 } \ExplSyntaxOn %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % rpgquote.sty - to be removed in version 1.0.0 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %Usage \begin{quotebox}[options][color] \ExplSyntaxOn \DeclareTColorBox{quotebox}{O{} O{quoteboxcolor}}{% before~upper={% \bool_if:NT \l__rpg_layout_bool { \bool_if:NF \l__rpg_justified_bool {\RaggedRight} } }, code={\RpgDeprecate{\noexpand\quotebox}{1.0.0}{Use~\noexpand\RpgReadAloud~for~read-aloud~text.}\linespread{1.1}}, enhanced~jigsaw, frame~hidden, boxrule=0pt, breakable, enhanced, before~skip=13pt plus 4pt minus 4pt, boxsep=8pt, top=0pt, left=0pt, right=0pt, bottom=0pt, colback=#2, sharp~corners, parbox=false, borderline~west={1pt}{-0.5pt}{titlered}, borderline~east={1pt}{-0.5pt}{titlered}, fontupper=\RpgFontReadAloud, fontlower=\RpgFontReadAloud, overlay={% \foreach\n in {north~east,north~west,south~east,south~west} {\draw[titlered, fill=titlered] (frame.\n) circle (1.5pt); }; }, after~skip=13pt plus 4pt minus 4pt, #1 } \ExplSyntaxOff %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % rpgsections.sty - to be removed in version 1.0.0 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Special command for magic items, traps, and the like. \newcommand{\subtitlesection}[2]{% \RpgDeprecate{\noexpand\subtitlesection}{1.0.0}{Use \noexpand\RpgItemHeader for item headers.}% \subsubsection{#1}% \textit{#2} \par\vspace{3pt plus 1pt minus 1pt}\noindent\ignorespaces} % Map Areas and their References % Labelling helpers \newcommand{\AreaLabel@Prefix}{area} \newcommand{\SetAreaLabelPrefix}[1]{% \renewcommand{\AreaLabel@Prefix}{#1}} \newcounter{Area} \newcommand\ResetAreas{% \RpgDeprecate{\noexpand\ResetAreas}{1.0.0}{Use \noexpand\RpgResetAreas to reset area counters.}% \setcounter{Area}{0} } \NewDocumentCommand\area{mo}{% \RpgDeprecate{\noexpand\area}{1.0.0}{Use \noexpand\RpgArea to typeset a section with an area counter.}% \refstepcounter{Area}% \IfNoValueTF{#2}% {\label{\AreaLabel@Prefix:#1}}% {\label{\AreaLabel@Prefix:#2}}% \subsection{\arabic{Area}. #1}% } % defines sub-areas, like '5a', '5b' \newcounter{SubArea}[Area] \NewDocumentCommand\subarea{mo}{% \RpgDeprecate{\noexpand\subarea}{1.0.0}{Use \noexpand\RpgSubArea to typeset a section with an sub-area counter.}% \refstepcounter{SubArea}% \IfNoValueTF{#2}% {\label{\AreaLabel@Prefix:#1}}% {\label{\AreaLabel@Prefix:#2}}% \subsubsection{\arabic{Area}\alph{SubArea}. #1}% } % sub area references should be '5a', '5b', not '1', '2' \renewcommand\p@SubArea{\arabic{Area}} \renewcommand\theSubArea{\alph{SubArea}} \newcounter{DetailArea}[subsection] \newcommand{\DetailArea@Prefix}{} \newcommand{\SetDetailAreaPrefix}[1]{\renewcommand{\DetailArea@Prefix} {#1--\arabic{DetailArea}\par\expandafter\ignorespaces\noindent}} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % rpgspell.sty - to be removed in version 1.0.0 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \newcommand{\spellheader}[6]{% \RpgDeprecate{\noexpand\spellheader}{1.0.0}{Use \noexpand\RpgSpellHeader to typeset a spell header.}% \subtitlesection{#1}{#2} \begin{description}[noitemsep,nosep,after=\smallskip,leftmargin=1em] \item[\spellcastingtimename:] #3 \item[\spellrangename:] #4 \item[\spellcomponentsname:] #5 \item[\spelldurationname:] #6 \end{description} } \newenvironment{spell}[6] {\spellheader{#1}{#2}{#3}{#4}{#5}{#6}} % Environment encloses description. {} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % rpgtable.sty - to be removed in version 1.0.0 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Table Header \newcommand{\header}[1]{% \begingroup% \par\vspace{10pt plus 3 pt minus 3pt}% \noindent% \RpgFontTableTitle% #1% \endgroup% } % Table Environment \NewDocumentEnvironment{rpgtable}{O{XX} O{tablecolor}}{% \RpgDeprecate{\noexpand\rpgtable}{1.0.0}{Use \noexpand\RpgTable for tables.}% \par\vspace{2pt plus 1pt minus 1pt}% \noindent% \RpgFontTableBody% \setlength{\extrarowheight}{3pt}% \rowcolors{1}{}{#2}% \tabularx{\linewidth}{#1}% }{% \endtabularx% \par\vspace{10pt plus 3 pt minus 3pt}% }