Chronicles of Darkness grimoire-Artifact PDF https://git.lain.church/TheStranjer/ShardsOfPower
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

242 lines
9.9KB

  1. require "prawn"
  2. require "pry"
  3. require_relative "spell"
  4. require_relative "spells"
  5. require_relative "primitive_adds"
  6. puts "Book of Faces PDF generator"
  7. class BookOfFaces
  8. FONT_SIZE_CHAPTER = 48
  9. FONT_SIZE_SECTION = 24
  10. FONT_SIZE_SUBSECTION = 18
  11. FONT_SIZE_BODY = 10
  12. attr_accessor :pdf, :number_name, :chapter_name, :chapter_title, :section_name, :spells
  13. def start_chapter(num, name)
  14. @number_name = num
  15. @chapter_name = name
  16. @chapter_title = "Chapter #{number_name}: #{chapter_name}"
  17. puts "Starting #{chapter_title}"
  18. pdf.start_new_page
  19. pdf.outline.update do
  20. puts "\tAdding #{@book_of_faces.chapter_title} on page #{page_number}"
  21. section(@book_of_faces.chapter_title, :destination => page_number)
  22. end
  23. puts "\tSetting font size"
  24. pdf.font_size FONT_SIZE_CHAPTER
  25. pdf.font "Abess"
  26. puts "\tPrinting chapter to document"
  27. pdf.text "Chapter #{number_name}: #{chapter_name}"
  28. puts "\tRestoring body text"
  29. pdf.font "Goudy"
  30. pdf.font_size FONT_SIZE_BODY
  31. end
  32. def start_section(section_name)
  33. puts "Beginning section #{section_name}: "
  34. @section_name = section_name
  35. pdf.outline.add_subsection_to(chapter_title) do
  36. @pdf.outline.section section_name, :destination => @pdf.page_number
  37. end
  38. puts "\tSetting font size"
  39. pdf.font_size FONT_SIZE_SECTION
  40. pdf.text section_name
  41. puts "\tRestoring body text"
  42. pdf.font_size FONT_SIZE_BODY
  43. pdf.font "Goudy"
  44. end
  45. def roll_results(dramatic_failure:, failure:, success:, exceptional_success:)
  46. pdf.font_size FONT_SIZE_BODY
  47. pdf.font "Goudy"
  48. pdf.text "Roll Results", :style => :bold
  49. pdf.formatted_text [
  50. { :text => "Dramatic Failure: ", :styles => [:bold] },
  51. { :text => dramatic_failure }
  52. ]
  53. pdf.formatted_text [
  54. { :text => "Failure: ", :styles => [:bold] },
  55. { :text => failure }
  56. ]
  57. pdf.formatted_text [
  58. { :text => "Success: ", :styles => [:bold] },
  59. { :text => success }
  60. ]
  61. pdf.formatted_text [
  62. { :text => "Exceptional Success: ", :styles => [:bold] },
  63. { :text => exceptional_success }
  64. ]
  65. end
  66. def generate
  67. puts "Parsing spells..."
  68. @spells = Spell.spells
  69. puts "Creating PDF object..."
  70. @pdf = Prawn::Document.new(:margin => 0)
  71. pdf.default_leading 5
  72. pdf.font_families.update(
  73. "Goudy" => {
  74. :normal => "goudy.ttf",
  75. :bold => "goudy-bold.ttf",
  76. :italic => "goudy-italic.ttf"
  77. },
  78. "Abess" => {
  79. :normal => "abess.ttf"
  80. },
  81. "Lilith" => {
  82. :normal => "lilith.ttf"
  83. }
  84. )
  85. pdf.outline.instance_variable_set(:@book_of_faces, self)
  86. puts "Importing cover..."
  87. pdf.image("cover.png", :width => 612, :height => 792)
  88. puts "Printing inner cover..."
  89. pdf.start_new_page(:margin => 75)
  90. pdf.font "Abess"
  91. pdf.font_size 72
  92. pdf.text "The Book\nOf Faces", :align => :center
  93. puts "\tBook Of Faces big text..."
  94. pdf.font "Goudy"
  95. pdf.font_size 36
  96. pdf.text "\nA grimoire of spells, Gifts, Disciplines, Contracts, and other anomalies, with anecdotes and exposition from their in-game authors\n\n", :align => :center
  97. puts "\tDescription..."
  98. pdf.font_size 24
  99. pdf.text "Written by members of the /cofd/ Discord, edited by NEETzsche", :align => :center
  100. puts "\tMain credit..."
  101. pdf.outline.define do
  102. end
  103. start_chapter "One", "Introduction"
  104. start_section "Judging It By Its Cover"
  105. pdf.text "This tome is an Artifact-grimoire with certain special properties. It easily weighs about thirty or so pounds from all of the paper within it. It is leather bound with a very visible face on its cover and no title listed; each time people look away and take another look at it, the face on it changes. Upon opening it, it appears anachronistic and mixed. Most of the pages are merely old paper, but some of them are papyrus scrolls that have been glued into it, while others are cuneiform tablets, and some are even touch screens. Upon inspection of this tome, it's clear it should be much bigger, and much heavier, than it actually is. A quill pen is attached to it by a string. Even though a quill pen normally would only be used with ink-on-paper, it appears to also work as a tool to etch into the cuneiform tablets, as a stylus for the touch screens, and whatever else someone manages to find in this tome. Its contents change upon future viewings, making it feel like an endless sea."
  106. start_section "Exploring Its Contents"
  107. pdf.text "If one were to open it up and start reading, the content would make no sense. It simply cannot be understood. No amount of knowledge on High Speech, First Tongue, or whatever other language of supernatural origin seems to decipher it. However, he who possesses this book may inscribe their meaningful experiences into it. Mages can Scribe Grimoire (Mage: the Awakening, p. 166) into it, except not only is it Lasting, but they may also place their improvised spells in it as though they were Rotes. They may also write their anecdotes, philosophy and experiences within this book, as long as they are sufficiently meaningful. Other supernatural entities like vampires or werewolves may list in explicit detail their Gifts, Disciplines, Contracts or other traits."
  108. pdf.text "This action requires an hour of soul-searching, a successful roll on their equivalent Integrity rating, and a Beat. This Beat is consumed by the book; that Beat is gone forever."
  109. roll_results(
  110. :dramatic_failure => "Same as failure, but in addition to this, the Book of Faces is offended at the player's arrogance. It emits a piercing roar that deals one point of Resistant aggravated damage to everyone in the room.",
  111. :failure => "The person attempting it gave the Book Of Faces dross. It gave it crap, nonsense. Emo scribblings and cockamamie shitposts. They do not get their Beat back; turns out, their life experience wasn't that useful after all. They may try again without penalty, but must sacrifice another Beat.",
  112. :success => "The content the character submitted is of actual value, and it is accepted, incorporated into its pages.\n\nIf the roll succeeds, for the remainder of the scene, the character may at his discretion learn any of the Rotes (as long as they have the Arcanum prerequisites, and even if they were Improvised spells when they were put into the Book of Faces) and Disciplines, may have Gifts conferred upon them, and may enter into Contracts found therein. In mechanics terms, the character reads the Book of Faces extensively for a number of hours and spends their Experiences however they desire, focusing on the things they find most interesting. If they want to use the Book of Faces again in the future, they must make a second roll.",
  113. :exceptional_success => "The willworker not only gives it valuable information, but demonstrates they are particularly capable of learning. They gain a full Experience point, but it can only be spent learning things from the Book of Faces"
  114. )
  115. start_chapter("Two", "Spells")
  116. spells.group_by(&:primary_arcanum).sort_by { |arcanum, spells| arcanum }.to_h.each do |arcanum, arcanum_spells|
  117. arcanum_name = arcanum.to_s.titleize
  118. puts "Compiling spells for #{arcanum_name}..."
  119. start_section("#{arcanum_name} Spells")
  120. arcanum_spells.group_by(&arcanum).sort_by { |rating, spells| rating }.to_h.each do |rating, rating_spells|
  121. rating_title = "#{rating.to_dots} #{Spell::RANKS[rating - 1]} of #{arcanum_name}"
  122. puts "\tCompiling #{rating_title} spells..."
  123. pdf.outline.add_subsection_to("#{arcanum_name} Spells") do
  124. @pdf.outline.section rating_title, :destination => @pdf.page_number
  125. end
  126. pdf.font_size FONT_SIZE_SECTION
  127. pdf.text rating_title
  128. rating_spells.sort_by { |spell| spell.name }.each do |spell|
  129. puts "\t\tCompiling #{spell.full_title} by #{spell.authors.join(', ')}"
  130. spell_ary = [{:text => "#{spell.name} (", :font => "Lilith", :color => "004E6D", :size => FONT_SIZE_SUBSECTION}]
  131. pdf.font_size FONT_SIZE_BODY
  132. previous = false
  133. spell.arcana.each do |arcanum|
  134. spell_ary << {:text => ", ", :font => "Lilith", :color => "004E6D", :size => FONT_SIZE_SUBSECTION} if previous
  135. spell_ary << {:text => arcanum.to_s.titleize, :font => "Lilith", :color => "004E6D", :size => FONT_SIZE_SUBSECTION}
  136. spell_ary << {:text => spell.send(arcanum).to_dots, :color => "004E6D", :size => FONT_SIZE_SUBSECTION, :character_spacing => -5}
  137. previous = true
  138. end
  139. spell_ary << {:text => " )", :font => "Lilith", :styles => [], :color => "004E6D", :size => FONT_SIZE_SUBSECTION, :character_spacing => -3}
  140. pdf.formatted_text spell_ary
  141. pdf.formatted_text [
  142. {:text => "Practice: ", :styles => [:bold], :font => "Goudy"},
  143. {:text => spell.practice, :font => "Goudy"},
  144. ]
  145. pdf.formatted_text [
  146. {:text => "Primary Factor: ", :styles => [:bold], :font => "Goudy"},
  147. {:text => spell.primary_factor, :font => "Goudy"},
  148. ]
  149. pdf.formatted_text [
  150. {:text => "Withstand: ", :styles => [:bold], :font => "Goudy"},
  151. {:text => spell.withstand, :font => "Goudy"},
  152. ] if !spell.withstand.nil?
  153. pdf.formatted_text [
  154. {:text => "Suggested Rote Skills: ", :styles => [:bold], :font => "Goudy"},
  155. {:text => spell.suggested_rote_skills.join(', '), :font => "Goudy"},
  156. ]
  157. pdf.formatted_text [
  158. {:text => spell.authors.length == 1 ? "Author: " : "Authors: ", :styles => [:bold], :font => "Goudy"},
  159. {:text => spell.authors.join(', '), :font => "Goudy"},
  160. ]
  161. pdf.text spell.rules_text
  162. spell.reaches.each do |reach|
  163. pdf.formatted_text [
  164. {:text => "+#{reach[0]} Reach: ", :styles => [:bold], :font => "Goudy"},
  165. {:text => reach[1], :font => "Goudy"},
  166. ]
  167. end
  168. spell.adds.each do |add|
  169. pdf.formatted_text [
  170. {:text => "#{add[:verb] ? add[:verb] : "Add"} #{add[:arcana].collect { |arcanum, rating| [arcanum, rating].to_arcanum_with_dots }.to_list(:separator => add[:separator])}: ", :styles => [:bold], :font => "Goudy"},
  171. {:text => add[:effect], :font => "Goudy"},
  172. ]
  173. end
  174. end
  175. end
  176. pdf.start_new_page
  177. end
  178. pdf.render_file("book_of_faces.pdf")
  179. end
  180. end
  181. book_of_faces = BookOfFaces.new
  182. book_of_faces.generate