From 04e7c8bc770df14d7e00aa1f9504a6b1985509d2 Mon Sep 17 00:00:00 2001 From: NEETzsche <791672+TheStranjer@users.noreply.github.com> Date: Thu, 18 May 2023 04:25:00 -0600 Subject: [PATCH] Two spaces, not tabs --- condition.rb | 20 +- conditions.rb | 50 ++-- primitive_adds.rb | 52 ++-- shards_of_power.rb | 680 ++++++++++++++++++++++++++--------------------------- spell.rb | 146 ++++++------ spells.rb | 390 +++++++++++++++--------------- tilt.rb | 40 ++-- tilts.rb | 44 ++-- 8 files changed, 711 insertions(+), 711 deletions(-) diff --git a/condition.rb b/condition.rb index 50d83be..4679ff4 100644 --- a/condition.rb +++ b/condition.rb @@ -1,13 +1,13 @@ class Condition - attr_accessor :name, :rules_text, :beat, :resolution, :persistent, :authors, :possible_sources + attr_accessor :name, :rules_text, :beat, :resolution, :persistent, :authors, :possible_sources - def initialize(name:, rules_text:, beat: "n/a", resolution:, persistent: false, authors:, possible_sources: nil) - @name = name - @rules_text = rules_text - @beat = beat - @resolution = resolution - @persistent = persistent - @authors = authors - @possible_sources = possible_sources - end + def initialize(name:, rules_text:, beat: "n/a", resolution:, persistent: false, authors:, possible_sources: nil) + @name = name + @rules_text = rules_text + @beat = beat + @resolution = resolution + @persistent = persistent + @authors = authors + @possible_sources = possible_sources + end end \ No newline at end of file diff --git a/conditions.rb b/conditions.rb index c41dea3..7caa617 100644 --- a/conditions.rb +++ b/conditions.rb @@ -1,33 +1,33 @@ class Condition - def self.conditions - conditions = [] + def self.conditions + conditions = [] - conditions << Condition.new( - :name => "Vicarious Story", - :rules_text => "Your character shares experiences with another character on an ongoing basis. This Condition is usually inflicted on someone for whom another person wants to watch a life event unfold, such as a marriage/divorce, a First Change, a pregnancy, or an Awakening.\n\nExperiences that are directly pertinent to the life event deliver sensory visions to the viewer. These visions might be shared dreams with the person being monitored, but might also be feeling a baby's first kick against the womb's walls or looking in a mirror and seeing a Wolf-Blood's teeth growing sharper. The exact nature of these details is up to Storyteller discretion, but pertinent details should not be withheld. Experiences that are not pertinent are completely omitted. Vicariously watching a person's Awakening skips scenes where the target spills coffee on their TPS reports.\n\nThese visions impose the Stunned Tilt on the one vicariously watching for a turn, but since these visions are so transient, it is not enough to interrupt a supernatural ritual or an extended action, but can be extremely inconvenient in time-sensitive circumstances such as combat. Since the effects of this Condition are partially detrimental, it does not count as \"beneficial\" for the purposes of spells that cause it; effectively, a spell that makes this Condition will get a Beat at its resolution.", - :resolution => "The life experience ends. The Awakening or First Change terminates. The child is born. The marital vows are complete or the divorce finalized.", - :beat => "The one vicariously viewing loses an action during combat or some similarly fast-paced situation.", - :authors => ["NEETzsche"] - ) + conditions << Condition.new( + :name => "Vicarious Story", + :rules_text => "Your character shares experiences with another character on an ongoing basis. This Condition is usually inflicted on someone for whom another person wants to watch a life event unfold, such as a marriage/divorce, a First Change, a pregnancy, or an Awakening.\n\nExperiences that are directly pertinent to the life event deliver sensory visions to the viewer. These visions might be shared dreams with the person being monitored, but might also be feeling a baby's first kick against the womb's walls or looking in a mirror and seeing a Wolf-Blood's teeth growing sharper. The exact nature of these details is up to Storyteller discretion, but pertinent details should not be withheld. Experiences that are not pertinent are completely omitted. Vicariously watching a person's Awakening skips scenes where the target spills coffee on their TPS reports.\n\nThese visions impose the Stunned Tilt on the one vicariously watching for a turn, but since these visions are so transient, it is not enough to interrupt a supernatural ritual or an extended action, but can be extremely inconvenient in time-sensitive circumstances such as combat. Since the effects of this Condition are partially detrimental, it does not count as \"beneficial\" for the purposes of spells that cause it; effectively, a spell that makes this Condition will get a Beat at its resolution.", + :resolution => "The life experience ends. The Awakening or First Change terminates. The child is born. The marital vows are complete or the divorce finalized.", + :beat => "The one vicariously viewing loses an action during combat or some similarly fast-paced situation.", + :authors => ["NEETzsche"] + ) - conditions << Condition.new( - :name => "Arcane Trouble", - :rules_text => "When assigning this Condition, roll the spellcasting dicepool again. The number of successes + 1 will be referred to as SS. The Immediate Nimbus of the Mage becomes active for the entire duration of the Arcane Trouble Condition. The mage becomes a bright beacon for any mage with an Active Mage Sight, and Peripheral Mage Sight can sense the mage's presence by rolling Perception + SS.\n\nIf Death was used to cast the spell causing this Condition, the dead and Twilight reject the caster, making his every step very heavy, as if he was bound in a dense fog. The mage and everyone in the same scene subtracts SS from the dice pools of all action that have an impact on the Underworld and on ghosts or Twilight. In addition, any ghost can temporarily use the Mage as his Anchor.\n\nIf Fate was used to cast the spell causing this Condition, then once per scene, the Storyteller can give give SS as a penalty to any action near the mage. Also, once for the Condition duration, the Storyteller can turn any mage action into a dramatic failure. This dramatic failure cannot be used to cause another Arcane Trouble.\n\nIf Forces was used to cast the spell causing this Condition, then electronics go crazy around the mage. Subtract SS from the equipment bonuses of any equipment near the Mage, which includes most modern machines. If the equipment bonus is reduced to zero or less, the equipment refuses to work in the presence of the mage. In addition, if the Mage uses an electronic device, the Storyteller may roll Forces + Gnosis - Durability, where each success deals a point of damage to the object's Structure.\n\nIf Life was used to cast the spell causing this Condition, then the mage radiates an aura of weakness and vulnerability. The mage and everyone in the scene subtracts SS from all Strength, Dexterity, and Stamina rolls. Any attempts to poison or infect the mage receive a bonus equal to SS instead of the penalty listed.\n\nIf Matter was used to cast the spell causing this Condition, then objects become brittle and unreliable around the mage. The mage and everyone in the scene subtracts SS from the equipment bonuses of anything containing mechanical parts, including most modern machines and weapons like guns. If the equipment bonus is reduced to zero or less, the equipment refuses to work in the presence of the mage. In addition, the Storyteller may at any time roll Matter + Gnosis - Durability, where each success deals a point of damage to the object's Structure.\n\nIf Mind was used to cast the spell causing this Condition, then the mage radiates an aura of mental noise that interferes with concentration around him. The magician and everyone in the scene subtracts SS from all rolls that use Intelligence, Wits, or Resolve. Any attempt to confuse the mind of the mage or prevent his concentration will receive a bonus equal to SS instead of the penalty listed.\n\nIf Prime was used to cast the spell causing this Condition, then the Mage Sight of the mage is disrupted: instead of seeing Supernal Truths, it gives a meaningless stream of symbols. The mage and everyone in the same scene subtracts SS from attempts to use Mage Sight. They also receive the same penalty for any attempts to use the Practice of Knowing or Unveiling of any Arcana.\n\nIf Spirit was used to cast the spell causing this Condition, then the Gauntlet between the Shadow and the mortal world becomes especially thin around the magician, and this attracts the attention of the spirits. Any attempts by spirits to break through the Gauntlet or use Numina through the Gauntlet will receive a bonus equal to SS. Also, any place in which the mage is located receives an Open Condition for all spirits to use.\n\nIf Space was used to cast the spell causing this Condition, then strangely distort the space around the mage. The mage and everyone in the same scene deducts SS from any attempts to find something or get somewhere. Also, Storyteller can once per Condition duration strengthen or weaken any sympathetic mage connection Withstand by SS.\n\nIf Time was used to cast the spell causing this Condition, then make the sense of time jump strangely around the mage, making it difficult to coordinate any effort and not allowing people to concentrate. The mage and everyone in the same scene receive a penalty equal to SS for all extended actions, including ritual casting. Also, the mage subtracts SS from any successes gained in teamwork rolls.\n\nIf the spell that caused this Condition was conjunctional or combined, use the effects of all Arcana used for the spell. For example, if a spell used both Life and Spirit, then he would both attract the negative attention of spirits as described above and have the mentioned sense of illness and tiredness.", - :possible_sources => "Dramatic failure on a spellcasting roll.", - :resolution => "Successfully cast a spell that uses all Arcana creating this Condition, after waiting one day or one chapter, whichever is longer.", - :authors => ["Dark Archon", "NEETzsche"] - ) + conditions << Condition.new( + :name => "Arcane Trouble", + :rules_text => "When assigning this Condition, roll the spellcasting dicepool again. The number of successes + 1 will be referred to as SS. The Immediate Nimbus of the Mage becomes active for the entire duration of the Arcane Trouble Condition. The mage becomes a bright beacon for any mage with an Active Mage Sight, and Peripheral Mage Sight can sense the mage's presence by rolling Perception + SS.\n\nIf Death was used to cast the spell causing this Condition, the dead and Twilight reject the caster, making his every step very heavy, as if he was bound in a dense fog. The mage and everyone in the same scene subtracts SS from the dice pools of all action that have an impact on the Underworld and on ghosts or Twilight. In addition, any ghost can temporarily use the Mage as his Anchor.\n\nIf Fate was used to cast the spell causing this Condition, then once per scene, the Storyteller can give give SS as a penalty to any action near the mage. Also, once for the Condition duration, the Storyteller can turn any mage action into a dramatic failure. This dramatic failure cannot be used to cause another Arcane Trouble.\n\nIf Forces was used to cast the spell causing this Condition, then electronics go crazy around the mage. Subtract SS from the equipment bonuses of any equipment near the Mage, which includes most modern machines. If the equipment bonus is reduced to zero or less, the equipment refuses to work in the presence of the mage. In addition, if the Mage uses an electronic device, the Storyteller may roll Forces + Gnosis - Durability, where each success deals a point of damage to the object's Structure.\n\nIf Life was used to cast the spell causing this Condition, then the mage radiates an aura of weakness and vulnerability. The mage and everyone in the scene subtracts SS from all Strength, Dexterity, and Stamina rolls. Any attempts to poison or infect the mage receive a bonus equal to SS instead of the penalty listed.\n\nIf Matter was used to cast the spell causing this Condition, then objects become brittle and unreliable around the mage. The mage and everyone in the scene subtracts SS from the equipment bonuses of anything containing mechanical parts, including most modern machines and weapons like guns. If the equipment bonus is reduced to zero or less, the equipment refuses to work in the presence of the mage. In addition, the Storyteller may at any time roll Matter + Gnosis - Durability, where each success deals a point of damage to the object's Structure.\n\nIf Mind was used to cast the spell causing this Condition, then the mage radiates an aura of mental noise that interferes with concentration around him. The magician and everyone in the scene subtracts SS from all rolls that use Intelligence, Wits, or Resolve. Any attempt to confuse the mind of the mage or prevent his concentration will receive a bonus equal to SS instead of the penalty listed.\n\nIf Prime was used to cast the spell causing this Condition, then the Mage Sight of the mage is disrupted: instead of seeing Supernal Truths, it gives a meaningless stream of symbols. The mage and everyone in the same scene subtracts SS from attempts to use Mage Sight. They also receive the same penalty for any attempts to use the Practice of Knowing or Unveiling of any Arcana.\n\nIf Spirit was used to cast the spell causing this Condition, then the Gauntlet between the Shadow and the mortal world becomes especially thin around the magician, and this attracts the attention of the spirits. Any attempts by spirits to break through the Gauntlet or use Numina through the Gauntlet will receive a bonus equal to SS. Also, any place in which the mage is located receives an Open Condition for all spirits to use.\n\nIf Space was used to cast the spell causing this Condition, then strangely distort the space around the mage. The mage and everyone in the same scene deducts SS from any attempts to find something or get somewhere. Also, Storyteller can once per Condition duration strengthen or weaken any sympathetic mage connection Withstand by SS.\n\nIf Time was used to cast the spell causing this Condition, then make the sense of time jump strangely around the mage, making it difficult to coordinate any effort and not allowing people to concentrate. The mage and everyone in the same scene receive a penalty equal to SS for all extended actions, including ritual casting. Also, the mage subtracts SS from any successes gained in teamwork rolls.\n\nIf the spell that caused this Condition was conjunctional or combined, use the effects of all Arcana used for the spell. For example, if a spell used both Life and Spirit, then he would both attract the negative attention of spirits as described above and have the mentioned sense of illness and tiredness.", + :possible_sources => "Dramatic failure on a spellcasting roll.", + :resolution => "Successfully cast a spell that uses all Arcana creating this Condition, after waiting one day or one chapter, whichever is longer.", + :authors => ["Dark Archon", "NEETzsche"] + ) - conditions << Condition.new( - :name => "Abyssal Burn", - :rules_text => "The Abyss burns Mana from the character every time he invokes the energies of the Supernal. Any attempt to cast a spell burns an amount of Mana equal to the number of successes on the Paradox roll in excess of the successes the Wisdom roll to absorb it.", - :possible_sources => "Successes on contained Paradox roll.", - :resolution => "Reduce one's Mana pool to zero.", - :authors => ["Dark Archon"] - ) + conditions << Condition.new( + :name => "Abyssal Burn", + :rules_text => "The Abyss burns Mana from the character every time he invokes the energies of the Supernal. Any attempt to cast a spell burns an amount of Mana equal to the number of successes on the Paradox roll in excess of the successes the Wisdom roll to absorb it.", + :possible_sources => "Successes on contained Paradox roll.", + :resolution => "Reduce one's Mana pool to zero.", + :authors => ["Dark Archon"] + ) - conditions - end + conditions + end end \ No newline at end of file diff --git a/primitive_adds.rb b/primitive_adds.rb index 80a6362..900d02f 100644 --- a/primitive_adds.rb +++ b/primitive_adds.rb @@ -1,16 +1,16 @@ class String PUNCTUATION_MARKS = [".", "!", "?"] - def titleize - gsub(/\w+/i) do |match| - ret = match.downcase - ret[0] = ret[0].upcase - ret - end - end + def titleize + gsub(/\w+/i) do |match| + ret = match.downcase + ret[0] = ret[0].upcase + ret + end + end - def titleize! - replace titleize - end + def titleize! + replace titleize + end def punctuated? PUNCTUATION_MARKS.include?(self[-1]) @@ -22,26 +22,26 @@ class String end class Integer - def to_dots - "•" * self - end + def to_dots + "•" * self + end end class Array - def to_list(separator: nil) + def to_list(separator: nil) separator = "and" if separator.nil? - if self.length == 0 - nil - elsif self.length == 1 - self.first - elsif self.length == 2 - "#{self.first} #{separator} #{self.last}" - else - ret = clone - ret[ret.length - 1] = "#{separator} #{ret[ret.length - 1]}" - ret.join(", ") - end - end + if self.length == 0 + nil + elsif self.length == 1 + self.first + elsif self.length == 2 + "#{self.first} #{separator} #{self.last}" + else + ret = clone + ret[ret.length - 1] = "#{separator} #{ret[ret.length - 1]}" + ret.join(", ") + end + end def to_arcanum_with_dots "#{self[0].to_s.titleize} #{self[1].to_dots}" diff --git a/shards_of_power.rb b/shards_of_power.rb index 7907b40..e1a2ca4 100644 --- a/shards_of_power.rb +++ b/shards_of_power.rb @@ -16,346 +16,346 @@ require_relative "primitive_adds" puts "Shards of Power PDF generator" class ShardsOfPower - FONT_SIZE_CHAPTER = 48 - FONT_SIZE_SECTION = 24 - FONT_SIZE_SUBSECTION = 18 - FONT_SIZE_BODY = 10 - - attr_accessor :pdf, :number_name, :chapter_name, :chapter_title, :section_name, :spells, :conditions, :tilts - - def start_chapter(num, name) - @number_name = num - @chapter_name = name - - @chapter_title = "Chapter #{number_name}: #{chapter_name}" - puts "Starting #{chapter_title}" - - pdf.start_new_page - - pdf.outline.update do - puts "\tAdding #{@shards_of_power.chapter_title} on page #{page_number}" - section(@shards_of_power.chapter_title, :destination => page_number) - end - - puts "\tSetting font size" - pdf.font_size FONT_SIZE_CHAPTER - pdf.font "Abess" - puts "\tPrinting chapter to document" - pdf.text "Chapter #{number_name}: #{chapter_name}", :align => :center - - puts "\tRestoring body text" - pdf.font "Goudy" - pdf.font_size FONT_SIZE_BODY - end - - def start_section(section_name) - puts "Beginning section #{section_name}: " - - @section_name = section_name - - pdf.outline.add_subsection_to(chapter_title) do - @pdf.outline.section section_name, :destination => @pdf.page_number - end - - puts "\tSetting font size" - pdf.font_size FONT_SIZE_SECTION - pdf.text section_name, :align => :center - - puts "\tRestoring body text" - pdf.font_size FONT_SIZE_BODY - pdf.font "Goudy" - - end - - def roll_results(dramatic_failure:, failure:, success:, exceptional_success:) - pdf.font_size FONT_SIZE_BODY - pdf.font "Goudy" - - pdf.text "Roll Results", :style => :bold - - pdf.formatted_text [ - { :text => "Dramatic Failure: ", :styles => [:bold] }, - { :text => dramatic_failure } - ] - - pdf.formatted_text [ - { :text => "Failure: ", :styles => [:bold] }, - { :text => failure } - ] - - pdf.formatted_text [ - { :text => "Success: ", :styles => [:bold] }, - { :text => success } - ] - - pdf.formatted_text [ - { :text => "Exceptional Success: ", :styles => [:bold] }, - { :text => exceptional_success } - ] - end - - def generate - puts "Parsing spells..." - @spells = Spell.spells - @conditions = Condition.conditions - @conditions.sort_by!(&:name) - @tilts = Tilt.tilts - @tilts.sort_by!(&:name) - - puts "Creating PDF object..." - @pdf = Prawn::Document.new(:margin => 0) - pdf.default_leading 5 - - pdf.font_families.update( - "Goudy" => { - :normal => "goudy.ttf", - :bold => "goudy-bold.ttf", - :italic => "goudy-italic.ttf" - }, - "Abess" => { - :normal => "abess.ttf" - }, - "Lilith" => { - :normal => "lilith.ttf" - }, - "Goblin Hand" => { - :normal => "VTCGoblinHand.ttf", - :bold => "VTCGoblinHandBold.ttf", - :italic => "VTCGoblinHandItalic.ttf" - } - ) - - pdf.outline.instance_variable_set(:@shards_of_power, self) - - puts "Importing cover..." - pdf.image("cover.png", :width => 612, :height => 792) - - puts "Printing inner cover..." - pdf.start_new_page(:margin => 50) - - pdf.font "Abess" - pdf.font_size 72 - pdf.text "Shards of Power", :align => :center - puts "\tShards of Power big text..." - - pdf.font "Goudy" - pdf.font_size 36 - pdf.text "\nA compendium of spells, Conditions, Artifacts, and other interesting tidbits for Mage: the Awakening\n\n", :align => :center - puts "\tDescription..." - - pdf.font_size 24 - pdf.text "Written by members of the /cofd/ Discord, edited by NEETzsche", :align => :center - puts "\tMain credit..." - - pdf.outline.define do - end - - start_chapter "One", "Introduction" - - pdf.column_box([0, pdf.cursor], :columns => 2, :width => pdf.bounds.width) do - 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\nMage: the Awakening 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 - - start_section "Tools Of Awakened Life" - - 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 Cx3JBpB.", :inline_format => true - - start_section "Chapters" - - pdf.text "There are multiple chapters in this book. Each of them covers a specific set of topics.\n\nChapter One 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\nChapter Two 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.\n\nChapter Three: Conditions & Tilts discusses new Conditions and Tilts that can be imposed by spells, or by other means, such as dramatic failures.", :inline_format => true - - start_section "Credits" - - spell_authors = spells.collect { |spell| spell.authors }.flatten.uniq.sort { |a, b| b.downcase <=> a.downcase } - - pdf.text "The following users have contributed to Shards of Power, in alphabetical order: #{spell_authors.to_list}" - end - - start_chapter("Two", "Spells") - - spells.group_by(&:primary_arcanum).sort_by { |arcanum, spells| arcanum }.to_h.each do |arcanum, arcanum_spells| - arcanum_name = arcanum.to_s.titleize - - puts "Compiling spells for #{arcanum_name}..." - - start_section("#{arcanum_name} Spells") - - pdf.column_box([0, pdf.cursor], :columns => 2, :width => pdf.bounds.width) do - arcanum_spells.group_by(&arcanum).sort_by { |rating, spells| rating }.to_h.each do |rating, rating_spells| - rating_title = "#{rating.to_dots} #{Spell::RANKS[rating - 1]} of #{arcanum_name}" - puts "\tCompiling #{rating_title} spells..." - pdf.outline.add_subsection_to("#{arcanum_name} Spells") do - @pdf.outline.section rating_title, :destination => @pdf.page_number - end - - rating_spells.sort_by! { |spell| spell.name } - - rating_spells.each do |spell| - puts "\t\tCompiling #{spell.full_title} by #{spell.authors.join(', ')}" - pdf.outline.add_subsection_to(rating_title) do - @pdf.outline.section spell.full_title, :destination => @pdf.page_number - end - pdf.group do |g| - if spell == rating_spells.first - g.font_size FONT_SIZE_SECTION - g.text rating_title - end - - spell_ary = [{:text => "#{spell.name} (", :font => "Lilith", :color => "004E6D", :size => FONT_SIZE_SUBSECTION}] - - g.font_size FONT_SIZE_BODY - previous = false - spell.arcana.each do |arcanum| - spell_ary << {:text => ", ", :font => "Lilith", :color => "004E6D", :size => FONT_SIZE_SUBSECTION} if previous - spell_ary << {:text => arcanum.to_s.titleize, :font => "Lilith", :color => "004E6D", :size => FONT_SIZE_SUBSECTION} - spell_ary << {:text => spell.send(arcanum).to_dots, :color => "004E6D", :size => FONT_SIZE_SUBSECTION, :character_spacing => -5} - - previous = true - end - - spell_ary << {:text => " )", :font => "Lilith", :styles => [], :color => "004E6D", :size => FONT_SIZE_SUBSECTION, :character_spacing => -3} - - g.formatted_text spell_ary - - g.formatted_text [ - {:text => "Practice: ", :styles => [:bold], :font => "Goudy"}, - {:text => spell.practice, :font => "Goudy"}, - ] - - g.formatted_text [ - {:text => "Primary Factor: ", :styles => [:bold], :font => "Goudy"}, - {:text => spell.primary_factor, :font => "Goudy"}, - ] - - g.formatted_text [ - {:text => "Withstand: ", :styles => [:bold], :font => "Goudy"}, - {:text => spell.withstand, :font => "Goudy"}, - ] if !spell.withstand.nil? - - g.formatted_text [ - {:text => "Cost: ", :styles => [:bold], :font => "Goudy"}, - {:text => spell.cost, :font => "Goudy"}, - ] if !spell.cost.nil? - - g.formatted_text [ - {:text => "Suggested Rote Skills: ", :styles => [:bold], :font => "Goudy"}, - {:text => spell.suggested_rote_skills.join(', '), :font => "Goudy"}, - ] - - g.formatted_text [ - {:text => spell.authors.length == 1 ? "Author: " : "Authors: ", :styles => [:bold], :font => "Goudy"}, - {:text => spell.authors.join(', '), :font => "Goudy"}, - ] - - g.text spell.rules_text, :inline_format => true - - spell.reaches.each do |reach| - reach_cost = mana_cost = reach_rules = nil - if reach.size == 3 - g.formatted_text [ - {:text => "+#{reach[0]} Reach, #{reach[1]} Mana: ", :styles => [:bold], :font => "Goudy"}, - {:text => reach[2], :font => "Goudy"}, - ] - else - g.formatted_text [ - {:text => "+#{reach[0]} Reach: ", :styles => [:bold], :font => "Goudy"}, - {:text => reach[1], :font => "Goudy"}, - ] - end - end - - spell.adds.each do |add| - g.formatted_text [ - {: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"}, - {:text => add[:effect], :font => "Goudy"}, - ] - end - end - end - end - end - - pdf.start_new_page - end - - start_chapter "Three", "Conditions & Tilts" - - start_section "Conditions" - - puts "Compiling Conditions..." - - pdf.column_box([0, pdf.cursor], :columns => 2, :width => pdf.bounds.width) do - conditions.each do |condition| - puts "\tCompiling #{condition.name}..." - pdf.outline.add_subsection_to("Conditions") do - @pdf.outline.section condition.name, :destination => @pdf.page_number - end - - pdf.image "conditionbox.png", :position => :center - pdf.move_up 30 - - pdf.font "Goblin Hand" - pdf.font_size FONT_SIZE_SUBSECTION - pdf.fill_color "FFFFFF" - pdf.text condition.name, :align => :center - - pdf.move_down 10 - pdf.font "Goudy" - pdf.fill_color "000000" - pdf.font_size FONT_SIZE_BODY - - pdf.text condition.rules_text, :inline_format => true - pdf.text "Possible Sources: #{condition.possible_sources}", :inline_format => true if condition.possible_sources - pdf.text "Resolution: #{condition.resolution}", :inline_format => true - pdf.text "Beat: #{condition.beat}", :inline_format => true - pdf.text "#{condition.authors.size > 1 ? "Authors" : "Author"}: #{condition.authors.to_list}", :inline_format => true - - end - end - - start_section "Tilts" - - puts "Compiling Tilts..." - - pdf.column_box([0, pdf.cursor], :columns => 2, :width => pdf.bounds.width) do - tilts.each do |tilt| - puts "\tCompiling #{tilt.full_title}..." - pdf.outline.add_subsection_to("Tilts") do - @pdf.outline.section tilt.full_title, :destination => @pdf.page_number - end - - pdf.image "conditionbox.png", :position => :center - - pdf.font "Goblin Hand" - pdf.fill_color "FFFFFF" - pdf.font_size FONT_SIZE_SUBSECTION - if tilt.environmental? - pdf.move_up 35 - pdf.text tilt.name, :align => :center - pdf.font_size FONT_SIZE_BODY - pdf.text "(Environmental)", :align => :center - else - pdf.move_up 30 - pdf.text tilt.name, :align => :center - end - - - - pdf.move_down 10 - pdf.font "Goudy" - pdf.fill_color "000000" - pdf.font_size FONT_SIZE_BODY - - pdf.text tilt.rules_text, :inline_format => true - pdf.text "Effect: #{tilt.effect}", :inline_format => true - pdf.text "Causing the Tilt: #{tilt.causing}", :inline_format => true - pdf.text "Ending the Tilt: #{tilt.ending}", :inline_format => true - pdf.text "#{tilt.authors.size > 1 ? "Authors" : "Author"}: #{tilt.authors.to_list}", :inline_format => true - - end - end - - pdf.render_file("shards_of_power.pdf") - end + FONT_SIZE_CHAPTER = 48 + FONT_SIZE_SECTION = 24 + FONT_SIZE_SUBSECTION = 18 + FONT_SIZE_BODY = 10 + + attr_accessor :pdf, :number_name, :chapter_name, :chapter_title, :section_name, :spells, :conditions, :tilts + + def start_chapter(num, name) + @number_name = num + @chapter_name = name + + @chapter_title = "Chapter #{number_name}: #{chapter_name}" + puts "Starting #{chapter_title}" + + pdf.start_new_page + + pdf.outline.update do + puts "\tAdding #{@shards_of_power.chapter_title} on page #{page_number}" + section(@shards_of_power.chapter_title, :destination => page_number) + end + + puts "\tSetting font size" + pdf.font_size FONT_SIZE_CHAPTER + pdf.font "Abess" + puts "\tPrinting chapter to document" + pdf.text "Chapter #{number_name}: #{chapter_name}", :align => :center + + puts "\tRestoring body text" + pdf.font "Goudy" + pdf.font_size FONT_SIZE_BODY + end + + def start_section(section_name) + puts "Beginning section #{section_name}: " + + @section_name = section_name + + pdf.outline.add_subsection_to(chapter_title) do + @pdf.outline.section section_name, :destination => @pdf.page_number + end + + puts "\tSetting font size" + pdf.font_size FONT_SIZE_SECTION + pdf.text section_name, :align => :center + + puts "\tRestoring body text" + pdf.font_size FONT_SIZE_BODY + pdf.font "Goudy" + + end + + def roll_results(dramatic_failure:, failure:, success:, exceptional_success:) + pdf.font_size FONT_SIZE_BODY + pdf.font "Goudy" + + pdf.text "Roll Results", :style => :bold + + pdf.formatted_text [ + { :text => "Dramatic Failure: ", :styles => [:bold] }, + { :text => dramatic_failure } + ] + + pdf.formatted_text [ + { :text => "Failure: ", :styles => [:bold] }, + { :text => failure } + ] + + pdf.formatted_text [ + { :text => "Success: ", :styles => [:bold] }, + { :text => success } + ] + + pdf.formatted_text [ + { :text => "Exceptional Success: ", :styles => [:bold] }, + { :text => exceptional_success } + ] + end + + def generate + puts "Parsing spells..." + @spells = Spell.spells + @conditions = Condition.conditions + @conditions.sort_by!(&:name) + @tilts = Tilt.tilts + @tilts.sort_by!(&:name) + + puts "Creating PDF object..." + @pdf = Prawn::Document.new(:margin => 0) + pdf.default_leading 5 + + pdf.font_families.update( + "Goudy" => { + :normal => "goudy.ttf", + :bold => "goudy-bold.ttf", + :italic => "goudy-italic.ttf" + }, + "Abess" => { + :normal => "abess.ttf" + }, + "Lilith" => { + :normal => "lilith.ttf" + }, + "Goblin Hand" => { + :normal => "VTCGoblinHand.ttf", + :bold => "VTCGoblinHandBold.ttf", + :italic => "VTCGoblinHandItalic.ttf" + } + ) + + pdf.outline.instance_variable_set(:@shards_of_power, self) + + puts "Importing cover..." + pdf.image("cover.png", :width => 612, :height => 792) + + puts "Printing inner cover..." + pdf.start_new_page(:margin => 50) + + pdf.font "Abess" + pdf.font_size 72 + pdf.text "Shards of Power", :align => :center + puts "\tShards of Power big text..." + + pdf.font "Goudy" + pdf.font_size 36 + pdf.text "\nA compendium of spells, Conditions, Artifacts, and other interesting tidbits for Mage: the Awakening\n\n", :align => :center + puts "\tDescription..." + + pdf.font_size 24 + pdf.text "Written by members of the /cofd/ Discord, edited by NEETzsche", :align => :center + puts "\tMain credit..." + + pdf.outline.define do + end + + start_chapter "One", "Introduction" + + pdf.column_box([0, pdf.cursor], :columns => 2, :width => pdf.bounds.width) do + 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\nMage: the Awakening 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 + + start_section "Tools Of Awakened Life" + + 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 Cx3JBpB.", :inline_format => true + + start_section "Chapters" + + pdf.text "There are multiple chapters in this book. Each of them covers a specific set of topics.\n\nChapter One 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\nChapter Two 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.\n\nChapter Three: Conditions & Tilts discusses new Conditions and Tilts that can be imposed by spells, or by other means, such as dramatic failures.", :inline_format => true + + start_section "Credits" + + spell_authors = spells.collect { |spell| spell.authors }.flatten.uniq.sort { |a, b| b.downcase <=> a.downcase } + + pdf.text "The following users have contributed to Shards of Power, in alphabetical order: #{spell_authors.to_list}" + end + + start_chapter("Two", "Spells") + + spells.group_by(&:primary_arcanum).sort_by { |arcanum, spells| arcanum }.to_h.each do |arcanum, arcanum_spells| + arcanum_name = arcanum.to_s.titleize + + puts "Compiling spells for #{arcanum_name}..." + + start_section("#{arcanum_name} Spells") + + pdf.column_box([0, pdf.cursor], :columns => 2, :width => pdf.bounds.width) do + arcanum_spells.group_by(&arcanum).sort_by { |rating, spells| rating }.to_h.each do |rating, rating_spells| + rating_title = "#{rating.to_dots} #{Spell::RANKS[rating - 1]} of #{arcanum_name}" + puts "\tCompiling #{rating_title} spells..." + pdf.outline.add_subsection_to("#{arcanum_name} Spells") do + @pdf.outline.section rating_title, :destination => @pdf.page_number + end + + rating_spells.sort_by! { |spell| spell.name } + + rating_spells.each do |spell| + puts "\t\tCompiling #{spell.full_title} by #{spell.authors.join(', ')}" + pdf.outline.add_subsection_to(rating_title) do + @pdf.outline.section spell.full_title, :destination => @pdf.page_number + end + pdf.group do |g| + if spell == rating_spells.first + g.font_size FONT_SIZE_SECTION + g.text rating_title + end + + spell_ary = [{:text => "#{spell.name} (", :font => "Lilith", :color => "004E6D", :size => FONT_SIZE_SUBSECTION}] + + g.font_size FONT_SIZE_BODY + previous = false + spell.arcana.each do |arcanum| + spell_ary << {:text => ", ", :font => "Lilith", :color => "004E6D", :size => FONT_SIZE_SUBSECTION} if previous + spell_ary << {:text => arcanum.to_s.titleize, :font => "Lilith", :color => "004E6D", :size => FONT_SIZE_SUBSECTION} + spell_ary << {:text => spell.send(arcanum).to_dots, :color => "004E6D", :size => FONT_SIZE_SUBSECTION, :character_spacing => -5} + + previous = true + end + + spell_ary << {:text => " )", :font => "Lilith", :styles => [], :color => "004E6D", :size => FONT_SIZE_SUBSECTION, :character_spacing => -3} + + g.formatted_text spell_ary + + g.formatted_text [ + {:text => "Practice: ", :styles => [:bold], :font => "Goudy"}, + {:text => spell.practice, :font => "Goudy"}, + ] + + g.formatted_text [ + {:text => "Primary Factor: ", :styles => [:bold], :font => "Goudy"}, + {:text => spell.primary_factor, :font => "Goudy"}, + ] + + g.formatted_text [ + {:text => "Withstand: ", :styles => [:bold], :font => "Goudy"}, + {:text => spell.withstand, :font => "Goudy"}, + ] if !spell.withstand.nil? + + g.formatted_text [ + {:text => "Cost: ", :styles => [:bold], :font => "Goudy"}, + {:text => spell.cost, :font => "Goudy"}, + ] if !spell.cost.nil? + + g.formatted_text [ + {:text => "Suggested Rote Skills: ", :styles => [:bold], :font => "Goudy"}, + {:text => spell.suggested_rote_skills.join(', '), :font => "Goudy"}, + ] + + g.formatted_text [ + {:text => spell.authors.length == 1 ? "Author: " : "Authors: ", :styles => [:bold], :font => "Goudy"}, + {:text => spell.authors.join(', '), :font => "Goudy"}, + ] + + g.text spell.rules_text, :inline_format => true + + spell.reaches.each do |reach| + reach_cost = mana_cost = reach_rules = nil + if reach.size == 3 + g.formatted_text [ + {:text => "+#{reach[0]} Reach, #{reach[1]} Mana: ", :styles => [:bold], :font => "Goudy"}, + {:text => reach[2], :font => "Goudy"}, + ] + else + g.formatted_text [ + {:text => "+#{reach[0]} Reach: ", :styles => [:bold], :font => "Goudy"}, + {:text => reach[1], :font => "Goudy"}, + ] + end + end + + spell.adds.each do |add| + g.formatted_text [ + {: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"}, + {:text => add[:effect], :font => "Goudy"}, + ] + end + end + end + end + end + + pdf.start_new_page + end + + start_chapter "Three", "Conditions & Tilts" + + start_section "Conditions" + + puts "Compiling Conditions..." + + pdf.column_box([0, pdf.cursor], :columns => 2, :width => pdf.bounds.width) do + conditions.each do |condition| + puts "\tCompiling #{condition.name}..." + pdf.outline.add_subsection_to("Conditions") do + @pdf.outline.section condition.name, :destination => @pdf.page_number + end + + pdf.image "conditionbox.png", :position => :center + pdf.move_up 30 + + pdf.font "Goblin Hand" + pdf.font_size FONT_SIZE_SUBSECTION + pdf.fill_color "FFFFFF" + pdf.text condition.name, :align => :center + + pdf.move_down 10 + pdf.font "Goudy" + pdf.fill_color "000000" + pdf.font_size FONT_SIZE_BODY + + pdf.text condition.rules_text, :inline_format => true + pdf.text "Possible Sources: #{condition.possible_sources}", :inline_format => true if condition.possible_sources + pdf.text "Resolution: #{condition.resolution}", :inline_format => true + pdf.text "Beat: #{condition.beat}", :inline_format => true + pdf.text "#{condition.authors.size > 1 ? "Authors" : "Author"}: #{condition.authors.to_list}", :inline_format => true + + end + end + + start_section "Tilts" + + puts "Compiling Tilts..." + + pdf.column_box([0, pdf.cursor], :columns => 2, :width => pdf.bounds.width) do + tilts.each do |tilt| + puts "\tCompiling #{tilt.full_title}..." + pdf.outline.add_subsection_to("Tilts") do + @pdf.outline.section tilt.full_title, :destination => @pdf.page_number + end + + pdf.image "conditionbox.png", :position => :center + + pdf.font "Goblin Hand" + pdf.fill_color "FFFFFF" + pdf.font_size FONT_SIZE_SUBSECTION + if tilt.environmental? + pdf.move_up 35 + pdf.text tilt.name, :align => :center + pdf.font_size FONT_SIZE_BODY + pdf.text "(Environmental)", :align => :center + else + pdf.move_up 30 + pdf.text tilt.name, :align => :center + end + + + + pdf.move_down 10 + pdf.font "Goudy" + pdf.fill_color "000000" + pdf.font_size FONT_SIZE_BODY + + pdf.text tilt.rules_text, :inline_format => true + pdf.text "Effect: #{tilt.effect}", :inline_format => true + pdf.text "Causing the Tilt: #{tilt.causing}", :inline_format => true + pdf.text "Ending the Tilt: #{tilt.ending}", :inline_format => true + pdf.text "#{tilt.authors.size > 1 ? "Authors" : "Author"}: #{tilt.authors.to_list}", :inline_format => true + + end + end + + pdf.render_file("shards_of_power.pdf") + end end shards_of_power = ShardsOfPower.new diff --git a/spell.rb b/spell.rb index 4247183..d7cabcb 100644 --- a/spell.rb +++ b/spell.rb @@ -1,83 +1,83 @@ class Spell - ARCANA = [:death, :fate, :forces, :life, :matter, :mind, :prime, :space, :spirit, :time] - RANKS = ["Initiate", "Apprentice", "Disciple", "Adept", "Master"] - ARCANA.each do |arcanum| - attr_accessor arcanum - end + ARCANA = [:death, :fate, :forces, :life, :matter, :mind, :prime, :space, :spirit, :time] + RANKS = ["Initiate", "Apprentice", "Disciple", "Adept", "Master"] + ARCANA.each do |arcanum| + attr_accessor arcanum + end - attr_accessor :name, - :practice, - :primary_factor, - :withstand, - :suggested_rote_skills, - :reaches, - :adds, - :rules_text, - :cost + attr_accessor :name, + :practice, + :primary_factor, + :withstand, + :suggested_rote_skills, + :reaches, + :adds, + :rules_text, + :cost - attr_accessor :authors + attr_accessor :authors - def initialize( - death: 0, - fate: 0, - forces: 0, - life: 0, - matter: 0, - mind: 0, - prime: 0, - space: 0, - spirit: 0, - time: 0, - name:, - practice:, - primary_factor:, - withstand: nil, - suggested_rote_skills:, - reaches: [], - rules_text:, - authors:, - adds: [], - cost: nil) + def initialize( + death: 0, + fate: 0, + forces: 0, + life: 0, + matter: 0, + mind: 0, + prime: 0, + space: 0, + spirit: 0, + time: 0, + name:, + practice:, + primary_factor:, + withstand: nil, + suggested_rote_skills:, + reaches: [], + rules_text:, + authors:, + adds: [], + cost: nil) - @death = death - @fate = fate - @forces = forces - @life = life - @matter = matter - @mind = mind - @prime = prime - @space = space - @spirit = spirit - @time = time - @name = name - @practice = practice - @primary_factor = primary_factor - @withstand = withstand - @suggested_rote_skills = suggested_rote_skills - @reaches = reaches - @rules_text = rules_text - @authors = authors - @adds = adds - @cost = cost - end + @death = death + @fate = fate + @forces = forces + @life = life + @matter = matter + @mind = mind + @prime = prime + @space = space + @spirit = spirit + @time = time + @name = name + @practice = practice + @primary_factor = primary_factor + @withstand = withstand + @suggested_rote_skills = suggested_rote_skills + @reaches = reaches + @rules_text = rules_text + @authors = authors + @adds = adds + @cost = cost + end - def primary_arcanum - ARCANA.max { |arcanum1, arcanum2| self.send(arcanum1) <=> self.send(arcanum2) } - end + def primary_arcanum + ARCANA.max { |arcanum1, arcanum2| self.send(arcanum1) <=> self.send(arcanum2) } + end - def full_title - "#{name} (#{arcana_with_dots.join(', ')})" - end + def full_title + "#{name} (#{arcana_with_dots.join(', ')})" + end - def arcana - ARCANA.select { |arcanum| self.send(arcanum) > 0} - end + def arcana + ARCANA.select { |arcanum| self.send(arcanum) > 0} + end - def arcana_with_dots - arcana.collect { |arcanum| arcanum_with_dots(arcanum) } - end - - def arcanum_with_dots(arcanum) - [arcanum, self.send(arcanum)].to_arcanum_with_dots - end + def arcana_with_dots + arcana.collect { |arcanum| arcanum_with_dots(arcanum) } + end + + def arcanum_with_dots(arcanum) + [arcanum, self.send(arcanum)].to_arcanum_with_dots + end end \ No newline at end of file diff --git a/spells.rb b/spells.rb index 94130e6..169adf3 100644 --- a/spells.rb +++ b/spells.rb @@ -1,6 +1,6 @@ class Spell - def self.spells - spells = [] + def self.spells + spells = [] spells << Spell.new( :name => "Catalysis", @@ -49,20 +49,20 @@ class Spell :rules_text => "The subject gains the ability to \"speak\" with spirits. She usually speaks to it by expressing ideas similar to its own communication form, such as speech, magically generated optical oscillations, or vibrations, but this is not necessary; the subject can speak in her own language and the magic \"translates\" her words for her. This does not grant her any capability to control a Spirit, only to understand and be understood by it. Spirits have an advanced ability to understand things that transpire around them, especially as pertains to humans, but the subject gains a bonus to any Empathy rolls made with that Spirit equal to the spell's Potency. A jaggling may not understand just why the people went into the house across the street last night, for example, but it could give a general estimate of their number and unusual features like being covered in tattoos (“skin patterns”).", ) - spells << Spell.new( - :name => "Marionette", - :life => 2, - :practice => "Ruling", - :primary_factor => "Duration", - :withstand => "Resolve", - :suggested_rote_skills => ["Medicine", "Athletics", "Expression"], - :authors => ["Dark Archon"], - :rules_text => "The Shaman can control the body of a mundane living thing. At the base level for the Duration of the spell the shaman can only command base life processes such as sleep, hunger, sweat, lacrimation, etc. Doing so may be obvious magic or an Act of Hubris depending upon the situation.", - :reaches => [ - [1, "Marionette can hijack living supernatural creatures."], - [2, "The shaman takes over direct control over the muscles and nerves of a life form, forcing it to perform whatever physical tasks the Shaman desires for the Duration. If conscious, the subject is fully aware of the fact that their body is acting outside of their control. This may cause Dissonance if the subject is a Sleeper. The willworker cannot have the target perform Social or Mental tasks."] - ] - ) + spells << Spell.new( + :name => "Marionette", + :life => 2, + :practice => "Ruling", + :primary_factor => "Duration", + :withstand => "Resolve", + :suggested_rote_skills => ["Medicine", "Athletics", "Expression"], + :authors => ["Dark Archon"], + :rules_text => "The Shaman can control the body of a mundane living thing. At the base level for the Duration of the spell the shaman can only command base life processes such as sleep, hunger, sweat, lacrimation, etc. Doing so may be obvious magic or an Act of Hubris depending upon the situation.", + :reaches => [ + [1, "Marionette can hijack living supernatural creatures."], + [2, "The shaman takes over direct control over the muscles and nerves of a life form, forcing it to perform whatever physical tasks the Shaman desires for the Duration. If conscious, the subject is fully aware of the fact that their body is acting outside of their control. This may cause Dissonance if the subject is a Sleeper. The willworker cannot have the target perform Social or Mental tasks."] + ] + ) spells << Spell.new( :name => "Opacity", @@ -74,18 +74,18 @@ class Spell :rules_text => "The willworker can make transparent or translucent materials completely opaque. Air becomes completely impossible to see through, windows become solid colors, and bodies of water become too murky to see their non-aquatic contents. If the scale of this spell is an area of effect, any people inside of it suffer the Blinded Tilt." ) - spells << Spell.new( - :name => "It Takes One To Know One", - :death => 1, - :practice => "Unveiling", - :primary_factor => "Duration", - :suggested_rote_skills => ["Medicine", "Survival", "Empathy"], - :authors => ["Dark Archon"], - :rules_text => "Having visited or gazed upon Stygia, Moroi have the most death-like experience outside of actually dying. Being experienced with death and transition, they know how to find the marks that death leaves. For the spell's duration, the caster can measure the amount of contact with the death the target has with a glance. Most people have only a very minor death aura, but a veteran coroner's aura could be startling.", - :reaches => [[1, "The caster can distinguish between those who witnessed death and those who have caused it directly. She can also accurately guess how many people have been killed by the target."]] - ) + spells << Spell.new( + :name => "It Takes One To Know One", + :death => 1, + :practice => "Unveiling", + :primary_factor => "Duration", + :suggested_rote_skills => ["Medicine", "Survival", "Empathy"], + :authors => ["Dark Archon"], + :rules_text => "Having visited or gazed upon Stygia, Moroi have the most death-like experience outside of actually dying. Being experienced with death and transition, they know how to find the marks that death leaves. For the spell's duration, the caster can measure the amount of contact with the death the target has with a glance. Most people have only a very minor death aura, but a veteran coroner's aura could be startling.", + :reaches => [[1, "The caster can distinguish between those who witnessed death and those who have caused it directly. She can also accurately guess how many people have been killed by the target."]] + ) - spells << Spell.new( + spells << Spell.new( :name => "Witch Razor", :forces => 3, :practice => "Weaving", @@ -102,18 +102,18 @@ class Spell ) - spells << Spell.new( + spells << Spell.new( :name => "Grim Grinning Ghost", :death => 3, :practice => "Perfecting", :primary_factor => "Potency", - :withstand => "Rank", + :withstand => "Rank", :suggested_rote_skills => ["Medicine", "Crafts", "Brawl"], :authors => ["Altasaire"], :rules_text => "Older and more traumatic ghosts often warp with time, making the corpus-based implements of their death and weapons they possess more prominent and terrifying. Fingers become claws, teeth become fangs, and threflection of a murdered serial killer’s blade becomes vicious and sharp.\n\nThis spell mimics and bolsters this facet of the ghost-existence, granting it up to Potency extra points of damage rating for its natural attacks for the Duration of the spell.", :reaches => [ - [1, "The Mage adds an additional tag to the ghost's weapon that is fitting to the character of the ghost; a dead bouncer might gain the Stun tag, while a pedophile shade might gain Grapple."], - [1, "The ghost enjoys 9-again on natural attacks."] + [1, "The Mage adds an additional tag to the ghost's weapon that is fitting to the character of the ghost; a dead bouncer might gain the Stun tag, while a pedophile shade might gain Grapple."], + [1, "The ghost enjoys 9-again on natural attacks."] ] ) @@ -128,7 +128,7 @@ class Spell :rules_text => "Sometimes you're about to run out of ammunition and you're out of extra magazines, or maybe you're just short on time to reload the ones you do have. The Adamantine Arrow has run into this exact situation more than a few times. The willworker's firearm reloads automatically as the magazine approaches empty, filling it back up before it fully runs out. Each time it fills up what would have been a full magazine, reduce the Potency of this spell by one." ) - spells << Spell.new( + spells << Spell.new( :name => "Longer Leash", :death => 3, :practice => "Perfecting", @@ -140,7 +140,7 @@ class Spell ) - spells << Spell.new( + spells << Spell.new( :name => "Shut Down", :forces => 2, :practice => "Ruling", @@ -150,7 +150,7 @@ class Spell :rules_text => "This disables a specific targeted electronic device, or all electronic devices within an area of effect. The Scale factor determines how many specific devices may be disabled, or how wide the area of effect is." ) - spells << Spell.new( + spells << Spell.new( :name => "Overclock", :forces => 3, :practice => "Perfecting", @@ -159,12 +159,12 @@ class Spell :authors => ["Altasaire", "NEETzsche"], :rules_text => "Making the silicon heart dance to the tune of the divine fire within, the Mage invigorates the calculating power of a given device. Mechanically, this is represented as improving the equipment bonus of the device by one per Potency.", :reaches => [ - [1, "The Mage also expands the RAM or cache memory, giving it the 9-Again property in addition to its equipment bonus."], + [1, "The Mage also expands the RAM or cache memory, giving it the 9-Again property in addition to its equipment bonus."], [2, "The spell can affect quantum computers and other calculating things of deviant science and hypertech."] ] ) - spells << Spell.new( + spells << Spell.new( :name => "Invoke Doom", :fate => 1, :practice => "Compelling", @@ -175,7 +175,7 @@ class Spell :rules_text => "The fates of some individuals recoil and tear before some things, and this spell forces it to happen in a clear manner.\n\nThis spell forces a person with Destiny to avoid their Doom even more fastidiously than normal. The Destined must spend a point of Willpower to even come within the area of influence of its Doom (described by the Area factor of the spell), and cannot touch it at all. If the fated person is already within the proscribed area and fails the roll, they must flee immediately." ) - spells << Spell.new( + spells << Spell.new( :name => "Cliche-Defying Contempt Aegis", :fate => 2, :practice => "Shielding", @@ -185,7 +185,7 @@ class Spell :rules_text => "The Mage exudes disgust at repeated narrative, denying the majesty of recurring themes and utterly ignoring what he finds distasteful.\n\nThe Mage may employ the aegis to shield against repetitive actions. The same emotional structure, weapon, or event unfolding again during the Duration of this spell is violently repelled – mundane events of this sort levelled at the target outright fail, whereas mystic ones force a Clash of Wills." ) - spells << Spell.new( + spells << Spell.new( :name => "Empty Sapphire Mirror / Empty Ruby Mirror", :mind => 2, :practice => "Shielding", @@ -197,7 +197,7 @@ class Spell ) - spells << Spell.new( + spells << Spell.new( :name => "Shun The Smiling Lady", :mind => 2, :practice => "Veiling", @@ -208,7 +208,7 @@ class Spell :rules_text => "Love is like an ending, no more keenly felt than when it is gone. This spell strikes a target’s name from the rolls of love, veiling any romantic feelings or approaches from his mind. This spell can also be used to veil other emotional states such as anger or fear. Mundane efforts to pierce the veil fail automatically, while supernatural ones provoke a Clash of Wills." ) - spells << Spell.new( + spells << Spell.new( :name => "Stubborn God-Beast Indulgence / The Snake Within", :mind => 3, :practice => "Perfecting", @@ -218,11 +218,11 @@ class Spell :authors => ["Altasaire"], :rules_text => "The next time during this spell's duration that its subject would recover Willpower from indulging their Vice, they recover a number of points equal to the spell's Potency, instead of the usual one. If this value exceeds their Resolve, they will develop a Condition related to the rush of the experience, such as Addicted, Guilty, or Obsession.", :reaches => [ - [1, "For one Mana, the subject may recover Willpower from their vice an additional time during the same scene."] + [1, "For one Mana, the subject may recover Willpower from their vice an additional time during the same scene."] ] ) - spells << Spell.new( + spells << Spell.new( :name => "Stoke the Flame", :mind => 3, :practice => "Perfecting", @@ -231,12 +231,12 @@ class Spell :authors => ["Altasaire"], :rules_text => "Basking in the fires of their Animus and the cool, unstoppable power of their Gnosis, the Mage is reinvigorated. He regains a point of Willpower.", :reaches => [ - [2, "Drawing deeper, more greedily, the Mage emerges a temporarily more perfect and mentally rarified being. They regain, instead, points of Willpower equal to the spell's Potency."] + [2, "Drawing deeper, more greedily, the Mage emerges a temporarily more perfect and mentally rarified being. They regain, instead, points of Willpower equal to the spell's Potency."] ] ) - spells << Spell.new( + spells << Spell.new( :name => "Hyperfocus", :mind => 3, :practice => "Perfecting", @@ -246,11 +246,11 @@ class Spell :authors => ["Altasaire"], :rules_text => "The Mage launches their mind into a state of intense concentration, allowing them to keep track of difficult tasks far beyond what is possible for Sleepers. For each level of Potency, the Mage may exceed the normal number of iterations in extended actions by one.", :reaches => [ - [1, "The heightened focus and clarity, combined with divergent, enhanced thinking, open up thought pathways to quick decisions and better choices. For the Duration, the Mage gains the effects of the Good Time Management merit."] + [1, "The heightened focus and clarity, combined with divergent, enhanced thinking, open up thought pathways to quick decisions and better choices. For the Duration, the Mage gains the effects of the Good Time Management merit."] ] ) - spells << Spell.new( + spells << Spell.new( :name => "Self-As-Goal Redefinition", :mind => 3, :practice => "Perfecting", @@ -260,11 +260,11 @@ class Spell :authors => ["Altasaire"], :rules_text => "Language shapes thought, and thought shapes action. Thus does the Mage whisper proper structure into her half-formed mind.This spell gives the Mage, for the Duration, another Aspiration slot, giving her soul the capacity to encompass more things and particulars of the world.", :adds => [ - {:arcana => { :prime => 2 }, :effect => "For +1 Reach, the Mage may adopt another Obsession instead."} + {:arcana => { :prime => 2 }, :effect => "For +1 Reach, the Mage may adopt another Obsession instead."} ] ) - spells << Spell.new( + spells << Spell.new( :name => "Pyretic Will-Crushing Song", :mind => 3, :practice => "Fraying", @@ -274,11 +274,11 @@ class Spell :authors => ["Altasaire"], :rules_text => "Twisting a burning multifaceted song into the core of the opponent's mind, the Mage attacks their willpower reserves. This spell removes a Willpower point from the target entity's pool per Potency.", :reaches => [ - [1, "The song is sinister and vile. The caster may apply the Shaken or Spooked Condition to the target of the spell."] + [1, "The song is sinister and vile. The caster may apply the Shaken or Spooked Condition to the target of the spell."] ] ) - spells << Spell.new( + spells << Spell.new( :name => "Creation-Carving Blow", :space => 1, :practice => "Knowing", @@ -288,7 +288,7 @@ class Spell :rules_text => "Space is more flexible than many believe. By subtly observing the laws of space around her, the Mage allows her blows to come from angles which are devilishly hard to parry. If employing the ‘Specified Targets’ rule, she may ignore an amount of attack penalties equal to Potency." ) - spells << Spell.new( + spells << Spell.new( :name => "Celestial Atlas", :space => 1, :practice => "Knowing", @@ -297,15 +297,15 @@ class Spell :authors => ["Altasaire"], :rules_text => "The Mage is aware of the direction and his relative position to visible celestial bodies.", :reaches => [ - [1, "The Mage is likewise aware of objects too dim to be seen to the naked eye."] + [1, "The Mage is likewise aware of objects too dim to be seen to the naked eye."] ], :adds => [ - {:arcana => { :forces => 1 }, :effect => "This spell can be used during the day, and in spite of light pollution."}, - {:arcana => { :time => 1 }, :effect => "The Mage also knows the age of the light from different celestial sources."} + {:arcana => { :forces => 1 }, :effect => "This spell can be used during the day, and in spite of light pollution."}, + {:arcana => { :time => 1 }, :effect => "The Mage also knows the age of the light from different celestial sources."} ] ) - spells << Spell.new( + spells << Spell.new( :name => "Iron Chains", :space => 2, :practice => "Shielding", @@ -315,7 +315,7 @@ class Spell :rules_text => "This spell targets a sympathetic connection. As long as the spell endures, this link cannot be altered in strength or quality by mundane events: he'll remain in the friend zone, she'll never Manage to get a divorce, this kid will never get bored of his favorite toy. Alternatively, this spell can be used to prevent a sympathetic connection from forming in the first place. Supernatural attempts to alter the sympathetic connection provoke a Clash of Wills." ) - spells << Spell.new( + spells << Spell.new( :name => "Motion Lock", :space => 2, :practice => "Shielding", @@ -326,7 +326,7 @@ class Spell ) - spells << Spell.new( + spells << Spell.new( :name => "Tunnel Vision", :space => 2, :practice => "Veiling", @@ -340,7 +340,7 @@ class Spell ] ) - spells << Spell.new( + spells << Spell.new( :name => "Accuracy Without Distance", :space => 3, :practice => "Weaving", @@ -349,11 +349,11 @@ class Spell :authors => ["Altasaire"], :rules_text => "Blurring the distinctions between 'far' and 'close', a Mage attacks a target she cannot hope to hit, and impossibly does. For the Duration of the spell a given target is treated as being in point blank range from the Mage. This spell may be combined with the Sympathetic Casting attainment.", :reaches => [ - [2, "The spell, at this level of exertion, becomes anisotropic — the target is in point blank range from the Mage, but the Mage is in their normal range from the target."] + [2, "The spell, at this level of exertion, becomes anisotropic — the target is in point blank range from the Mage, but the Mage is in their normal range from the target."] ] ) - spells << Spell.new( + spells << Spell.new( :name => "Pristine Flowers Splashed Red", :space => 3, :practice => "Weaving", @@ -362,13 +362,13 @@ class Spell :authors => ["Altasaire"], :rules_text => "The Mage warps space around their subject into the shape of a sublime lotus. The blade that follows through strikes from a side an enemy could never expect, angles impossibly twisted. The subject's quarries lose Defense against the melee attacks of the subject for the Duration of the spell.", :reaches => [ - [1, "As above, but it also applies to ranged attacks."], - [1, "The subject may employ the short and medium burst actions in melee, as the world twists so that a single thrust or blade arc meets the flesh of the enemy twice, thrice, or more."], - [2, "As above, but the long burst action is, too, available."] + [1, "As above, but it also applies to ranged attacks."], + [1, "The subject may employ the short and medium burst actions in melee, as the world twists so that a single thrust or blade arc meets the flesh of the enemy twice, thrice, or more."], + [2, "As above, but the long burst action is, too, available."] ] ) - spells << Spell.new( + spells << Spell.new( :name => "Redefine Positionability", :space => 4, :practice => "Patterning", @@ -379,7 +379,7 @@ class Spell :rules_text => "The Mage redefines the “position” quality of a thing, assigning a specific value to it, or excising it from the target’s being. What follows is the target, in principle, not being able to change their position. The phenomenon of “moving”, as in, changing coordinate, or spatial relation to other things, is denied to it." ) - spells << Spell.new( + spells << Spell.new( :name => "Fortress of Arrogance", :prime => 2, :practice => "Shielding", @@ -389,7 +389,7 @@ class Spell :rules_text => "The Mage wraps the subject in symbol-planes and unassailable slopes, making incoming magic slide right off or ricochet harmlessly. Any external Supernal magical effect incoming at the subject provokes a Clash of Wills." ) - spells << Spell.new( + spells << Spell.new( :name => "Ego-Infused Wholeness Embodiment", :prime => 2, :practice => "Shielding", @@ -398,11 +398,11 @@ class Spell :authors => ["Altasaire"], :rules_text => "It is not the place of the Lie to dictate the identity and structure of Truth. Whenever a fully-Abyssal interference effect attempts to alter a target with this spell active, its integrity reasserts itself like an immune system waging war on a plague. Any such attempt to shape her against her will, be it by gulmoth-claw, abyssal Numen, or other vile deviance, provokes a Clash of Wills.", :reaches => [ - [2, "Half-Lying Abyssal interferences (befouled spells and such) are likewise rejected."] + [2, "Half-Lying Abyssal interferences (befouled spells and such) are likewise rejected."] ] ) - spells << Spell.new( + spells << Spell.new( :name => "Ironman", :time => 2, :practice => "Shielding", @@ -412,7 +412,7 @@ class Spell :rules_text => "For the Duration of the spell, any attempt to move back in time over its area of effect or including its subjects is met by a Clash of Wills." ) - spells << Spell.new( + spells << Spell.new( :name => "Time out of Mind", :time => 3, :practice => "Weaving", @@ -421,14 +421,14 @@ class Spell :authors => ["Altasaire"], :rules_text => "Sometimes what you most need is a breather and a moment to think. For the Duration of the spell, the subject may perform any purely mental actions she can imagine. Objectively, this thinking is compressed to a singular moment in time, allowing a Mage to come to conclusions extremely fast. Spells cannot be cast in this period of compressed time.", :reaches => [ - [1, " Extended actions performed under the auspices of this spell have their iteration durations halved."] + [1, " Extended actions performed under the auspices of this spell have their iteration durations halved."] ], :adds => [ - {:arcana => { :mind => 2 }, :effect => "The Mage may employ mental holograms and nirmitas for the subjective duration of the spell, allowing him to manifest in his mental palace the ethereal versions of any mental equipment he might require during his mental toil with equipment bonuses up to Potency."} + {:arcana => { :mind => 2 }, :effect => "The Mage may employ mental holograms and nirmitas for the subjective duration of the spell, allowing him to manifest in his mental palace the ethereal versions of any mental equipment he might require during his mental toil with equipment bonuses up to Potency."} ] ) - spells << Spell.new( + spells << Spell.new( :name => "Thousand Buzzing Wasps / Omae Wa Mo Shindeiru", :time => 3, :practice => "Perfecting", @@ -437,11 +437,11 @@ class Spell :authors => ["Altasaire"], :rules_text => "The Mage's body blurs, his fists impossibly fast. For the duration of the spell, the subject may use the short burst and medium burst maneuvers in melee against targets in their reach.", :reaches => [ - [1, "as above, but the subject may also employ the long burst maneuver."] - ] + [1, "as above, but the subject may also employ the long burst maneuver."] + ] ) - spells << Spell.new( + spells << Spell.new( :name => "Terrifying Argent Witchery", :time => 3, :practice => "Fraying", @@ -451,11 +451,11 @@ class Spell :authors => ["Altasaire"], :rules_text => "The Mage projects an incessant stream of visions of potential bad futures at their target, showing them all ways they and theirs can come to harm, their works crumble, and their ideas die. The subject of the spell gains the Beaten Down Tilt.", :reaches => [ - [1, "For the duration of the spell they may not do any actions or spells in the same manner as the spell \"Post-cognition\”."] - ] + [1, "For the duration of the spell they may not do any actions or spells in the same manner as the spell \"Post-cognition\”."] + ] ) - spells << Spell.new( + spells << Spell.new( :name => "Essense Feast", :spirit => 2, :practice => "Shielding", @@ -464,11 +464,11 @@ class Spell :authors => ["Altasaire"], :rules_text => "The Mage protects a spirit from the mutative power of Essence. For the Duration of the spell the subject spirit will not pick up any new traits from the essence it consumes, neither harmful nor beneficial.", :reaches => [ - [1, "Beneficial traits inside the spirit’s purview and theme are permissible."] - ] + [1, "Beneficial traits inside the spirit’s purview and theme are permissible."] + ] ) - spells << Spell.new( + spells << Spell.new( :name => "Essense Famine", :spirit => 2, :practice => "Veiling", @@ -479,7 +479,7 @@ class Spell :rules_text => "For the Duration of the spell, the afflicted spirit cannot perceive (and thus, willingly consume) sources of Essence external to it and capable of nourishing it. This spell cannot be used on spirits above Rank 5." ) - spells << Spell.new( + spells << Spell.new( :name => "Thornwall", :spirit => 3, :practice => "Weaving", @@ -488,11 +488,11 @@ class Spell :authors => ["Altasaire", "NEETzsche"], :rules_text => "The Mage grows sharp blades and thorns on the Gauntlet, or forces screaming gales to traverse its surface. For the Duration of the spell, anything crossing the Gauntlet suffers the Potency of the spell in bashing damage.", :adds => [ - {:arcana => { :spirit => 4 }, :effect => "It deals lethal damage instead, or with 1 Mana and a Reach, aggravated damage."}, - {:arcana => { :spirit => 5 }, :effect => "It tears them to shreds, immediately killing them. This is Withstood by either Rank or Stamina."}, + {:arcana => { :spirit => 4 }, :effect => "It deals lethal damage instead, or with 1 Mana and a Reach, aggravated damage."}, + {:arcana => { :spirit => 5 }, :effect => "It tears them to shreds, immediately killing them. This is Withstood by either Rank or Stamina."}, ], :reaches => [ - [1, "The willworker may create a Key that allows for safe passage to those who possess it."] + [1, "The willworker may create a Key that allows for safe passage to those who possess it."] ] ) @@ -512,7 +512,7 @@ class Spell ] ) - spells << Spell.new( + spells << Spell.new( :name => "Imperfection-Revealing Diagrams", :matter => 1, :practice => "Knowing", @@ -524,7 +524,7 @@ class Spell ) - spells << Spell.new( + spells << Spell.new( :name => "Irritate", :matter => 3, :practice => "Weaving", @@ -533,12 +533,12 @@ class Spell :authors => ["Altasaire"], :rules_text => "The Mage affects the air (or another gas), granting it the qualities of a battlefield irritant. The air in the affected area becomes a toxin with Toxicity equal to Potency. People without proper gas masks on suffer the Blinded Tilt while in the area and roll Stamina + Resolve – Toxicity or suffer the Toxicity as a penalty on all actions until they are clear of the area.", :reaches => [ - [1, "The affected air is particularly dense and is not displaced from the area significantly by winds or movement."], - [1, "The affected air becomes opaque."] + [1, "The affected air is particularly dense and is not displaced from the area significantly by winds or movement."], + [1, "The affected air becomes opaque."] ] ) - spells << Spell.new( + spells << Spell.new( :name => "Disperse Wounds", :death => 3, :practice => "Perfecting", @@ -547,15 +547,15 @@ class Spell :authors => ["Dark Archon", "21C Hermit"], :rules_text => "The necromancer calls forth entropy, but he may unwind it for those he favors. For each level of Potency, the mage may convert one point of lethal damage the subject suffers into two points of bashing damage. This spell does not work against lethal damage upgraded from accumulated bashing damage, including accumulation from this very spell. So, if a subject with 8 levels of Health had suffered 4 lethal damage, this spell may convert them into 1 lethal damage and 6 bashing damage at Potency 3, or 8 bashing damage at Potency 4. If that same subject had suffered 5 lethal damage instead, even at Potency 5 this spell would still leave him at 2 lethal damage and 6 bashing damage.", :reaches => [ - [1, "The spell instead converts one point of lethal damage into one point of bashing damage per level of Potency."] + [1, "The spell instead converts one point of lethal damage into one point of bashing damage per level of Potency."] ], :adds => [ - { :arcana => { :life => 2 }, :effect => "The spell also heals any Tilts connected to the Health box affected, even if the box is technically uncleared and thus the Tilt should remain."}, - { :arcana => { :time => 2 }, :effect => "The spell may also heal scars and physical Conditions related to the healed wounds. With the Temporal Sympathy Attainment, the spell may force persistent Conditions caused from past injuries into transient Conditions, so that they naturally heal over time." } + { :arcana => { :life => 2 }, :effect => "The spell also heals any Tilts connected to the Health box affected, even if the box is technically uncleared and thus the Tilt should remain."}, + { :arcana => { :time => 2 }, :effect => "The spell may also heal scars and physical Conditions related to the healed wounds. With the Temporal Sympathy Attainment, the spell may force persistent Conditions caused from past injuries into transient Conditions, so that they naturally heal over time." } ] ) - spells << Spell.new( + spells << Spell.new( :name => "Cursed Wounds", :death => 3, :practice => "Perfecting", @@ -564,12 +564,12 @@ class Spell :authors => ["Dark Archon", "21C Hermit", "NEETzsche"], :rules_text => "The necromancer coats a weapon with the venom of Death. For a number of attacks equal to Potency, wounds inflicted by the enchanted weapon are unable to be healed by natural healing or mundane medical attention. This includes any wound penalties, Personal Tilts, or Condtions tied to the wound. Supernatural healing works normally.", :reaches => [ - [1, "The wound gains the resistant property."], - [1, "The weapon, instead of causing wounds that do not heal, inflicts the Agony Tilt instantly."] + [1, "The wound gains the resistant property."], + [1, "The weapon, instead of causing wounds that do not heal, inflicts the Agony Tilt instantly."] ] ) - spells << Spell.new( + spells << Spell.new( :name => "Blade of Grass", :death => 3, :practice => "Perfecting", @@ -578,11 +578,11 @@ class Spell :authors => ["Dark Archon", "Menace"], :rules_text => "In the hands of a Disciple of Death, even a blade of grass can become a deadly weapon. The mage improves the abillity to harm others in the targeted item, Perfecting qualities of lethality and rending. This bestows the 8-again quality on all attack roll made with selected item.", :reaches => [ - [1, "For 1 Mana, all attack rolls made with the selected weapon gain the rote quality instead."] + [1, "For 1 Mana, all attack rolls made with the selected weapon gain the rote quality instead."] ] ) - spells << Spell.new( + spells << Spell.new( :name => "Reassert Mortality", :death => 3, :practice => "Fraying", @@ -592,14 +592,14 @@ class Spell :authors => ["Dark Archon", "Five Eyes"], :rules_text => "There are plenty of things in the Fallen who have cheated death and mortality in various ways - vampires live forever, werewolves regenerate their wounds, and so on. But Death can’t be cheated, and neither are Disciples of Death, who are more than able to return things to their natural state. This spell reasserts Death's claim on a subject, overcoming supernatural resilience. For the Duration of the spell, the subject suffers lethal damage from any source that would cause lethal damage to a normal human; a manifested spirit or ambulatory corpse finds that blades and guns are just as fearsome to them as to a flesh-and-blood mortal. This affects a number of injuries equal to the spell's Potency during the course of its Duration.", :reaches => [ - [2, "All injuries during the spell's Duration, including aggravated ones, are affected."], - [1, "For 1 Mana, the subject will suffer aggravated damage from sources that deal aggravated damage to normal humans."], - [1, "Attacks against the subject gain the armor-piercing quality, rated at the spell's Potency."], - [1, "Any reflexive or instant action taken to heal the subject by supernatural means provokes a Clash of Wills."] + [2, "All injuries during the spell's Duration, including aggravated ones, are affected."], + [1, "For 1 Mana, the subject will suffer aggravated damage from sources that deal aggravated damage to normal humans."], + [1, "Attacks against the subject gain the armor-piercing quality, rated at the spell's Potency."], + [1, "Any reflexive or instant action taken to heal the subject by supernatural means provokes a Clash of Wills."] ] ) - spells << Spell.new( + spells << Spell.new( :name => "Fate Scan", :fate => 1, :practice => "Knowing", @@ -609,13 +609,13 @@ class Spell :authors => ["Dark Archon"], :rules_text => "The Mage picks a narrative \"area of questioning\", and for each level of Potency the mage learns the most likely thing to happen with a subject in this area, in descending order of likelihood. The Mage doesn't know when or how it is likely to happen, but knows how likely it is.", :reaches => [ - [1, "The Mage may define one more area of questioning, splitting the Potency between them as they see fit. This Reach can be taken multiple times."], - [1, "The Mage can analyze how target is going to affect other people and their destinies instead."], - [1, "Instead of scrutinizing one subject, mage can give himself insight about destinies of all people in the Scale for the Duration of the spell, seeing how their destinies interconnect and influence one another."] + [1, "The Mage may define one more area of questioning, splitting the Potency between them as they see fit. This Reach can be taken multiple times."], + [1, "The Mage can analyze how target is going to affect other people and their destinies instead."], + [1, "Instead of scrutinizing one subject, mage can give himself insight about destinies of all people in the Scale for the Duration of the spell, seeing how their destinies interconnect and influence one another."] ] ) - spells << Spell.new( + spells << Spell.new( :name => "Dark Warning", :fate => 1, :practice => "Unveiling", @@ -624,11 +624,11 @@ class Spell :authors => ["Dark Archon", "espritdecalmar"], :rules_text => "Destiny never arrives without a warning - but if it is, mage can arrange for one. When a mage casts this spell, he chooses a destiny (or Destiny) of which he is aware. The spell causes the Fate to manifest one foreshadowing event per dot of Potency of that destiny between the time of casting and when the fated event occurs. For instance, if a Sleeper is destined to get into a car crash, the spell might cause her to see a commercial about auto insurance, or she might drive by the site of a car crash the day before. The effects of this spell are normally minor and subtle, but they can be useful for getting someone to believe in the power of fate and symbolism. Alternatively, the mage might wish to cause foreshadowing to manifest for particularly obscure destinies in order to analyze a mystery from a different point of view.", :reaches => [ - [1, "The mage chooses exactly how the foreshadowing manifests."] + [1, "The mage chooses exactly how the foreshadowing manifests."] ] ) - spells << Spell.new( + spells << Spell.new( :name => "No Tomorrow", :fate => 2, :practice => "Veiling", @@ -638,12 +638,12 @@ class Spell :authors => ["Dark Archon", "Flinty"], :rules_text => "Every action, even the tiniest movement, has consequences. This spell renders its subject unable to perceive the long-term consequences of an actions he contemplates taking. For example a man on vacation fails to see the damage an affair could have on his marriage.", :reaches => [ - [1, "The mage may fabricate a false consequence the subject perceives to be the logical outcome of his actions. Said man might be made to think that having an affair be ultimatly benefical for his marriage."], - [2, "For 1 Mana, short term consequences are hidden aswell. The subject can contemplate the act of jumping from a building, but is unable to perceive what a fall from a high place will do to him."] + [1, "The mage may fabricate a false consequence the subject perceives to be the logical outcome of his actions. Said man might be made to think that having an affair be ultimatly benefical for his marriage."], + [2, "For 1 Mana, short term consequences are hidden aswell. The subject can contemplate the act of jumping from a building, but is unable to perceive what a fall from a high place will do to him."] ] ) - spells << Spell.new( + spells << Spell.new( :name => "Miracle of Hephaestus / Tesla's Bright Dream", :forces => 3, :practice => "Weaving", @@ -652,11 +652,11 @@ class Spell :authors => ["Altasaire"], :rules_text => "This spell makes it so that non-electromagnetic forces can flow along the same lines and by the same principles as electromagnetic ones. With this spell, one can transfer a measure of kinetic energy along a powerline or send a campfire over WiFi.", :reaches => [ - [1, "The transfer can bypass symbolic gates and strictures of web-design. One can transfer a punch over the internet, making the kinetic energy of it go through the same pathways the information comprising a web-page or the lines of an IM messenger does."] + [1, "The transfer can bypass symbolic gates and strictures of web-design. One can transfer a punch over the internet, making the kinetic energy of it go through the same pathways the information comprising a web-page or the lines of an IM messenger does."] ] ) - spells << Spell.new( + spells << Spell.new( :name => "Rest Well", :life => 2, :practice => "Ruling", @@ -665,11 +665,11 @@ class Spell :authors => ["Dark Archon", "NEETzsche"], :rules_text => "The Mage uses this spell to speed up his rest process. The spell's Duration may not terminate before the willworker is done sleeping, and each level of Potency divides time needed to get a full night rest by 2, so Potency 1 gives 4 hours, Potency 2 gives 2 hours, Potency 3 gives 1 hours, Potency 4 gives 30 minutes and Potency 5 gives 15 minutes to get a full night's rest. All Condition and penalties inflicted by lack of rest are removed by the end of said rest. The willworker cannot regain Willpower from this rest like a proper night's sleep would offer him.", :reaches => [ - [1, "The target may also restore Willpower as if it got a full night's rest."] + [1, "The target may also restore Willpower as if it got a full night's rest."] ] ) - spells << Spell.new( + spells << Spell.new( :name => "False Health", :life => 2, :practice => "Veiling", @@ -679,7 +679,7 @@ class Spell :rules_text => "Hiding your weaknesses is essential to survival, and any Apprentice of Life knows a lot about how to survive. The target’s health seems to be fine, even if it is actually suffering from wounds, diseases or toxins. This spell does nothing to alleviate suffering or stop bleeding, but any mundane attempts to determine hurt automatically fail, and all supernatural ones trigger a Clash of Wills. If the subject contains any foreign substances, like toxins or bullets, those will be detected by mundane means or Matter; Sleepers noticing that will subject spell to Dissonance and have a breaking point." ) - spells << Spell.new( + spells << Spell.new( :name => "Brew Potion", :matter => 3, :practice => "Perfecting", @@ -688,13 +688,13 @@ class Spell :authors => ["MagicSwordsman"], :rules_text => "Magical potions and unguents are widely recognized as part of the wizard’s trade. This spell prepares a material compound to hold a Supernal charge. A mage may then cast another spell into the potion, specifically shaping their Imago and spending a point of Mana. The potion may contain up to its Potency in spells, but using the compound triggers all of them. While within the potion, a spell counts against the caster’s spell control, but its Duration is held.\n\nPotions come with certain limitations. Whomever imbibes the potion becomes the subject of its spells, although a cream or oil might be spread or splattered. If Brew Potion’s Duration runs out while it still contains spells, the held spells are lost and the potion visibly spoils.\n\nUsually this spell is cast on a liquid that resonates with the spell effect, but it could also be cast on a piece of fruit to be eaten, a powder to be inhaled, a breakable object to be tossed like a grenade, etc. “Ingredients” act as Sacrament Yantras.", :reaches => [ - [1, "The mage may add a Key to the activation of the potion. Perhaps it will only work once a certain reagent is mixed in, or it only has an effect on a certain person."], - [1, "The potion’s ingredients lose any effect they may have had on an imbiber; so an Acceleration potion of quicksilver won’t inflict mercury poisoning."], - [1, "The potion may contain multiple doses. If the same spell is cast into it multiple times, each adds an additional use to the potion."] + [1, "The mage may add a Key to the activation of the potion. Perhaps it will only work once a certain reagent is mixed in, or it only has an effect on a certain person."], + [1, "The potion’s ingredients lose any effect they may have had on an imbiber; so an Acceleration potion of quicksilver won’t inflict mercury poisoning."], + [1, "The potion may contain multiple doses. If the same spell is cast into it multiple times, each adds an additional use to the potion."] ] ) - spells << Spell.new( + spells << Spell.new( :name => "Transparency", :matter => 3, :practice => "Weaving", @@ -704,7 +704,7 @@ class Spell :rules_text => "One of the best ways to hide something is to make it invisible. This spell makes the matter of object completely transparent. While this does not alter the other properties of the material, objects that require light absorption, such as solar panels, are disabled for the Duration of this spell." ) - spells << Spell.new( + spells << Spell.new( :name => "One-Man Forge", :matter => 3, :practice => "Weaving", @@ -714,11 +714,11 @@ class Spell :authors => ["Dark Archon"], :rules_text => "Shaping allows mages to mix materials, but they still remain separated at atomic level. To truly break boundaries and become one-man forge, Mage must make a step further. This spell breaks down raw materials in Scale, changing them to liquid and then creating an alloy or compound of those materials, \"mixing\" them on the atomic level. This allows for mage to create any alloy or compound which can be made at present temperature.", :reaches => [ - [1, "The spellcaster may manipulate the physical and chemical conditions to make any possible alloy that uses the the precursor targets."] + [1, "The spellcaster may manipulate the physical and chemical conditions to make any possible alloy that uses the the precursor targets."] ] ) - spells << Spell.new( + spells << Spell.new( :name => "Golden Years, Tarnished Black", :mind => 3, :practice => "Fraying", @@ -727,11 +727,11 @@ class Spell :authors => ["amechra"], :rules_text => "Memories are fickle and changeable - exploiting this, the subject has one of their happy memories stripped of all of its positive aspects. They suffer the False Memories (VtR: B&S) condition with regards to that memory.", :reaches => [ - [1, "You are no longer restricted to only affecting happy memories. When this spell is used to worsen unhappy memories, the subject suffers the Fugue condition with regards to that memory instead."] + [1, "You are no longer restricted to only affecting happy memories. When this spell is used to worsen unhappy memories, the subject suffers the Fugue condition with regards to that memory instead."] ] ) - spells << Spell.new( + spells << Spell.new( :name => "Service is Mastery / Power Through Slavery", :mind => 3, :practice => "Weaving", @@ -740,18 +740,18 @@ class Spell :authors => ["amechra"], :rules_text => "A distressingly popular spell amongst both the Adamantine Arrow and the Seers of the Throne (though for very different reasons). Upon casting this spell, choose another person to be your target's \"master\" - your target receives Obedience to [master] as a second Vice, and takes a Beat whenever they fulfil that Vice.", :reaches => [ - [1, "The target may take an Arcane Beat instead of a normal Beat whenever they would fulfil their secondary Vice. They may also treat \"following my master's orders\" as an Oblation."], - [1, "The master you choose may be an organization rather a single person - the target's second Vice becomes Obedience to Members of [Organization Name]."], - [1, "The master you choose gains the benefits of the Loved merit with regards to the Target."] + [1, "The target may take an Arcane Beat instead of a normal Beat whenever they would fulfil their secondary Vice. They may also treat \"following my master's orders\" as an Oblation."], + [1, "The master you choose may be an organization rather a single person - the target's second Vice becomes Obedience to Members of [Organization Name]."], + [1, "The master you choose gains the benefits of the Loved merit with regards to the Target."] ], :adds => [ - {:arcana => { :prime => 2 }, :effect => "The target does not suffer Breaking Points due to their master's spells - they still suffer from all the other effects of the Sleeping Curse." }, - {:arcana => { :death => 3 }, :effect => "The target suffers from the Soulless condition for the duration of the spell." } + {:arcana => { :prime => 2 }, :effect => "The target does not suffer Breaking Points due to their master's spells - they still suffer from all the other effects of the Sleeping Curse." }, + {:arcana => { :death => 3 }, :effect => "The target suffers from the Soulless condition for the duration of the spell." } ] ) - spells << Spell.new( + spells << Spell.new( :name => "Cassandra's Curse", :prime => 2, :practice => "Veiling", @@ -760,13 +760,13 @@ class Spell :authors => ["Strill"], :rules_text => "Just like the prophet who always spoke the truth but was cursed so that no one believed her, the mage conceals all truth the subject speaks. Everyone who listens to her words is left with the impression that she's either lying, ignorant, or confused. If the spell adds a tinge of falsehood to statements that Sleeper witnesses are absolutely certain is true, those Sleepers may suffer Quiescence if they think about the contradiction too much, and spell itself will be hit with Dissonance.", :reaches => [ - [1, "Listeners perceive the subject to not just be confused or mistaken, but outright lying."], - [1, "The spell affects all forms of communication the subject engages in."], - [1, "The mage can restrict the curse to apply only to particular facts or categories. (e.g. \"My company's illegal financial dealings\", \"The secret tunnels underneath my house\", \"Statements made while performing as a fortune teller\")."] + [1, "Listeners perceive the subject to not just be confused or mistaken, but outright lying."], + [1, "The spell affects all forms of communication the subject engages in."], + [1, "The mage can restrict the curse to apply only to particular facts or categories. (e.g. \"My company's illegal financial dealings\", \"The secret tunnels underneath my house\", \"Statements made while performing as a fortune teller\")."] ] ) - spells << Spell.new( + spells << Spell.new( :name => "Liar, Liar", :prime => 3, :practice => "Weaving", @@ -776,12 +776,12 @@ class Spell :authors => ["Dark Archon"], :rules_text => "To speak a lie in the presence of a Prime Apperentice is to affront Truth itself. But Truth can strike back, forcing that person to speak it, no matter how hard or painful it is. The mage renders target unable to speak, write or articulate any falsehood. The target is not forced to speak, yet cannot transfer information it knows not to be true by mundane means; supernatural ones force Clash of Wills. Lies by omission are fine.", :reaches => [ - [1, "Target is unable to lie by omission either, being forced to speak full truth or be silent."], - [1, "The Mage can allow the target to have some leniency, choosing a topic or situation in which the target can lie without the spell interfering."] + [1, "Target is unable to lie by omission either, being forced to speak full truth or be silent."], + [1, "The Mage can allow the target to have some leniency, choosing a topic or situation in which the target can lie without the spell interfering."] ] ) - spells << Spell.new( + spells << Spell.new( :name => "Silent Room", :prime => 2, :practice => "Shielding", @@ -790,12 +790,12 @@ class Spell :authors => ["Dark Archon"], :rules_text => "With this spell, the mage enforces silence and obedience, forcing all magic aside in his domain. For the Duration of the spell, all attempts to use Supernal magic inside the area of effect are Withstood by this spell's Potency. The Mage is subject to the effects of this spell as well.", :reaches => [ - [1, "Target is unable to lie by omission either, being forced to speak full truth or be silent."], - [1, "Mage may specify one Key, which any mage can incorporate into his casting to avoid having to pass the Withstand."] + [1, "Target is unable to lie by omission either, being forced to speak full truth or be silent."], + [1, "Mage may specify one Key, which any mage can incorporate into his casting to avoid having to pass the Withstand."] ] ) - spells << Spell.new( + spells << Spell.new( :name => "Spitting on Heavenly Font", :prime => 3, :practice => "Fraying", @@ -804,12 +804,12 @@ class Spell :authors => ["Dark Archon"], :rules_text => "Sometimes, a mage needs to do the unthinkable and willingly distort existing magic. Disciples of Prime do not have the power to sling spells back across the Abyss, but he has the power to invite the Abyss into the spell, befouling and distorting it by Paradox.\n\nThis spell targets existing spells which are unsafely relinquished and speed up natural processes of Abyssal distortion. During the Duration of the spell, all rolls to distort the spell by the Storyteller have bonus dice equal to this spell's Potency.\n\nUsage of this spell would be definitely considered a Scelesti Practice by most Consilia, and would count as an Act of Hubris.", :reaches => [ - [1, "For 1 Mana, the Mage rends the spell apart with Paradox, forcing its next Distortion roll to happen immediately."], - [1, "For 1 Mana, the Mage can use this spell against an active or safely relinquished spell, forcing its next Distortion roll to happen immediately. This attempt is Withstood by target spell's Potency."] + [1, "For 1 Mana, the Mage rends the spell apart with Paradox, forcing its next Distortion roll to happen immediately."], + [1, "For 1 Mana, the Mage can use this spell against an active or safely relinquished spell, forcing its next Distortion roll to happen immediately. This attempt is Withstood by target spell's Potency."] ] ) - spells << Spell.new( + spells << Spell.new( :name => "Wrestle Out The Keys to Heaven", :prime => 4, :practice => "Unraveling", @@ -819,12 +819,12 @@ class Spell :authors => ["Dark Archon"], :rules_text => "With this spell, an Adept of Prime applies brutal force, tearing down the mystical connection between spell and its creator. This spell forces a Clash of Wills between mage and creator of targeted active spell. If the caster of Wrestle Out The Keys To Heaven wins, the targeted active spell is unsafely relinquished against the will of its creator for the Duration of this spell. If the targeted active spell is cast upon a Scale, then Wrestle Out Keys to Heaven need to cover the same Scale.", :reaches => [ - [1, "For 1 Mana, the Mage rends the spell apart with Paradox, forcing its next Distortion roll to happen immediately."], - [1, "For 1 Mana, the Mage can use this spell against an active or safely relinquished spell, forcing its next Distortion roll to happen immediately. This attempt is Withstood by target spell's Potency."] + [1, "For 1 Mana, the Mage rends the spell apart with Paradox, forcing its next Distortion roll to happen immediately."], + [1, "For 1 Mana, the Mage can use this spell against an active or safely relinquished spell, forcing its next Distortion roll to happen immediately. This attempt is Withstood by target spell's Potency."] ] ) - spells << Spell.new( + spells << Spell.new( :name => "Pass On Greatest Treasure", :prime => 4, :practice => "Patterning", @@ -834,12 +834,12 @@ class Spell :authors => ["Dark Archon"], :rules_text => "Sometimes a load is too heavy to carry alone. With this spell, an Adept of Prime can temporarily pass on control of a number of his active spells equal to Pass On Greatest Treasure's Potency without relinquishing them for the Duration of the spell. The should be somebody who is able to carry said spell: a Mage, a willing Sleepwalker, one's Sanctum, a Node or Artifact. The target does not gain control over the passed spells which original caster has, but passed spells count against their Gnosis-derived Reach limits. If target is unwilling, then spell is Withstood with Resolve.", :reaches => [ - [1, "The target gets the same amount control over each passed spell which the original caster has and may drop or relinquish them safely or unsafely."], - [2, "For 1 Mana, the effect is Lasting and selected spells are transferred permanently to their new owner."] + [1, "The target gets the same amount control over each passed spell which the original caster has and may drop or relinquish them safely or unsafely."], + [2, "For 1 Mana, the effect is Lasting and selected spells are transferred permanently to their new owner."] ] ) - spells << Spell.new( + spells << Spell.new( :name => "Thread of Ariadne", :space => 1, :practice => "Knowing", @@ -849,12 +849,12 @@ class Spell :authors => ["Dark Archon"], :rules_text => "The Mage uses his existing sympathetic connection to track the target. For the Duration of the spell, the mage knows the general direction, following which paths he can find toward his intended target.", :reaches => [ - [1, "The Mage knows not just the general direction, but instinctively knows the best possible path to the target and can follow it for the Duration of the spell."] + [1, "The Mage knows not just the general direction, but instinctively knows the best possible path to the target and can follow it for the Duration of the spell."] ] ) - spells << Spell.new( + spells << Spell.new( :name => "Twist Link", :space => 3, :practice => "Weaving", @@ -864,12 +864,12 @@ class Spell :authors => ["amechra"], :rules_text => "Relationships are fragile, weak things - easily twisted and turned and placed on their head. Twist Link allows the mage to redefine the context of a sympathetic link; they could redefine a business rivalry as a childhood friendship, or a pair of lovers as a pair of enemies. The mage only defines the new relationship in general terms - much like creating or destroying a link, this spell doesn't guarantee outcomes or force reactions. This effect is Lasting, but normal interactions can restore the original link context over time. Much like other weaker sympathy-changing magic, Twist Link cannot affect Connected links.", :reaches => [ - [1, "Place the Embarassing Secret condition regarding the original context of the relationship on the link."], - [1, "Place the Swooning condition on the link."] + [1, "Place the Embarassing Secret condition regarding the original context of the relationship on the link."], + [1, "Place the Swooning condition on the link."] ] ) - spells << Spell.new( + spells << Spell.new( :name => "Phasing", :space => 4, :practice => "Patterning", @@ -878,13 +878,13 @@ class Spell :authors => ["Dark Archon"], :rules_text => "You are here; but at the same time, you aren't. By carefully manipulating the space your body occupies, you are protected against all physical attacks - they just pass through your body. People are still able to see, hear and smell you; mental and magical attacks work as normal. Liquids and gases don't affect you, but you are still able to be blinded, deafened and so on.", :reaches => [ - [1, "By passing the light through the body to the other side, you are invisible as well."], - [1, "You can manipulate objects, carry items and physically attack your enemies."], - [1, "Aimed spells won't work on you - enemy needs to attack your Pattern directly to harm you."] + [1, "By passing the light through the body to the other side, you are invisible as well."], + [1, "You can manipulate objects, carry items and physically attack your enemies."], + [1, "Aimed spells won't work on you - enemy needs to attack your Pattern directly to harm you."] ] ) - spells << Spell.new( + spells << Spell.new( :name => "Spirit Invitation", :spirit => 3, :practice => "Weaving", @@ -893,11 +893,11 @@ class Spell :authors => ["Dark Archon"], :rules_text => "The Shaman opens and closes ways from the Shadow to the material world as he sees fit. At this point, he is not able to bind spirits, but he is able to invite them. This spell creates the Open Condition on a specific Resonance for a target, for the Duration of spell. Unwilling sentient targets Withstand with Resolve.", :reaches => [ - [1, "Shaman is able to give target universal Open Condition, useable by all spirits."] + [1, "Shaman is able to give target universal Open Condition, useable by all spirits."] ] ) - spells << Spell.new( + spells << Spell.new( :name => "Preclude Waning Effect", :spirit => 3, :practice => "Perfecting or Fraying", @@ -907,11 +907,11 @@ class Spell :authors => ["NEETzsche"], :rules_text => "A spiritual Condition's effects are prolonged past when they would normally expire. As long as the spell remains active, the Condition cannot resolve. For example, a Possessed (Mage: the Awakening, p. 261) entity remains in such a state well past when the scene ends. Mundane attempts to resolve the Condition fail automatically, while supernatural methods to do so provoke a Clash of Wills.", :adds => [ - { :verb => "Substitute", :arcana => { :fate => 3, :life => 3, :mind => 3}, :separator => "or", :effect => "A blessing or Condition, a Condition imposed on a living entity like a disease, or a Mental Condition persists instead. The Storyteller chooses an appropriate trait to Withstand if the effect being prolonged is negative."} + { :verb => "Substitute", :arcana => { :fate => 3, :life => 3, :mind => 3}, :separator => "or", :effect => "A blessing or Condition, a Condition imposed on a living entity like a disease, or a Mental Condition persists instead. The Storyteller chooses an appropriate trait to Withstand if the effect being prolonged is negative."} ] ) - spells << Spell.new( + spells << Spell.new( :name => "See The Signs", :fate => 1, :practice => "Knowing", @@ -922,7 +922,7 @@ class Spell :rules_text => "This spell allows the Mage to know what Fate has in store for the subject, allowing the Mage to view the subject's Aspirations. This spell reveals a number of Aspirations equal to Potency, in an order determined by the Storyteller." ) - spells << Spell.new( + spells << Spell.new( :name => "Sacred Mission", :prime => 1, :practice => "Knowing", @@ -933,7 +933,7 @@ class Spell :rules_text => "All Willworkers work to achieve a higher calling, by means of this spell the Mage can learn what Truths the subject is trying to uncover. This spell reveals a number of Obsessions equal to Potency." ) - spells << Spell.new( + spells << Spell.new( :name => "Full Night's Rest", :life => 3, :practice => "Perfecting", @@ -943,7 +943,7 @@ class Spell :rules_text => "The spell reproduces the effects of a full night’s rest in the subject, including regaining a point of Willpower if applicable. Each level of Potency instantly removes one level of negative modifier caused by exhaustion." ) - spells << Spell.new( + spells << Spell.new( :name => "Bamboo's Vivacity", :life => 3, :practice => "Weaving", @@ -953,7 +953,7 @@ class Spell :rules_text => "This spells allows the Mage to accelerate plants' growth rate to that of the fastest growing plant on earth. This means that they will gain a little under a meter per day in length, and grow to prodigious (although not outright supernatural) thickness. Each cast affects an area corresponding to scale, not a single plant (unless the plant in question is so large as to occupy the entire scale)." ) - spells << Spell.new( + spells << Spell.new( :name => "Dog Whistle", :spirit => 2, :practice => "Veiling", @@ -962,11 +962,11 @@ class Spell :authors => ["NEETzsche"], :rules_text => "The mage says something with a double meaning in the First Tongue. To her intended audience, it means one thing, and to every other entity, it means something entirely different. The audience needs to be a specific entity. Attempts by spirits and other entities to pierce the deception is Withstood by the spell's Potency.", :reaches => [ - [1, "The caster can specify an entire category of entities as his target audience, like a spirit choir or werewolf Auspice."] + [1, "The caster can specify an entire category of entities as his target audience, like a spirit choir or werewolf Auspice."] ] ) - spells << Spell.new( + spells << Spell.new( :name => "Intense Dream", :mind => 1, :practice => "Compelling", @@ -976,7 +976,7 @@ class Spell :rules_text => "The mage compels a sleeping target to begin dreaming, and do so in a vivid and psychologically compelling fashion. The caster does not dictate the content of the dream. To do this, she should cast Dream Reaching (Mage: the Awakening, p. 160); otherwise the Storyteller controls the nature and subject matter of the dream.\n\nIn the state of this intense dream, the subject may experience Breaking Points and collect Beats as though they were awake. The entirety of the dream counts as one scene." ) - spells << Spell.new( + spells << Spell.new( :name => "Twilight Object", :spirit => 3, :practice => "Weaving", @@ -985,11 +985,11 @@ class Spell :authors => ["NEETzsche"], :rules_text => "The willworker renders an object usable on spiritual entities in Twilight. Guns can shoot at spirits as though they were Twilight guns and cameras can see the goings-on of both the physical world and Twilight. However, the object is not necessarily under the total control of the willworker; a spirit could pick a gun up and shoot someone in the physical world, as it can be used in both Twilight and the physical world, as an example.", :reaches => [ - [1, "The object can Reach across the Gauntlet outright. This is Withstood by the Gauntlet's strength in the area it is currently in. As the Gauntlet's strength changes, so too does the effectiveness of this Reach ability. So if a gun is taken to a place with a stronger Gauntlet, it might not work there, or vice versa."] + [1, "The object can Reach across the Gauntlet outright. This is Withstood by the Gauntlet's strength in the area it is currently in. As the Gauntlet's strength changes, so too does the effectiveness of this Reach ability. So if a gun is taken to a place with a stronger Gauntlet, it might not work there, or vice versa."] ] ) - spells << Spell.new( + spells << Spell.new( :name => "Supernal Steganography", :forces => 2, :practice => "Veiling", @@ -998,11 +998,11 @@ class Spell :authors => ["NEETzsche"], :rules_text => "The Mage masks the true meaning of an electronic message to unintended recipients, making something important look innocuous. Photos of a murdered target might be made to look like a dog face Snapchat picture and an email listing a Sanctum's exact location might read like Papa John's coupons. Mundane attempts to detect the true message fail automatically, while supernatural ones provoke a Clash of Wills.", :reaches => [ - [1, "The real message destroys itself when the spell expires, and its removal is so thorough that attempts to recover it provoke a Clash of Wills like above."] + [1, "The real message destroys itself when the spell expires, and its removal is so thorough that attempts to recover it provoke a Clash of Wills like above."] ] ) - spells << Spell.new( + spells << Spell.new( :name => "Green Thumb", :life => 1, :practice => "Compelling", @@ -1011,12 +1011,12 @@ class Spell :authors => ["NEETzsche"], :rules_text => "The Mage creates the ideal conditions for plant life out of normal dirt and water. Using this spell, she can make plants grow even in polluted soil or in places the plant would not grow. As long as this spell is active, the plant grows as though it had perfect growing conditions.", :reaches => [ - [1, "the Mage may customize the growing pattern of the plant. Nothing biologically impossible can happen, but small things like making a squash grow in a certain shape or a tree's branches emerge at certain spots and in certain directions are wholly plausible."] + [1, "the Mage may customize the growing pattern of the plant. Nothing biologically impossible can happen, but small things like making a squash grow in a certain shape or a tree's branches emerge at certain spots and in certain directions are wholly plausible."] ] ) - spells << Spell.new( + spells << Spell.new( :name => "Locked Locus", :spirit => 2, :practice => "Shielding", @@ -1025,12 +1025,12 @@ class Spell :authors => ["NEETzsche"], :rules_text => "This spell precludes a Locus from being used without authorization. The caster specifies a Key that must be used in order to use the Locus to cross the Gauntlet. Supernatural abilities that allow one to cross the Gauntlet using this Locus without permission provoke a Clash of Wills if the proper Key is not possessed.", :reaches => [ - [1, "Essence cannot be extracted from the Locus without use of the Key."], - [1, "Attempts to impact anything across the Gauntlet is similarly restricted."] + [1, "Essence cannot be extracted from the Locus without use of the Key."], + [1, "Attempts to impact anything across the Gauntlet is similarly restricted."] ] ) - spells << Spell.new( + spells << Spell.new( :name => "Babel", :mind => 3, :practice => "Fraying", @@ -1039,11 +1039,11 @@ class Spell :authors => ["NEETzsche"], :rules_text => "The spell's subject is capable of understanding and translating no language. When he speaks, gibberish comes out, and when he writes, he only puts scribbling to paper. Just as he cannot communicate his thoughts to others, all he can get out of others is word salad or incoherent babbling. This is true for the spoken word, written language, symbols, encoded signals, body language, hand symbols and concepts that only exist as thought. The only exception is that Awakened characters do not lose their ability to understand High Speech.", :reaches => [ - [1, "They also cannot comprehend High Speech."] + [1, "They also cannot comprehend High Speech."] ] ) - spells << Spell.new( + spells << Spell.new( :name => "Elusivity", :space => 2, :practice => "Veiling", @@ -1053,7 +1053,7 @@ class Spell :rules_text => "The Mage becomes particularly difficult to track. He naturally takes unexpected routes to his destination and people who would want to find him take routes other than the one he is. All mundane attempts to track him fail, and all supernatural attempts to do so provokes a Clash of Wills." ) - spells << Spell.new( + spells << Spell.new( :name => "Supernal Will", :mind => 4, :practice => "Patterning", @@ -1062,14 +1062,14 @@ class Spell :authors => ["noire"], :rules_text => "The mage taps into the deepest reserves of personal resolve and unleashes a tidal wave of conviction toward a single minded goal. When the target spends Willpower to go above and beyond what should be possible to achieve her goals, substitute her Resolve rating for the usual Willpower bonus. The spell cannot increase the subject’s Willpower bonus above her resolve.", :reaches => [ - [1, "If the roll gaining this benefit is contested, roll with 8-again."], - [1, "The spell may temporarily increase Resolve by one dot per level of Potency of the spell. The spell cannot increase the subject’s Resolve above their normal maximum. Sleepers compelled to above their natural Resolve gain the broken condition after the spell ends."], - [1, "For a point of Mana, the benefit of the spell may affect spellcasting."] + [1, "If the roll gaining this benefit is contested, roll with 8-again."], + [1, "The spell may temporarily increase Resolve by one dot per level of Potency of the spell. The spell cannot increase the subject’s Resolve above their normal maximum. Sleepers compelled to above their natural Resolve gain the broken condition after the spell ends."], + [1, "For a point of Mana, the benefit of the spell may affect spellcasting."] ] ) - spells << Spell.new( + spells << Spell.new( :name => "Abuse Body", :life => 2, :practice => "Ruling", @@ -1354,16 +1354,16 @@ class Spell :rules_text => "The willworker reads any Conditions or spiritual effects that target or directly impact the subject of observation, such as Numina, Gifts, or Influences, up to the Potency of the spell, in an order at the Storyteller's discretion. He gains a full understanding of what they do and how they work. The subject can be a person, place, or thing. Spiritual effects that are designed to be surreptitious invoke a Clash of Wills." ) - # TESTS + # TESTS - duplicate_spells = spells.group_by(&:name).select {| k, v| v.length > 1 } - raise "Duplicate spells (on name) detected: #{duplicate_spells.collect{ |k,v| k}.to_list}" if duplicate_spells.length > 0 + duplicate_spells = spells.group_by(&:name).select {| k, v| v.length > 1 } + raise "Duplicate spells (on name) detected: #{duplicate_spells.collect{ |k,v| k}.to_list}" if duplicate_spells.length > 0 - unpunctuated_spells = spells.select { |spell| spell.rules_text.unpunctuated? || spell.reaches.collect{|reach| reach.size == 2 ? reach[1] : reach[2] }.any?(&:unpunctuated?) || spell.adds.any? { |add| add[:effect].unpunctuated? } } + unpunctuated_spells = spells.select { |spell| spell.rules_text.unpunctuated? || spell.reaches.collect{|reach| reach.size == 2 ? reach[1] : reach[2] }.any?(&:unpunctuated?) || spell.adds.any? { |add| add[:effect].unpunctuated? } } - raise "The following spells lack punctuation: #{unpunctuated_spells.collect(&:name).to_list}" if unpunctuated_spells.length > 0 + raise "The following spells lack punctuation: #{unpunctuated_spells.collect(&:name).to_list}" if unpunctuated_spells.length > 0 - spells + spells - end + end end diff --git a/tilt.rb b/tilt.rb index 80b633f..16598ae 100644 --- a/tilt.rb +++ b/tilt.rb @@ -1,25 +1,25 @@ class Tilt - attr_accessor :name, :rules_text, :effect, :causing, :ending, :environmental, :authors + attr_accessor :name, :rules_text, :effect, :causing, :ending, :environmental, :authors - def initialize(name:, rules_text:, effect:, causing:, ending:, environmental: false , authors:) - @name = name - @rules_text = rules_text - @effect = effect - @causing = causing - @ending = ending - @environmental = environmental - @authors = authors - end + def initialize(name:, rules_text:, effect:, causing:, ending:, environmental: false , authors:) + @name = name + @rules_text = rules_text + @effect = effect + @causing = causing + @ending = ending + @environmental = environmental + @authors = authors + end - def full_title - if environmental - "#{name} (Environmental)" - else - name - end - end + def full_title + if environmental + "#{name} (Environmental)" + else + name + end + end - def environmental? - environmental - end + def environmental? + environmental + end end \ No newline at end of file diff --git a/tilts.rb b/tilts.rb index b6f4d6d..01349b8 100644 --- a/tilts.rb +++ b/tilts.rb @@ -1,28 +1,28 @@ class Tilt - def self.tilts - tilts = [] + def self.tilts + tilts = [] - tilts << Tilt.new( - :name => "Sticky Ground", - :rules_text => "The ground is covered in a sticky substance that precludes people, animals, and vehicles from treading on it. The substance could be a thin layer on top, or a thick quick sand that will eventually suck them in.", - :effect => "Divide the Speed of all who might tread on this ground in half, rounding up, and all rolls that require her to move her feet suffer a -2 penalty. Any dramatic failure on a Physical roll inflicts the Immobilized Tilt.", - :causing => "This Tilt can be caused by anything ranging from a spell, to a natural feature of the terrain. A character might choose to pour hot pine tar on the ground, making it difficult to move.", - :ending => "\"Get out of the quicksand!\" might be a good idea, but that is easier said than done. Characters can pour sand on the ground to give it traction. They can lower the temperature of the area, making the substance they're walking on solidify.", - :environmental => true, - :authors => ["NEETzsche", "Dark Archon"] - ) + tilts << Tilt.new( + :name => "Sticky Ground", + :rules_text => "The ground is covered in a sticky substance that precludes people, animals, and vehicles from treading on it. The substance could be a thin layer on top, or a thick quick sand that will eventually suck them in.", + :effect => "Divide the Speed of all who might tread on this ground in half, rounding up, and all rolls that require her to move her feet suffer a -2 penalty. Any dramatic failure on a Physical roll inflicts the Immobilized Tilt.", + :causing => "This Tilt can be caused by anything ranging from a spell, to a natural feature of the terrain. A character might choose to pour hot pine tar on the ground, making it difficult to move.", + :ending => "\"Get out of the quicksand!\" might be a good idea, but that is easier said than done. Characters can pour sand on the ground to give it traction. They can lower the temperature of the area, making the substance they're walking on solidify.", + :environmental => true, + :authors => ["NEETzsche", "Dark Archon"] + ) - tilts << Tilt.new( - :name => "Labyrinth", - :rules_text => "The landscape you are in does not have a consistent physical form. This could be a particularly mercurial part of the spirit world, a booby trapped Mage's Sanctum, or any other place where making a map on paper simply won't cut it.", - :effect => "It is impossible to leave the labyrinth by mundane means. Either the effect causing this environmental Tilt must expire, or some other supernatural ability allowing one to leave must take effect, and win a Clash of Wills. All mundane attempts to leave the labyrinth automatically fail. The same applies to attempts to use the environment to any kind of tactical advantage, such as finding cover or hiding in closets; the labyrinth's form is too capricious to entertain such static or simple methods of environmental manipulation.", - :causing => "Some supernatural abilities can cause this Tilt. Other places have this Tilt persistently, such as in Pandemonium.", - :ending => "The Gift, spell, Discipline, or ability expires. The labyrinthine place is destroyed. A supernatural ability that allows one command over the environment can partially end the Tilt by vetoing that element of it with a Clash of Wills.", - :environmental => true, - :authors => ["NEETzsche"] - ) + tilts << Tilt.new( + :name => "Labyrinth", + :rules_text => "The landscape you are in does not have a consistent physical form. This could be a particularly mercurial part of the spirit world, a booby trapped Mage's Sanctum, or any other place where making a map on paper simply won't cut it.", + :effect => "It is impossible to leave the labyrinth by mundane means. Either the effect causing this environmental Tilt must expire, or some other supernatural ability allowing one to leave must take effect, and win a Clash of Wills. All mundane attempts to leave the labyrinth automatically fail. The same applies to attempts to use the environment to any kind of tactical advantage, such as finding cover or hiding in closets; the labyrinth's form is too capricious to entertain such static or simple methods of environmental manipulation.", + :causing => "Some supernatural abilities can cause this Tilt. Other places have this Tilt persistently, such as in Pandemonium.", + :ending => "The Gift, spell, Discipline, or ability expires. The labyrinthine place is destroyed. A supernatural ability that allows one command over the environment can partially end the Tilt by vetoing that element of it with a Clash of Wills.", + :environmental => true, + :authors => ["NEETzsche"] + ) - return tilts - end + return tilts + end end \ No newline at end of file