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.

239 lines
9.2KB

  1. require "prawn"
  2. require "pry"
  3. require_relative "spell"
  4. require_relative "spells"
  5. require_relative "primitive_adds"
  6. puts "Shards of Power PDF generator"
  7. class ShardsOfPower
  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 #{@shards_of_power.chapter_title} on page #{page_number}"
  21. section(@shards_of_power.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(:@shards_of_power, 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 "Shards of Power", :align => :center
  93. puts "\tShards of Power big text..."
  94. pdf.font "Goudy"
  95. pdf.font_size 36
  96. pdf.text "\nA compendium of spells, Conditions, Artifacts, and other interesting tidbits for Mage: the Awakening\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. pdf.text "Like every supernatural entity in the Chronicles of Darkness, there is a boundless breadth and depth of topics to discuss within them. The Awakened are by no stretch of the imagination an exception to this rule. This book does not dare claim that this will cover all of them, but it does dare to cover the broad strokes on a certain subtopic of the lives of those touched by the Supernal who still reside in the Fallen World: their toolkit.\n\n<b>Mage: the Awakening</b> covered the broadest strokes on Awakened life in general, but there is so much more to the means by which Mages conduct their affairs and pursue their Obsessions that simply is not covered in that volume. There will be yet more that this one fails to consider. However, it is designed to touch on the high level ideas, and dig into some of the specifics for them, leaving you, the reader compelled, and hopefully, inspired as to where to explore next.", :inline_format => true
  105. start_section "Tools Of Awakened Life"
  106. pdf.text "This book is meant to be used as a toolkit. Each of the spells are modular, and for the most part do not operate off of each other. You, as the Storyteller or player, are meant to take the things you find fun, interesting and compelling while leaving the things you find silly, improper, or frustrating behind. This line of thought naturally extends to all of the Conditions, optional Arcana principles, alternative Relinquishment methods, and so on.\n\nThis book was written on a rolling basis by a number of people. It is a compilation, that accumulated over time. It did not get created overnight. As such, by the time you receive this file, there is a good likelihood that it's still in development, which means there might be more up-to-date versions of it, and additionally it may be open to input for your spells, your Artifacts, and your optional rules. The invite code at the time of publication is <b>Cx3JBpB</b>.", :inline_format => true
  107. start_section "Chapters"
  108. pdf.text "There are multiple chapters in this book. Each of them covers a specific set of topics.\n\n<b>Chapter One</b> is ithe Introduction. It is what you are reading now. It gives the mission statement, the credits, and a few other key details before you get into the spells and the Conditions.\n\n<b>Chapter Two</b> is the megagrimoire. It is a grimoire of grimoires, much like the book that White Wolf released when they still called themselves that, and is a combined set of spells that the players of this community have mutually agreed are at least somewhat reasonable. Many of us helped each other write these spells. All of their names will be listed in them, alphabetically.", :inline_format => true
  109. start_chapter("Two", "Spells")
  110. spells.group_by(&:primary_arcanum).sort_by { |arcanum, spells| arcanum }.to_h.each do |arcanum, arcanum_spells|
  111. arcanum_name = arcanum.to_s.titleize
  112. puts "Compiling spells for #{arcanum_name}..."
  113. start_section("#{arcanum_name} Spells")
  114. arcanum_spells.group_by(&arcanum).sort_by { |rating, spells| rating }.to_h.each do |rating, rating_spells|
  115. rating_title = "#{rating.to_dots} #{Spell::RANKS[rating - 1]} of #{arcanum_name}"
  116. puts "\tCompiling #{rating_title} spells..."
  117. pdf.outline.add_subsection_to("#{arcanum_name} Spells") do
  118. @pdf.outline.section rating_title, :destination => @pdf.page_number
  119. end
  120. pdf.font_size FONT_SIZE_SECTION
  121. pdf.text rating_title
  122. rating_spells.sort_by { |spell| spell.name }.each do |spell|
  123. puts "\t\tCompiling #{spell.full_title} by #{spell.authors.join(', ')}"
  124. pdf.outline.add_subsection_to(rating_title) do
  125. @pdf.outline.section spell.full_title, :destination => @pdf.page_number
  126. end
  127. spell_ary = [{:text => "#{spell.name} (", :font => "Lilith", :color => "004E6D", :size => FONT_SIZE_SUBSECTION}]
  128. pdf.font_size FONT_SIZE_BODY
  129. previous = false
  130. spell.arcana.each do |arcanum|
  131. spell_ary << {:text => ", ", :font => "Lilith", :color => "004E6D", :size => FONT_SIZE_SUBSECTION} if previous
  132. spell_ary << {:text => arcanum.to_s.titleize, :font => "Lilith", :color => "004E6D", :size => FONT_SIZE_SUBSECTION}
  133. spell_ary << {:text => spell.send(arcanum).to_dots, :color => "004E6D", :size => FONT_SIZE_SUBSECTION, :character_spacing => -5}
  134. previous = true
  135. end
  136. spell_ary << {:text => " )", :font => "Lilith", :styles => [], :color => "004E6D", :size => FONT_SIZE_SUBSECTION, :character_spacing => -3}
  137. pdf.formatted_text spell_ary
  138. pdf.formatted_text [
  139. {:text => "Practice: ", :styles => [:bold], :font => "Goudy"},
  140. {:text => spell.practice, :font => "Goudy"},
  141. ]
  142. pdf.formatted_text [
  143. {:text => "Primary Factor: ", :styles => [:bold], :font => "Goudy"},
  144. {:text => spell.primary_factor, :font => "Goudy"},
  145. ]
  146. pdf.formatted_text [
  147. {:text => "Withstand: ", :styles => [:bold], :font => "Goudy"},
  148. {:text => spell.withstand, :font => "Goudy"},
  149. ] if !spell.withstand.nil?
  150. pdf.formatted_text [
  151. {:text => "Suggested Rote Skills: ", :styles => [:bold], :font => "Goudy"},
  152. {:text => spell.suggested_rote_skills.join(', '), :font => "Goudy"},
  153. ]
  154. pdf.formatted_text [
  155. {:text => spell.authors.length == 1 ? "Author: " : "Authors: ", :styles => [:bold], :font => "Goudy"},
  156. {:text => spell.authors.join(', '), :font => "Goudy"},
  157. ]
  158. pdf.text spell.rules_text, :inline_format => true
  159. spell.reaches.each do |reach|
  160. pdf.formatted_text [
  161. {:text => "+#{reach[0]} Reach: ", :styles => [:bold], :font => "Goudy"},
  162. {:text => reach[1], :font => "Goudy"},
  163. ]
  164. end
  165. spell.adds.each do |add|
  166. pdf.formatted_text [
  167. {: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"},
  168. {:text => add[:effect], :font => "Goudy"},
  169. ]
  170. end
  171. end
  172. end
  173. pdf.start_new_page
  174. end
  175. pdf.render_file("shards_of_power.pdf")
  176. end
  177. end
  178. shards_of_power = ShardsOfPower.new
  179. shards_of_power.generate