Source for Sean's Star Sagas stuff
at trunk 5.7 kB view raw
1// Licensed under the Open Software License version 3.0 2// OR 3// Licensed under the MIT License. 4 5#let accent = red.darken(50%).saturate(-25%) 6#let paper-color = rgb("#fae6cf") 7 8#let template(content) = { 9 set page(fill: paper-color) 10 set text(font: "Gentium Book Plus", features: ("ss02",)) 11 show heading: set text(font: "Ysabeau Office", weight: 800) 12 show heading: set par(leading: 0.325em) 13 show heading: set align(center) 14 15 content 16} 17 18#let modifier(number) = { 19 let mod = calc.floor((number - 10) / 2) 20 if (mod < 0) [#mod] else { [+#mod] } 21} 22 23#let stat-template(content) = { 24 set text(font: "Ubuntu Sans", number-type: "lining") 25 show strong: set text(fill: accent) 26 set line(stroke: (paint: accent)) 27 let statblock-gradient = gradient.linear(angle: 45deg, white, white.darken(10%)) 28 29 block( 30 fill: statblock-gradient, 31 width: 100%, 32 inset: 0.65em, 33 breakable: false, 34 content, 35 ) 36} 37 38#let sourceref(abbr) = super[\[#abbr\]] 39 40#let statblock-template( 41 slot-title: [], 42 slot-ability-scores: [], 43 slot-named-ability-sections: [], 44) = {} 45 46#let npc-statblock( 47 name: [], 48 description: [], 49 str: 10, 50 dex: 10, 51 con: 10, 52 int: 10, 53 wis: 10, 54 cha: 10, 55 attrs: (), 56 stats: (), 57 feats: (), 58 role: [], 59 role-detail: [], 60 num-columns: 1, 61 named-ability-sections: (), 62) = { 63 set align(start + top) 64 show: stat-template 65 set columns(num-columns) 66 67 let padding = 0.65em 68 let stroke-width = 0.75pt 69 let thin-stroke = stroke-width + accent 70 let thick-stroke = stroke-width * 2 + accent 71 72 set par(spacing: padding, leading: padding) 73 set stack(spacing: padding) 74 set line(stroke: stroke-width) 75 76 show: columns 77 78 let statline(content) = { 79 set par(hanging-indent: 1em) 80 81 content 82 } 83 84 let action-heading = block.with( 85 width: 100%, 86 inset: (bottom: padding / 2), 87 stroke: (bottom: stroke-width + accent), 88 above: 1em, 89 ) 90 91 { 92 set par(leading: padding / 2) 93 grid( 94 columns: (1fr, auto), 95 grid.cell( 96 stroke: ( 97 right: thin-stroke, 98 top: thick-stroke, 99 bottom: thin-stroke, 100 ), 101 inset: (y: padding, right: padding), 102 stack( 103 dir: ttb, 104 text(size: 1.5em, smallcaps[*#name*]), 105 emph(description), 106 ), 107 ), 108 grid.cell( 109 stroke: ( 110 left: thin-stroke, 111 top: thick-stroke, 112 bottom: thin-stroke, 113 ), 114 inset: (top: padding, left: padding), 115 { 116 set align(top + right) 117 { 118 strong(role) 119 120 par(role-detail) 121 } 122 }, 123 ), 124 ) 125 } 126 127 { 128 show: statline 129 stack( 130 dir: ttb, 131 ..attrs.map(par), 132 ) 133 } 134 135 line(stroke: 1.5pt, length: 100%) 136 137 { 138 set block(width: 100%) 139 set align(center) 140 grid( 141 columns: 6, 142 column-gutter: padding, 143 stack(dir: ttb, [*STR*], [#str (#modifier(str))]), 144 stack(dir: ttb, [*DEX*], [#dex (#modifier(dex))]), 145 stack(dir: ttb, [*CON*], [#con (#modifier(con))]), 146 stack(dir: ttb, [*INT*], [#int (#modifier(int))]), 147 stack(dir: ttb, [*WIS*], [#wis (#modifier(wis))]), 148 stack(dir: ttb, [*CHA*], [#cha (#modifier(cha))]), 149 ) 150 } 151 152 line(stroke: 1.5pt, length: 100%) 153 154 { 155 show: statline 156 stack( 157 dir: ttb, 158 ..stats.map(par), 159 ) 160 } 161 162 163 if ( 164 feats.len() > 0 or named-ability-sections.len() > 0 165 ) { line(length: 100%) } 166 167 if (feats.len() > 0) { 168 stack(dir: ttb, ..feats) 169 } 170 171 if (named-ability-sections.len() > 0) { 172 for section in named-ability-sections { 173 action-heading(upper(strong(section.title))) 174 175 stack(dir: ttb, ..section.abilities) 176 } 177 } 178} 179 180#let hero-spread-template(insert-page: true, content) = { 181 set page(numbering: none, columns: 1) 182 set text(font: "Ysabeau Office", size: 14pt) 183 show heading: set text( 184 size: 4em, 185 font: "Reforma 1969", 186 features: ( 187 "ss01", 188 "smcp", 189 ), 190 style: "italic", 191 ) 192 193 if (insert-page == true) { 194 pagebreak() 195 } 196 197 content 198} 199 200#let hero-heading-template(insert-page: true, content) = { 201 if (insert-page == true) { 202 pagebreak() 203 } 204 205 show: place.with( 206 top + center, 207 float: true, 208 scope: "parent", 209 ) 210 211 show heading: set text( 212 font: "Reforma 1918", 213 size: 28pt, 214 weight: 900, 215 tracking: 0pt, 216 ) 217 218 content 219} 220 221#let hero-heading-par(content) = { 222 let padding = 1em 223 show: block.with(width: 100%, inset: (y: padding)) 224 set align(start) 225 set text(font: "Ysabeau Office") 226 227 content 228} 229 230#let sidebar-template(title: [], content) = { 231 set text(size: 1em, font: "Ubuntu Sans") 232 show heading: set text(1em, font: "Ubuntu Sans") 233 show: block.with(fill: white, inset: 0.65em) 234 235 if (title != []) { 236 text(size: 1em, title) 237 } 238 239 content 240} 241 242#let templates = ( 243 base: template, 244 stat: stat-template, 245 chapter-heading: hero-heading-template, 246 chapter-heading-par: hero-heading-par, 247 chapter-intro: hero-spread-template, 248 sidebar: sidebar-template, 249)