Source for Sean's Star Sagas stuff

Gradient statblocks

Changed files
+237 -141
+204 -107
KNIGHTS.typ
··· 118 118 } 119 119 ] 120 120 121 - #pagebreak(to: "odd") 121 + #page[] 122 122 123 123 #set page(columns: 2, numbering: "1") 124 124 ··· 162 162 The original video games are based on the _Dungeons & Dragons_ 3rd Edition ruleset, which was also then streamlined---think how _Baldur's Gate 3_ tweaked _Dungeons & Dragons_ 5th Edition. 163 163 5E is very familiar and I didn't want to force players to learn a new system, so this book also aims to retrofit the original games' "D&D-isms" into a 5E shell, like using 5E's Power Attack mechanics instead of how it worked in the video games. 164 164 165 - #pagebreak() 166 - 167 165 #{ 168 166 show: templates.chapter-intro 169 167 show: knights-chapter-cover-template ··· 173 171 heading[Characters] 174 172 } 175 173 176 - #pagebreak() 174 + #{ 175 + show: templates.chapter-heading 176 + 177 + upper[= Character Creation] 178 + } 179 + 180 + #{ 181 + show: templates.chapter-heading 182 + upper(heading(outlined: false)[The Fighter]) 183 + } 184 + 185 + == Class Features 186 + 187 + As a fighter, you gain the following class features. 188 + 189 + === Hit Points 190 + 191 + / Hit Dice: 1D10 per fighter level 192 + / Hit Points at 1st Level: 10 + your Constitution modifier 193 + / Hit Points at Higher Levels: 1D10 (or 6) + your Constitution modifier per fighter level after 1st 194 + 195 + === Proficiencies 196 + 197 + / Armor: All armor, shields 198 + / Weapons: Simple weapons, martial weapons 199 + / Tools: None 200 + 201 + === Fighting Style 202 + 203 + You adopt a particular style of fighting as your specialty. 204 + Choose one of the following options. 205 + You can’t take a Fighting Style option more than once, even if you later get to choose again. 206 + 207 + ==== Archery 208 + 209 + You gain a +2 bonus to attack rolls you make with ranged weapons 210 + 211 + ==== Defense 212 + 213 + While you are wearing armor, you gain a +1 bonus to AC 214 + 215 + ==== Dueling 216 + 217 + When you are wielding a melee weapon in one hand and no other weapons, you gain a +2 bonus to damage rolls with that weapon. 218 + 219 + ==== Great Weapon Fighting 220 + 221 + When you roll a 1 or 2 on a damage die for an attack you make with a melee weapon that you are wielding with two hands, you can reroll the die and must use the new roll, even if the new roll is a 1 or a 2. 222 + The weapon must have the two-handed or versatile property for you to gain this benefit. 223 + 224 + ==== Protection 225 + 226 + When a creature you can see attacks a target other than you that is within 5 feet of you, you can use your reaction to impose disadvantage on the attack roll. 227 + You must be wielding a shield. 228 + 229 + ==== Two-Weapon Fighting 230 + 231 + When you engage in two-weapon fighting, you can add your ability modifier. 232 + 233 + #{ 234 + show: templates.chapter-heading 235 + upper(heading(outlined: false)[The Scoundrel]) 236 + } 237 + 238 + #{ 239 + show: templates.chapter-heading 240 + 241 + upper[== The Sorce-Wielder] 242 + } 243 + 244 + #{ 245 + show: templates.chapter-heading 246 + 247 + upper[= Sorce Powers] 248 + } 177 249 178 250 #{ 179 251 show: templates.chapter-intro ··· 184 256 heading[Rules] 185 257 } 186 258 187 - #pagebreak() 188 - 189 259 #{ 190 260 show: templates.chapter-heading 191 261 192 262 upper[= The Stealth Sequence] 193 263 } 194 264 195 - #pagebreak() 196 - 197 265 #{ 198 266 show: templates.chapter-heading 199 267 200 268 upper[= The Combat Sequence] 201 269 } 202 - 203 - #pagebreak() 204 270 205 271 #{ 206 272 show: templates.chapter-intro ··· 210 276 211 277 heading[Campaigns in the First Imperium] 212 278 } 213 - 214 - #pagebreak() 215 279 216 280 #{ 217 281 show: templates.chapter-heading 218 282 219 - upper[= Adversaries] 283 + upper[= Companions] 284 + } 220 285 221 - show: templates.chapter-heading-par 286 + #{ 287 + [== 4K-47] 222 288 223 - lorem(50) 289 + npc-statblock( 290 + name: [4K-47], 291 + description: [Medium Humanoid (4K Unit), Chaotic Dark, Hates meatbags], 292 + role: [Companion], 293 + str: 15, 294 + dex: 17, 295 + con: 13, 296 + int: 10, 297 + wis: 8, 298 + cha: 9, 299 + attrs: ( 300 + [*Armor Class* 15 (natural armor)], 301 + [*Guard* 18], 302 + [*Hit Points* 16], 303 + [*Speed* 35 ft.], 304 + ), 305 + stats: ( 306 + [*Languages* Basic, Ternary, 4K Ternary], 307 + [*Saves* Str +3, Dex + 3, Cha +3], 308 + [*Proficiency Bonus* equal to party leader's proficiency bonus], 309 + ), 310 + named-ability-sections: ( 311 + ( 312 + title: [Actions], 313 + abilities: ( 314 + [ 315 + _*Signature Attack (Ion Blaster)*_. 316 + _Ranged Weapon Attack:_ 317 + +4 plus PB to hit, range 30/60 ft., one target. 318 + _Hit:_ 6 kinetic damage. 319 + ], 320 + ), 321 + ), 322 + ( 323 + title: [Reactions], 324 + abilities: ( 325 + [ 326 + _*Not Bad, for a Meatbag (3/Day).*_ 327 + When 4K-47 witnesses a sapient creature within earshot defeat an enemy in combat, it gives them a compliment. 328 + The creature gains advantage on their all attacks for the remainder of combat. 329 + ], 330 + [ 331 + _*Reactive Shield (1/Day).*_ 332 + Until the start of its next turn, 4K-47 has a +5 bonus to AC. 333 + This includes the triggering attack. 334 + ], 335 + ), 336 + ), 337 + ), 338 + ) 224 339 } 225 340 226 - == Mandos 341 + #{ 342 + show: place.with(bottom, float: true, scope: "parent") 227 343 228 - // #region Manderous 229 - // We want this guaranteed to be on the first page of Mandos, so it's placed first. 230 - #place( 231 - bottom, 232 - float: true, 233 - scope: "parent", 234 - { 235 - [=== Companion: Manderous Brodo] 344 + [== Manderous Brodo] 236 345 237 - [ 238 - Manderous is a total bro. He's awesome. 239 - ] 346 + [ 347 + Manderous is a total bro. He's awesome. 348 + ] 240 349 241 - npc-statblock( 242 - num-columns: 2, 243 - name: [Manderous Brodo], 244 - role: [Companion], 245 - str: 18, 246 - dex: 14, 247 - con: 16, 248 - int: 8, 249 - wis: 9, 250 - cha: 10, 251 - ac: [17 (badass Mando armor)], 252 - hp: [8 + Eight times their level (number of d10 Hit Dice equal to their level)], 253 - speed: ([35 ft.],), 254 - type: [Medium Humanoid (Mando)], 255 - alignment: [Chaotic Dark], 256 - attrs: ( 257 - [*Source Echo* Manly, brotherly bright pink], 258 - ), 259 - stats: ( 260 - [*Saves* Str + 3], 261 - [*Proficiency Bonus* equal to leader's proficiency bonus], 350 + npc-statblock( 351 + num-columns: 2, 352 + name: [Manderous Brodo], 353 + description: [Medium Humanoid (Mando), Chaotic Dark, Crew Cut], 354 + role: [Companion], 355 + str: 18, 356 + dex: 14, 357 + con: 16, 358 + int: 8, 359 + wis: 9, 360 + cha: 10, 361 + attrs: ([*Source Echo* Manly, brotherly bright pink],), 362 + stats: ([*Saves* Str + 3], [*Proficiency Bonus* equal to party leader's proficiency bonus]), 363 + named-ability-sections: ( 364 + ( 365 + title: [Actions], 366 + abilities: ( 367 + [ 368 + _*Signature Attack (Lazgun).*_ 369 + _Ranged Weapon Attack:_ 370 + +3 plus PB to hit, one target. 371 + _Hit:_ 1d10 plus PB kinetic damage. 372 + ], 373 + [ 374 + _*1st Level: Thermal Detonator (2 Ferocity).*_ 375 + #lorem(15) 376 + ], 377 + [ 378 + _*2nd Level: Thermal Detonator (2 Ferocity).*_ 379 + #lorem(15) 380 + ], 381 + [ 382 + _*3rd Level: Thermal Detonator (2 Ferocity).*_ 383 + #lorem(15) 384 + ], 385 + [ 386 + #colbreak() 387 + _*5th Level: Thermal Detonator (2 Ferocity).*_ 388 + #lorem(15) 389 + ], 390 + ), 262 391 ), 263 - named-ability-sections: ( 264 - ( 265 - title: [Actions], 266 - abilities: ( 267 - [ 268 - _*Signature Attack (Lazgun).*_ 269 - _Ranged Weapon Attack:_ 270 - +3 plus PB to hit, one target. 271 - _Hit:_ 1d10 plus PB kinetic damage. 272 - ], 273 - [ 274 - _*1st Level: Thermal Detonator (2 Ferocity).*_ 275 - #lorem(15) 276 - ], 277 - [ 278 - _*2nd Level: Thermal Detonator (2 Ferocity).*_ 279 - #lorem(15) 280 - ], 281 - [ 282 - _*3rd Level: Thermal Detonator (2 Ferocity).*_ 283 - #lorem(15) 284 - ], 285 - [ 286 - #colbreak() 287 - _*5th Level: Thermal Detonator (2 Ferocity).*_ 288 - #lorem(15) 289 - ], 290 - ), 291 - ), 292 - ( 293 - title: [Reactions], 294 - abilities: ( 295 - [ 296 - _*Covering Fire (1/Day)!*_ 297 - When Manderous and his leader are within 30 feet of each other and one of them is hit by an attack, Manderous uses his Lazgun to cover you both, moving to an unoccupied space they can see within 30 feet. 298 - ], 299 - ), 392 + ( 393 + title: [Reactions], 394 + abilities: ( 395 + [ 396 + _*Covering Fire! (1/Day)*_ 397 + When Manderous and his leader are within 30 feet of each other and one of them is hit by an attack, Manderous uses his Lazgun to cover you both, moving to an unoccupied space they can see within 30 feet. 398 + ], 300 399 ), 301 400 ), 302 - ) 303 - }, 304 - ) 305 - // #endregion 401 + ), 402 + ) 403 + } 404 + 405 + #{ 406 + show: templates.chapter-heading 306 407 307 - // We can place these mandos in any order 408 + upper[= Adversaries] 409 + } 410 + 411 + == 4K Units 412 + 413 + #pagebreak() 414 + 415 + == Mandos 416 + 308 417 #place(bottom, float: true)[ 309 418 #npc-statblock( 310 419 name: [Mando Charger], 311 - type: [Medium Humanoid (Mando)], 312 - alignment: [Typically Chaotic], 313 - cr: [1/2], 314 - role: [Minion], 315 - ac: [13 (light armor)], 316 - attrs: ([*Sorce Echo* A misty blue with gray and amber vapor whisps],), 317 - hp: [7], 420 + description: [Medium Humanoid (Mando), Typically Chaotic], 421 + role: [CR 1/2 Minion], 422 + role-detail: [20 XP], 318 423 str: 15, 319 424 dex: 12, 320 425 con: 12, 321 426 wis: 11, 322 427 cha: 11, 323 - speed: ([35 ft.],), 324 - xp-value: [20 XP], 325 428 stats: ( 326 429 [*Senses* darkvision 60 ft., passive Perception 10], 327 430 [*Proficiency Bonus* +2], ··· 372 475 #place(top, float: true)[ 373 476 #npc-statblock( 374 477 name: [Mando Sharpshooter], 375 - type: [Medium Humanoid (Mando)], 376 - alignment: [Typically Chaotic], 377 - cr: [1], 378 - role: [Artillery], 379 - ac: [13 (light armor)], 380 - hp: [30 (4d8 + 12)], 478 + description: [Medium Humanoid (Mando), Typically Chaotic], 479 + role: [CR 1 Artillery], 381 480 str: 14, 382 481 dex: 16, 383 482 con: 16, 384 483 wis: 12, 385 484 cha: 12, 386 - speed: ([35 ft.],), 387 485 stats: ( 388 486 [*Senses* darkvision 60 ft., passive Perception 10], 389 487 [*Proficiency Bonus* +2], 390 488 [*Languages* Basic, Mandoa, understands all languages but can't speak], 391 489 ), 392 - xp-value: [20 XP], 393 490 ) 394 491 ] 395 492
+33 -34
lib5e.typ
··· 24 24 set text(font: "Ubuntu Sans", number-type: "lining") 25 25 show strong: set text(fill: accent) 26 26 set line(stroke: (paint: accent)) 27 + let statblock-gradient = gradient.linear(angle: 45deg, white, white.darken(10%)) 27 28 28 29 block( 29 - fill: white, 30 + fill: statblock-gradient, 30 31 width: 100%, 31 32 inset: 0.65em, 32 33 breakable: false, ··· 44 45 45 46 #let npc-statblock( 46 47 name: [], 48 + description: [], 47 49 str: 10, 48 50 dex: 10, 49 51 con: 10, 50 52 int: 10, 51 53 wis: 10, 52 54 cha: 10, 53 - retainer: false, 54 - ac: [], 55 - hp: [], 56 - shadow: [–], 57 - speed: (), 58 55 attrs: (), 59 56 stats: (), 60 57 feats: (), 61 - cr: [], 62 58 role: [], 63 - type: [], 64 - alignment: [], 65 - xp-value: [], 59 + role-detail: [], 66 60 num-columns: 1, 67 61 named-ability-sections: (), 68 - break-before: none, 69 62 ) = { 70 63 set align(start + top) 71 64 show: stat-template ··· 109 102 stack( 110 103 dir: ttb, 111 104 text(size: 1.5em, smallcaps[*#name*]), 112 - emph[#type, #alignment], 105 + emph(description), 113 106 ), 114 107 ), 115 108 grid.cell( ··· 121 114 inset: (top: padding, left: padding), 122 115 { 123 116 set align(top + right) 124 - if (cr != []) { 125 - stack( 126 - dir: ttb, 127 - strong[CR #cr #role], 128 - [#xp-value], 129 - ) 130 - } else { 117 + { 131 118 strong(role) 119 + 120 + par(role-detail) 132 121 } 133 122 }, 134 123 ), ··· 139 128 show: statline 140 129 stack( 141 130 dir: ttb, 142 - par[*Armor Class* #ac], 143 - par[*Hit Points* #hp], 144 - par[*Speed* #speed.join(", ")], 145 131 ..attrs.map(par), 146 132 ) 147 133 } ··· 175 161 176 162 177 163 if ( 178 - feats.len() > 0 or named-ability-sections.len() > 0 and break-before != "named-actions" 164 + feats.len() > 0 or named-ability-sections.len() > 0 179 165 ) { line(length: 100%) } 180 166 181 167 if (feats.len() > 0) { 182 168 stack(dir: ttb, ..feats) 183 169 } 184 - 185 - if (break-before == "named-actions") { colbreak() } 186 170 187 171 if (named-ability-sections.len() > 0) { 188 172 for section in named-ability-sections { 189 - if (section.at("break-before", default: false) == true) { colbreak() } 190 - 191 173 action-heading(upper(strong(section.title))) 192 174 193 175 stack(dir: ttb, ..section.abilities) 194 - 195 - if (section.at("break-after", default: false) == true) { 196 - colbreak() 197 - } 198 176 } 199 177 } 200 178 } 201 179 202 - #let hero-spread-template(content) = { 180 + #let hero-spread-template(insert-page: true, content) = { 203 181 set page(numbering: none, columns: 1) 204 182 set text(font: "Ysabeau Office", size: 14pt) 205 183 show heading: set text( ··· 212 190 style: "italic", 213 191 ) 214 192 193 + if (insert-page == true) { 194 + pagebreak() 195 + } 196 + 215 197 content 216 198 } 217 199 218 - #let hero-heading-template(content) = { 200 + #let hero-heading-template(insert-page: true, content) = { 201 + if (insert-page == true) { 202 + pagebreak() 203 + } 204 + 219 205 show: place.with( 220 206 top + center, 221 207 float: true, ··· 224 210 225 211 show heading: set text( 226 212 font: "Reforma 1918", 227 - size: 2em, 213 + size: 28pt, 228 214 weight: 900, 229 215 tracking: 0pt, 230 216 ) ··· 241 227 content 242 228 } 243 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 + 244 242 #let templates = ( 245 243 base: template, 246 244 stat: stat-template, 247 245 chapter-heading: hero-heading-template, 248 246 chapter-heading-par: hero-heading-par, 249 247 chapter-intro: hero-spread-template, 248 + sidebar: sidebar-template, 250 249 )