diff --git a/Dockerfile b/Dockerfile index 5376d77..6b2a8ee 100755 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,6 @@ FROM ruby:2.6.3 -EXPOSE 7878 - -ENV HOST=0.0.0.0 PORT=7878 RACK_ENV=development +ENV HOST=0.0.0.0 PORT=7878 RACK_ENV=production # throw errors if Gemfile has been modified since Gemfile.lock RUN bundle config --global frozen 1 @@ -18,5 +16,4 @@ COPY . /app WORKDIR /app/src -CMD ["rerun", "-b", "--", "ruby", "./app.rb"] -#CMD ["ruby", "./app.rb"] \ No newline at end of file +CMD ["ruby", "./app.rb"] \ No newline at end of file diff --git a/Dockerfile.dev b/Dockerfile.dev new file mode 100755 index 0000000..5376d77 --- /dev/null +++ b/Dockerfile.dev @@ -0,0 +1,22 @@ +FROM ruby:2.6.3 + +EXPOSE 7878 + +ENV HOST=0.0.0.0 PORT=7878 RACK_ENV=development + +# throw errors if Gemfile has been modified since Gemfile.lock +RUN bundle config --global frozen 1 + +WORKDIR /app + +# to generate Gemfile.lock, run this in service dir: +# $ docker run --rm -v "$PWD":/app -w /app ruby:2.6.3 bundle install +COPY Gemfile Gemfile.lock /app/ +RUN bundle install + +COPY . /app + +WORKDIR /app/src + +CMD ["rerun", "-b", "--", "ruby", "./app.rb"] +#CMD ["ruby", "./app.rb"] \ No newline at end of file diff --git a/deploy.md b/deploy.md new file mode 100755 index 0000000..ec2f7d0 --- /dev/null +++ b/deploy.md @@ -0,0 +1,10 @@ +Deploy +------ + +https://devcenter.heroku.com/articles/container-registry-and-runtime + +heroku login +heroku container:login +heroku container:push web -a charred-black +heroku container:release web -a charred-black +heroku open \ No newline at end of file diff --git a/src/data/lifepaths/wizard.json b/src/data/lifepaths/wizard.json index f4148ad..fff82e5 100755 --- a/src/data/lifepaths/wizard.json +++ b/src/data/lifepaths/wizard.json @@ -69,7 +69,7 @@ } }, "Peasant Setting": { - "Speaker of Names": { + "Speaker Of Names": { "time": 7, "res": 20, "stat": [ @@ -185,7 +185,7 @@ 2, "Low Born", "Impressive Hat", - "Never a Moment of Peace" + "Never A Moment Of Peace" ], "requires": "Wizard's Apprentice, Neophyte Sorcerer, Apt Pupil or Junior Student. This character may not have the Mark of Privilege", "requires_expr": [ @@ -263,10 +263,10 @@ "religious subsetting:canon", "religious subsetting:abbot/abbess", "religious subsetting:bishop", - "outcast subsetting:mad summoner", - "outcast subsetting:crazy witch", - "seafaring setting:weather witch", - "noble court subsetting:court summoner" + "mad summoner", + "crazy witch", + "weather witch", + "court summoner" ], "key_leads": [ "Outcast Subsetting", @@ -347,13 +347,13 @@ "Dismissive", "Polite", "Arrogant", - "Frustrated", + "Disgruntled", "Faust" ], "requires": "Senior Student, Mad Summoner, Apt Pupil or Wizard's Apprentice", "requires_expr": [ "senior student", - "outcast subsetting:mad summoner", + "mad summoner", "apt pupil", "wizard's apprentice" ], @@ -364,7 +364,7 @@ ] } }, - "Outcast Setting": { + "Outcast Subsetting": { "Demented Inventor": { "time": 7, "res": 15, @@ -390,14 +390,14 @@ ], "traits": [ 2, - "Demented", + "Unhinged", "Tinker" ], "requires": "Rogue Wizard, Apt Pupil or Wizard's Apprentice", "requires_expr": [ "rogue wizard", "apt pupil", - "villager setting:wizard's apprentice" + "wizard's apprentice" ], "key_leads": [ "Peasant Setting", @@ -432,8 +432,8 @@ ], "requires": "Coroner, Death Cultist, Cultist or Apt Pupil", "requires_expr": [ - "noble court subsetting:coroner", - "death cult setting:death cultist", + "coroner", + "death cultist", "cultist", "apt pupil" ] @@ -472,6 +472,13 @@ [ "+has_n_lifepaths_or_less", 1 + ], + [ + "born peasant", + "village born", + "city born", + "born noble", + "son of a gun" ] ], "key_leads": [ @@ -483,6 +490,12 @@ "Junior Student": { "time": 2, "res": 5, + "stat": [ + [ + 1, + "p" + ] + ], "leads": [ "City", "Court", @@ -519,653 +532,688 @@ ] }, "Senior Student": { - "time": 1, - "res": 1, + "time": 2, + "res": 10, + "stat": [ + [ + 1, + "m" + ] + ], "leads": [ - "Peasant", - "Villager", "City", "Court", - "Servitude", - "Outcast", - "Soldier", - "Seafaring", - "Religious" + "Outcast" ], "skills": [ [ - 3, - "" + 7, + "Calligraphy", + "Rhetoric", + "Aura Reading", + "Empyrealia", + "Demonology", + "Doctrine", + "School of Magic-wise", + "Junior Student-wise" ] ], "traits": [ - 1, - "" + 2, + "Graduate", + "Bully" + ], + "requires": "Junior Student or Sorcerer. May not be taken twice", + "requires_expr": [ + "junior student", + "sorcerer" ], - "requires": "", - "requires_expr": [], "key_leads": [ - "Peasant Setting", - "Villager Setting", "City Dweller Setting", "Noble Court Subsetting", - "Servitude And Captive Setting", - "Outcast Subsetting", - "Professional Soldier Subsetting", - "Seafaring Setting", - "Religious Subsetting" + "Outcast Subsetting" ] }, "Adjunct": { - "time": 1, - "res": 1, + "time": 6, + "res": 10, + "stat": [ + [ + 1, + "m" + ] + ], "leads": [ - "Peasant", - "Villager", "City", - "Court", - "Servitude", "Outcast", - "Soldier", - "Seafaring", "Religious" ], "skills": [ [ - 3, - "" + 6, + "Research", + "Folklore", + "Alchemy", + "Taxidermy", + "Library-wise" ] ], "traits": [ 1, - "" + "Overworked", + "Familiar Face" + ], + "requires": "Senior Student", + "requires_expr": [ + "senior student" ], - "requires": "", - "requires_expr": [], "key_leads": [ - "Peasant Setting", - "Villager Setting", "City Dweller Setting", - "Noble Court Subsetting", - "Servitude And Captive Setting", "Outcast Subsetting", - "Professional Soldier Subsetting", - "Seafaring Setting", "Religious Subsetting" ] }, "Master Sorcerer": { - "time": 1, - "res": 1, + "time": 8, + "res": 30, + "stat": [ + [ + 1, + "p" + ], + [ + 1, + "m" + ] + ], "leads": [ - "Peasant", - "Villager", "City", "Court", - "Servitude", "Outcast", - "Soldier", - "Seafaring", - "Religious" + "Seafaring" ], "skills": [ [ - 3, - "" + 5, + "Sorcery", + "Instructor", + "Facet-wise", + "Aura-wise" ] ], "traits": [ 1, - "" + "Versatile", + "Sixth Sense" + ], + "requires": "Adjunct or Court Sorcerer", + "requires_expr": [ + "adjunct", + "court sorcerer" ], - "requires": "", - "requires_expr": [], "key_leads": [ - "Peasant Setting", - "Villager Setting", "City Dweller Setting", "Noble Court Subsetting", - "Servitude And Captive Setting", "Outcast Subsetting", - "Professional Soldier Subsetting", - "Seafaring Setting", - "Religious Subsetting" + "Seafaring Setting" ] }, "Master Enchanter": { - "time": 1, - "res": 1, + "time": 8, + "res": 20, + "stat": [ + [ + 1, + "p" + ], + [ + 1, + "m" + ] + ], "leads": [ - "Peasant", - "Villager", "City", "Court", - "Servitude", - "Outcast", - "Soldier", - "Seafaring", - "Religious" + "Outcast" ], "skills": [ [ - 3, - "" + 6, + "Enchanting", + "Instructor", + "Carving", + "Etching", + "Herbalism", + "Jeweler", + "Vessel-wise" ] ], "traits": [ 1, - "" + "Nimble", + "Practiced Precision" + ], + "requires": "Adjunct or Court Enchanter", + "requires_expr": [ + "adjunct", + "court enchanter" ], - "requires": "", - "requires_expr": [], "key_leads": [ - "Peasant Setting", - "Villager Setting", "City Dweller Setting", "Noble Court Subsetting", - "Servitude And Captive Setting", - "Outcast Subsetting", - "Professional Soldier Subsetting", - "Seafaring Setting", - "Religious Subsetting" + "Outcast Subsetting" ] }, "Master Summoner": { - "time": 1, - "res": 1, + "time": 8, + "res": 20, + "stat": [ + [ + 1, + "p" + ], + [ + 1, + "m" + ] + ], "leads": [ - "Peasant", - "Villager", "City", "Court", - "Servitude", - "Outcast", - "Soldier", - "Seafaring", - "Religious" + "Outcast" ], "skills": [ [ - 3, - "" + 8, + "Summoning", + "Instructor", + "Bargaining", + "Ugly Truth", + "Soothing Platitudes", + "Rule of Law", + "Philosophy", + "Scheme-wise" ] ], "traits": [ 1, - "" + "Extrovert", + "Fearless", + "Obscure Aura" + ], + "requires": "Adjunct or Court Summoner", + "requires_expr": [ + "adjunct", + "court summoner" ], - "requires": "", - "requires_expr": [], "key_leads": [ - "Peasant Setting", - "Villager Setting", "City Dweller Setting", "Noble Court Subsetting", - "Servitude And Captive Setting", - "Outcast Subsetting", - "Professional Soldier Subsetting", - "Seafaring Setting", - "Religious Subsetting" + "Outcast Subsetting" ] }, "Researcher": { - "time": 1, - "res": 1, + "time": 10, + "res": 15, "leads": [ - "Peasant", - "Villager", - "City", "Court", - "Servitude", "Outcast", - "Soldier", - "Seafaring", "Religious" ], "skills": [ [ - 3, - "" + 12, + "Research", + "Composition", + "Cartography", + "Cryptogrpahy", + "Doctrine", + "Apothecary", + "Ritual", + "Death Art", + "Foreign Languages", + "Dark Arts-wise", + "Elven Songs-wise", + "Orc Rituals-wise", + "Dwarven Art-wise" ] ], "traits": [ - 1, - "" + 2, + "Myopic", + "Bookworm", + "Speaker Of The Secret Language" + ], + "requires": "Adjunct or Scholar. May only be taken once", + "requires_expr": [ + "adjunct", + "scholar" ], - "requires": "", - "requires_expr": [], "key_leads": [ - "Peasant Setting", - "Villager Setting", - "City Dweller Setting", "Noble Court Subsetting", - "Servitude And Captive Setting", "Outcast Subsetting", - "Professional Soldier Subsetting", - "Seafaring Setting", "Religious Subsetting" ] }, "Councillor": { - "time": 1, - "res": 1, + "time": 5, + "res": 40, + "stat": [ + [ + 1, + "m" + ] + ], "leads": [ - "Peasant", - "Villager", "City", - "Court", - "Servitude", - "Outcast", - "Soldier", - "Seafaring", - "Religious" + "Court" ], "skills": [ [ - 3, - "" + 6, + "Administration", + "Rhetoric", + "Wine Tasting", + "Troubled Student-wise" ] ], "traits": [ 1, - "" + "Council Of Mages", + "Imperious Demeanor" + ], + "requires": "Master Sorcerer, Master Enchanter or Master Summoner", + "requires_expr": [ + "master sorcerer", + "master enchanter", + "master summoner" ], - "requires": "", - "requires_expr": [], "key_leads": [ - "Peasant Setting", - "Villager Setting", "City Dweller Setting", - "Noble Court Subsetting", - "Servitude And Captive Setting", - "Outcast Subsetting", - "Professional Soldier Subsetting", - "Seafaring Setting", - "Religious Subsetting" + "Noble Court Subsetting" ] }, "Headmaster": { - "time": 1, - "res": 1, + "time": 12, + "res": 50, "leads": [ - "Peasant", - "Villager", - "City", "Court", - "Servitude", - "Outcast", - "Soldier", - "Seafaring", "Religious" ], "skills": [ [ - 3, - "" + 7, + "Oratory", + "Etiquette", + "Poetry", + "Strategy Games", + "Vintner", + "Dark Secret-wise" + ], + [ + 1, + "General" ] ], "traits": [ - 1, - "" + 3, + "Stoic", + "Master Of Mages", + "Domineering Presence" + ], + "requires": "Councillor", + "requires_expr": [ + "councillor" ], - "requires": "", - "requires_expr": [], "key_leads": [ - "Peasant Setting", - "Villager Setting", - "City Dweller Setting", "Noble Court Subsetting", - "Servitude And Captive Setting", - "Outcast Subsetting", - "Professional Soldier Subsetting", - "Seafaring Setting", "Religious Subsetting" ] } }, "Death Cult Setting": { "Harem Slave": { - "time": 1, - "res": 1, + "time": 3, + "res": 3, "leads": [ - "Peasant", - "Villager", - "City", - "Court", "Servitude", - "Outcast", - "Soldier", - "Seafaring", - "Religious" + "Outcast" ], "skills": [ [ - 3, - "" + 4, + "Creepy Priest-wise", + "Disgusting Necromancer-wise", + "Death Cult-wise", + "Escape Artist" ] ], "traits": [ - 1, - "" + 2, + "Numb" ], - "requires": "", - "requires_expr": [], "key_leads": [ - "Peasant Setting", - "Villager Setting", - "City Dweller Setting", - "Noble Court Subsetting", "Servitude And Captive Setting", - "Outcast Subsetting", - "Professional Soldier Subsetting", - "Seafaring Setting", - "Religious Subsetting" + "Outcast Subsetting" ] }, "Death Cultist": { - "time": 1, - "res": 1, + "time": 2, + "res": 5, "leads": [ - "Peasant", - "Villager", - "City", - "Court", "Servitude", "Outcast", - "Soldier", - "Seafaring", - "Religious" + "Soldier" ], "skills": [ [ 3, - "" + "Death-wise", + "Riot-wise", + "Secret Cult Worship-wise" ] ], "traits": [ - 1, - "" + 2, + "Zealot", + "Suicidal" ], - "requires": "", - "requires_expr": [], "key_leads": [ - "Peasant Setting", - "Villager Setting", - "City Dweller Setting", - "Noble Court Subsetting", "Servitude And Captive Setting", "Outcast Subsetting", - "Professional Soldier Subsetting", - "Seafaring Setting", - "Religious Subsetting" + "Professional Soldier Subsetting" ] }, "Grave Robber": { - "time": 1, - "res": 1, + "time": 3, + "res": 7, "leads": [ - "Peasant", - "Villager", - "City", - "Court", "Servitude", "Outcast", - "Soldier", - "Seafaring", - "Religious" + "Soldier" ], "skills": [ [ - 3, - "" + 4, + "Ditch Digging", + "Graveyard-wise", + "Night Watch-wise", + "Shovel-wise" ] ], "traits": [ - 1, - "" + 2, + "Lunatic" ], - "requires": "", - "requires_expr": [], "key_leads": [ - "Peasant Setting", - "Villager Setting", - "City Dweller Setting", - "Noble Court Subsetting", "Servitude And Captive Setting", "Outcast Subsetting", - "Professional Soldier Subsetting", - "Seafaring Setting", - "Religious Subsetting" + "Professional Soldier Subsetting" ] }, "Spy": { - "time": 1, - "res": 1, + "time": 4, + "res": 10, + "stat": [ + [ + 1, + "m" + ] + ], "leads": [ - "Peasant", - "Villager", "City", - "Court", - "Servitude", "Outcast", - "Soldier", - "Seafaring", - "Religious" + "Soldier" ], "skills": [ [ - 3, - "" + 7, + "Inconspicuous", + "Stealthy", + "Falsehood", + "Forgery", + "Observation", + "Righteous Priest-wise" ] ], "traits": [ 1, - "" + "Furtive", + "Manhunter" + ], + "requires": "Cultist or Insurrectionist", + "requires_expr": [ + "death cultist", + "insurrectionist", + "cultist" ], - "requires": "", - "requires_expr": [], "key_leads": [ - "Peasant Setting", - "Villager Setting", "City Dweller Setting", - "Noble Court Subsetting", - "Servitude And Captive Setting", "Outcast Subsetting", - "Professional Soldier Subsetting", - "Seafaring Setting", - "Religious Subsetting" + "Professional Soldier Subsetting" ] }, "Factotum": { - "time": 1, - "res": 1, + "time": 7, + "res": 15, + "stat": [ + [ + 1, + "pm" + ] + ], "leads": [ - "Peasant", - "Villager", "City", - "Court", "Servitude", "Outcast", - "Soldier", - "Seafaring", - "Religious" + "Soldier" ], "skills": [ [ - 3, - "" + 7, + "Haggling", + "Persuasion", + "Hauling", + "Appraisal", + "Taxidermy", + "Local Law-wise" ] ], "traits": [ 1, - "" + "Polite", + "Efficient", + "Stoic" + ], + "requires": "Spy, Tomb Guard, Deranged, Evangelist or Insurrectionist", + "requires_expr": [ + "spy", + "tomb guard", + "evangelist", + "deranged", + "insurrectionist" ], - "requires": "", - "requires_expr": [], "key_leads": [ - "Peasant Setting", - "Villager Setting", "City Dweller Setting", - "Noble Court Subsetting", "Servitude And Captive Setting", "Outcast Subsetting", - "Professional Soldier Subsetting", - "Seafaring Setting", - "Religious Subsetting" + "Professional Soldier Subsetting" ] }, "Tomb Guard": { - "time": 1, - "res": 1, + "time": 4, + "res": 10, + "stat": [ + [ + 1, + "p" + ] + ], "leads": [ - "Peasant", - "Villager", - "City", - "Court", "Servitude", "Outcast", - "Soldier", - "Seafaring", - "Religious" + "Soldier" ], "skills": [ [ - 3, - "" + 5, + "Spear", + "Knives", + "Brawling", + "Walking Corpse-wise" ] ], "traits": [ 1, - "" + "Disfigured", + "Loyal" + ], + "requires": "Cultist, Grave Digger, Freebooter or any soldier lifepath", + "requires_expr": [ + "death cultist", + "grave robber", + "cultist", + "gravedigger", + "freebooter", + "professional soldier subsetting:runner", + "professional soldier subsetting:apprentice", + "professional soldier subsetting:musician", + "professional soldier subsetting:foot soldier", + "professional soldier subsetting:archer", + "professional soldier subsetting:crossbowman", + "professional soldier subsetting:sailor", + "professional soldier subsetting:herald", + "professional soldier subsetting:bannerman", + "professional soldier subsetting:scout", + "professional soldier subsetting:sergeant", + "professional soldier subsetting:veteran", + "professional soldier subsetting:cavalryman", + "professional soldier subsetting:journeyman", + "professional soldier subsetting:armorer", + "professional soldier subsetting:atilliator", + "professional soldier subsetting:chaplain", + "professional soldier subsetting:engineer", + "professional soldier subsetting:wizard of war", + "professional soldier subsetting:quartermaster", + "professional soldier subsetting:captain" ], - "requires": "", - "requires_expr": [], "key_leads": [ - "Peasant Setting", - "Villager Setting", - "City Dweller Setting", - "Noble Court Subsetting", "Servitude And Captive Setting", "Outcast Subsetting", - "Professional Soldier Subsetting", - "Seafaring Setting", - "Religious Subsetting" + "Professional Soldier Subsetting" ] }, "Death Priest": { - "time": 1, - "res": 1, + "time": 6, + "res": 25, + "stat": [ + [ + 1, + "m" + ] + ], "leads": [ - "Peasant", - "Villager", - "City", - "Court", - "Servitude", "Outcast", "Soldier", - "Seafaring", "Religious" ], "skills": [ [ - 3, - "" + 6, + "Command", + "Ritual", + "God of Death-wise", + "Death Cult-wise" ] ], "traits": [ - 1, - "" + 2, + "Creepy", + "Invocations Of The Damned", + "Iron Will", + "Cult Leader" + ], + "requires": "Venal Priest or Heretic Priest", + "requires_expr": [ + "venal priest", + "heretic priest" ], - "requires": "", - "requires_expr": [], "key_leads": [ - "Peasant Setting", - "Villager Setting", - "City Dweller Setting", - "Noble Court Subsetting", - "Servitude And Captive Setting", "Outcast Subsetting", "Professional Soldier Subsetting", - "Seafaring Setting", "Religious Subsetting" ] }, "Death Artist": { - "time": 1, - "res": 1, + "time": 10, + "res": 20, + "stat": [ + [ + 1, + "p," + ] + ], "leads": [ - "Peasant", - "Villager", - "City", - "Court", "Servitude", - "Outcast", - "Soldier", - "Seafaring", - "Religious" + "Outcast" ], "skills": [ [ - 3, - "" + 8, + "Death Art", + "Tomb-wise", + "Orc Servant-wise", + "Evil Necromancer-wise", + "Death Cult-wise" ] ], "traits": [ - 1, - "" + 3, + "Cynical", + "Mind Over Matter", + "Missing Limb", + "Paranoid Ear", + "Meticulous", + "Corrupted" + ], + "requires": "Evil Necromancer, Apt Pupil or Rogue Wizard", + "requires_expr": [ + "evil necromancer", + "apt pupil", + "rogue wizard" ], - "requires": "", - "requires_expr": [], "key_leads": [ - "Peasant Setting", - "Villager Setting", - "City Dweller Setting", - "Noble Court Subsetting", "Servitude And Captive Setting", - "Outcast Subsetting", - "Professional Soldier Subsetting", - "Seafaring Setting", - "Religious Subsetting" + "Outcast Subsetting" ] } }, - "Servant of the Dark Blood Setting": { - "Master of the Weak": { - "time": 1, - "res": 1, - "leads": [ - "Peasant", - "Villager", - "City", - "Court", - "Servitude", - "Outcast", - "Soldier", - "Seafaring", - "Religious" + "Servant Of The Dark Blood Subsetting": { + "Master Of The Weak": { + "time": 7, + "res": 8, + "stat": [ + [ + 1, + "pm" + ] ], "skills": [ [ - 3, - "" + 5, + "Death Art", + "Apocalypse-wise", + "Graveyard-wise", + "Murder-wise" ] ], "traits": [ 1, - "" + "Feared Above All" ], - "requires": "", - "requires_expr": [], - "key_leads": [ - "Peasant Setting", - "Villager Setting", - "City Dweller Setting", - "Noble Court Subsetting", - "Servitude And Captive Setting", - "Outcast Subsetting", - "Professional Soldier Subsetting", - "Seafaring Setting", - "Religious Subsetting" + "requires": "Knower Of Secrets", + "requires_expr": [ + "knower of secrets" ] } } diff --git a/src/data/wizard_skills.json b/src/data/wizard_skills.json new file mode 100755 index 0000000..92c08a9 --- /dev/null +++ b/src/data/wizard_skills.json @@ -0,0 +1,52 @@ +{ + "Alchemy": { + "roots": [ + "Perception" + ] + }, + "Bargaining": { + "roots": [ + "Will", + "Perception" + ] + }, + "Circination": { + "magic": 1, + "roots": [ + "Perception", + "Agility" + ] + }, + "Death Art": { + "magic": 1, + "roots": [ + "Will", + "Forte" + ] + }, + "Enchanting": { + "magic": 1, + "roots": [ + "Perception", + "Agility" + ] + }, + "Sorcery": { + "magic": 1, + "roots": [ + "Perception" + ] + }, + "Spirit Binding": { + "magic": 1, + "roots": [ + "Will" + ] + }, + "Summoning": { + "magic": 1, + "roots": [ + "Perception" + ] + } +} \ No newline at end of file diff --git a/src/data/wizard_traits.json b/src/data/wizard_traits.json new file mode 100755 index 0000000..df4cb4c --- /dev/null +++ b/src/data/wizard_traits.json @@ -0,0 +1,149 @@ +{ + "Always in the Way": { + "cost": 1, + "type": "character" + }, + "Assistant Pig-Keeper": { + "cost": 1, + "type": "character" + }, + "Brook No Fools": { + "cost": 7, + "type": "die", + "desc": "The spirit binder's art is not something to be trifled with! Their secrets are well kept because meddling fools will only cause irreparable harm to themselves and the domains with which they tamper. A summoner with this trait receives a fate point every time they rebuff an offer of help from a potential student (so that character does not earn a test toward learning the skill). The summoner receives a persona point when they actively thwart another character from learning the secrets of Spirit Binding, Summoning, or Circination." + }, + "Bully": { + "cost": 1, + "type": "character" + }, + "Corrupted": { + "cost": 3, + "type": "die", + "desc": "This character has opened their body and soul to the dark powers. They must open the Corrupted emotional attribute. Increase their starting rank by one." + }, + "Council of Mages": { + "cost": 6, + "type": "die", + "desc": "The Council of Mages is a small, secretive, yet powerful entity. This trait grants a 1D reputation and a 1D affiliation with this organization. This combines with other appropriate reputations and affiliations." + }, + "Creepy": { + "cost": 1, + "type": "character" + }, + "Cult Leader": { + "cost": 8, + "type": "die", + "desc": "Cult Leaders are charismatic and eccentric. This trait grants a 1D reputation and 1D affiliation with the Death Cult. This combines with other appropriate reputations and affiliations." + }, + "Unhinged": { + "cost": 1, + "type": "character" + }, + "Disfigured": { + "cost": 3, + "type": "die", + "desc": "This character has led a life of hardship and pain. They've been cut up, broken, and beaten down. This trait grants +1D to shrug off or grit teeth for any injury." + }, + "Evil": { + "cost": 1, + "type": "character" + }, + "Faust": { + "cost": 3, + "type": "die", + "desc": "When bargaining with the higher powers for something pure and innocent like love, gain a bonus persona point for each agreement you strike on behalf of the one you seek to protect or affect." + }, + "Feared Above All": { + "cost": 5, + "type": "die", + "desc": "For good reason or not, this character is feared by all who know them. +1D to Intimidation. Choose a 1D infamous reputation." + }, + "Fiery": { + "cost": 1, + "type": "character" + }, + "Disgruntled": { + "cost": 1, + "type": "character" + }, + "Furtive": { + "cost": 1, + "type": "character" + }, + "Graduate": { + "cost": 3, + "type": "die", + "desc": "This trait grants a 1D affiliation with a College of Magic. This combines with other appropriate and applicable affiliations." + }, + "Harried": { + "cost": 1, + "type": "character" + }, + "Hazed": { + "cost": 2, + "type": "die", + "desc": "This character may take a free inimical relationship with another character who was their senior in the College of Magic." + }, + "Impressive Hat": { + "cost": 3, + "type": "die", + "desc": "This character's hat is mightily impressive. It can be seen for miles! It's so impressive that people often remember the hat more than the person. This gives a 1D Reputation among the people of a given locale as the wearer of the really impressive hat, so long as the hat is being worn, of course. Wearing the hat also gives a +2 Ob to any Disguise or Inconspicuous test." + }, + "Invocations of the Damned": { + "cost": 5, + "type": "call_on", + "desc": "The Dark Priest swears their soul to fell powers. Like other priests, they must have a Belief that ties to their Faith in order to maintain the emotional attribute. If the player writes a second Belief tied to their faith in the dark gods and their service to them, the priest may use this trait as a call-on for Faith when that Belief comes into question." + }, + "Late": { + "cost": 1, + "type": "character" + }, + "Low Born": { + "cost": 2, + "type": "die", + "desc": "Low Born characters are born of unremarkable parents. They cannot trace their lineage to any nobility or to any historic or notable figures. They have a 1D infamous reputation in noble or elite circles due to their obvious lack of heritage. It also adds a +1 Ob disadvantage to any Inconspicuous tests in noble or courtly settings." + }, + "Master of Mages": { + "cost": 0, + "type": "die", + "desc": "The Headmaster of a College of Magic attained their position by rigorous pursuit of excellence and expertise in sorcery and magic. This trait grants a 2D repuation among mages and the halls of power as a Master of Mages." + }, + "Misunderstood": { + "cost": 2, + "type": "die", + "desc": "Choose a 1D infamous reputation. And suffer -1 to your body of argument whenever you're trying to explain your nature, position, meaning, or special insight." + }, + "Never A Moment Of Peace": { + "cost": 3, + "type": "die", + "desc": "This trait grants the character a 5 rps relationship. This relationship must be with a character who is always bothering or interrupting him. If that character is forced out of his life, someone new will come along. This character just attracts these sort of people! You may invest additional resource points and increase the value of this relationship." + }, + "Polite": { + "cost": 1, + "type": "character" + }, + "Speaker Of The Secret Language": { + "cost": 1, + "type": "character" + }, + "Spirit Familiar": { + "cost": 5, + "type": "die", + "desc": "This character has a familiar whose spirit is linked to their own. They can see through the familiar's eyes using the familiar's Perception stat. However, when using their familiar's eyes, a character with this trait cannot look through their own though other senses may still be employed. It takes two actions of concentration to engage their familiar's eyes, and two more actions to return their sight to their own eyes. This trait does not grant Low Speech. However the creature does understand its companion's wishes and will go where its master directs it to go, look at what its master directs it to look at, etc. A character with this trait feels the pain of their familiar. If the familiar suffers a light or greater wound, the master suffers a light wound. If the familiar is ever killed, the master suffers a traumatic wound. In the game, the character is physically unharmed, but mentally traumatized. Recovery and Treatment are as per a standard traumatic wound. This wound does not bleed out. A familiar uses the following stats: Wi G2, Pe G3, Ag B4, Sp B5, Po B3, Fo B3, Hea B4, Ref B4, Ste B5, MW B9. Choose its form: cat, doc, snake, bird, pig, rabbit, fox or similar. No large predators or beasts of burden. The animal must show some mark or quality that indicates it is not entirely of this world. For example, it must be hairless, one eyed, two-tailed, of large size or even just have a disturbing aura." + }, + "Suicidal": { + "cost": 5, + "type": "die", + "desc": "This character (instantly) earns a persona point every time he takes a mortal wound." + }, + "Versatile": { + "cost": 4, + "type": "die", + "desc": "The Master Sorcerer places their confidence in the art of sorcery. It is a versatile and potent art, and they know it intimately. If using Art Magic, reduce by one the number of tests required for Weaving Magic into the Fiber of my Being. If using the standard Sorcery rules, reduce their practicals aptitude by one. If using Practical Magic, they may take an additional category of magic. In addition, the player earns a persona point for pushing their character's magic in a dangerous or untried direction." + }, + "Well Traveled": { + "cost": 4, + "type": "die", + "desc": "The Speaker of Names wanders the lands and seas, communing with the spirits. This trait allows the player to take a new domain when their character travels to a new locale in play. The player may describe a memory their character has of this place or a place like it. They may describe when they traveled here before. The player then adds a new domain to their spirit binder at its base level (0). Once used, this trait becomes a character trait. To be clear, the domain is added during play at a time of the player's choosing, not during character burning." + } +} \ No newline at end of file diff --git a/src/lib/data.rb b/src/lib/data.rb index dfbb97b..8e9e648 100755 --- a/src/lib/data.rb +++ b/src/lib/data.rb @@ -1,8 +1,138 @@ require 'json' module CharredData + def self.merge_data!(to, from) + from.keys.each do |k| + to[k] = from[k] + end + end + + def self.lifepath_requirements(expr) + if expr.is_a? Numeric + [] + elsif expr.is_a? String + if expr.start_with? "+" + [] + else + expr + end + elsif expr.is_a? Array + (expr.map { |e| self.lifepath_requirements(e) }).flatten + else + [] + end + end + def self.load_wizard_burner(data) + puts 'Loading wizard burner' + file = File.read('data/lifepaths/wizard.json') + wizard_data = JSON.parse(file) + + file = File.read('data/wizard_skills.json') + wizard_skills = JSON.parse(file) + self.merge_data!(data[:skills], wizard_skills) + + file = File.read('data/wizard_traits.json') + wizard_traits = JSON.parse(file) + self.merge_data!(data[:traits], wizard_traits) + + man = data[:lifepaths]['man'] + + man['College of Magic Setting'] = wizard_data['College of Magic Setting'] + man['Death Cult Setting'] = wizard_data['Death Cult Setting'] + + self.merge_data!(data[:lifepaths]['orc']['Servant Of The Dark Blood Subsetting'], wizard_data['Servant Of The Dark Blood Subsetting']) + + [ + 'Peasant Setting', + 'Villager Setting', + 'City Dweller Setting', + 'Noble Court Subsetting', + 'Outcast Subsetting' + ].each do |setting| + self.merge_data!(man[setting], wizard_data[setting]) + end + + [ + 'Peasant Setting', + 'Villager Setting', + 'City Dweller Setting', + 'Seafaring Setting', + 'Servitude And Captive Setting' + ].each do |setting| + self.merge_data!(man[setting], { + 'Gifted Child' => wizard_data['Special Gifted Lifepaths']['Gifted Child'] + }) + end + + [ + 'Noble Court Subsetting', + 'Religious Subsetting', + 'Outcast Subsetting', + 'Professional Soldier Subsetting' + ].each do |setting| + self.merge_data!(man[setting], { + 'Apt Pupil' => wizard_data['Special Gifted Lifepaths']['Apt Pupil'] + }) + end + + leads_short = { + 'College of Magic Setting' => 'College', + 'Death Cult Setting' => 'Death', + } + + # backfill leads + leads_short.keys.each do |wiz_set| + wizard_data[wiz_set].keys.each do |wiz_lp| + lifepath = wizard_data[wiz_set][wiz_lp] + next if !lifepath['requires_expr'] + + requirements = self.lifepath_requirements(lifepath['requires_expr']) + + requirements.each do |req| + setting = nil + req_lp = req + setting, req_lp = req.split(':') if req.include? ':' + + man.keys.each do |man_set| + next if wiz_set.downcase == man_set.downcase + next if setting && setting != man_set.downcase + man[man_set].keys.each do |man_lp| + next if req_lp != man_lp.downcase + + #puts "adding #{wiz_set}:#{wiz_lp} lead to #{man_set}:#{man_lp}" + + man[man_set][man_lp]['key_leads'] |= [wiz_set] + man[man_set][man_lp]['leads'] |= [leads_short[wiz_set]] + end + end + end + end + end + + # backfill Apt Pupil == Neophyte Sorcerer connection + man.keys.each do |man_set| + man[man_set].keys.each do |man_lp| + requirements = self.lifepath_requirements(man[man_set][man_lp]['requires_expr']) + next if requirements.include? 'apt pupil' + requirements.each do |req| + setting = nil + req_lp = req + setting, req_lp = req.split(':') if req.include? ':' + + next unless req_lp.downcase == 'neophyte sorcerer' + + if man[man_set][man_lp]['requires_expr'].include? 'neophyte sorcerer' + man[man_set][man_lp]['requires_expr'] |= ['apt pupil'] + else + puts "warning, could not add apt pupil to deep requirements array at #{man_set}:#{man_lp}" + end + end + end + end + data[:lifepaths]['man'] = man + puts 'loaded!' data end diff --git a/src/lib/pdf.rb b/src/lib/pdf.rb index 17187a0..36a5874 100755 --- a/src/lib/pdf.rb +++ b/src/lib/pdf.rb @@ -29,7 +29,7 @@ class CharSheet pdf.font 'data/caliban.ttf' pdf.default_leading -4 - logger.info @character + # logger.info @character <<-GRID (0...40).each do |x| @@ -123,10 +123,15 @@ class CharSheet self.render_shade_exponent(pdf, ref_attr[0], ref_attr[1], [279, 396.5]) self.render_shade_exponent(pdf, mor_attr[0], mor_attr[1], [278.5, 346]) + ptgs = @character['ptgs'] + ["Su", "Li", "Mi", "Se", "Tr", "Mo"].each do |tol| + tol_c = ptgs[tol.downcase] + pdf.draw_text "#{tol}", :at => [29 + (19.5 * tol_c), 190], :size => @t2 + end + pdf.draw_text str_attr[1], :at => [264, 428], :size => @t2 pdf.draw_text hes_attr[1], :at => [53, 318], :size => @t2 - skills_left = @character['skills'][0...13] skills_right = @character['skills'][13...26] diff --git a/src/public/js/burning-serialize.js b/src/public/js/burning-serialize.js index 20a00f7..484b1cb 100755 --- a/src/public/js/burning-serialize.js +++ b/src/public/js/burning-serialize.js @@ -234,7 +234,6 @@ function convertCurrentCharacterToStruct($scope, appropriateWeapons) { } chardata.stats = stats; - var lifepathSkills = []; var generalSkills = []; var addSkillTo = function(list, displaySkill){ diff --git a/src/public/js/burning.js b/src/public/js/burning.js index 7accf41..1ea389d 100755 --- a/src/public/js/burning.js +++ b/src/public/js/burning.js @@ -1245,6 +1245,7 @@ function BurningCtrl($scope, $http, $modal, $timeout, settings, appropriateWeapo // :traits => [ // [name, type] // ] + // :ptgs => { :su => ["B1"], ... } // } @@ -1343,6 +1344,15 @@ function BurningCtrl($scope, $http, $modal, $timeout, settings, appropriateWeapo }); chardata.affiliations = res; + chardata.ptgs = { + "su": $scope.ptgs.su, + "li": $scope.ptgs.li, + "mi": $scope.ptgs.mi, + "se": $scope.ptgs.se, + "tr": $scope.ptgs.tr, + "mo": $scope.ptgs.mo, + }; + chardata.attr_mod_questions = convertAttributeModifierQuestionResultsForCharsheet($scope); return chardata; diff --git a/src/views/partials/help.erb b/src/views/partials/help.erb index 8fcf930..53347c0 100755 --- a/src/views/partials/help.erb +++ b/src/views/partials/help.erb @@ -33,6 +33,9 @@
  • Hints for Great Wolves
  • +
  • + Hints for Wizards +
  • @@ -195,6 +198,23 @@ The revised edition defined a 'Broken' trait for Great Wolves; in Charred it is named 'Broken Wolf'. Similarly the previous Hunting skill for wolves has been renamed to 'Wolfish Hunting'.

    +

    Wizards

    +

    + The wizard content is taken from the 'Wizard Burner' chapter of Burning Wheel Codex. Some liberties were taken to prevent + collision with existing traits. +

    +

    + The Demented Inventor lifepath trait 'Demented' was changed to 'Unhinged' to avoid a conflict with Great Wolf trait of the + same name and to preserve the mechanical flavor. +

    +

    + The Master Of The Weak lifepath trait 'Feared' was changed to 'Feared Above All' to avoid a conflict with the Roden trait + of the same name. +

    +

    + The Court Summoner lifepath trait 'Frustrated' was changed to 'Disgruntled' to avoid a conflict with the Roden trait of the + same name. +

    \ No newline at end of file diff --git a/src/views/partials/main.erb b/src/views/partials/main.erb index 971349f..4ef255d 100755 --- a/src/views/partials/main.erb +++ b/src/views/partials/main.erb @@ -448,6 +448,10 @@
    Type
    +
    +
    + Description +
    @@ -460,6 +464,10 @@
    {{trait.typeForDisplay()}}
    +
    +
    +

    {{trait.desc}}

    +
    @@ -475,6 +483,9 @@
    +
    +

    {{trait.desc}}

    +
    @@ -487,6 +498,10 @@
    {{trait.typeForDisplay()}}
    +
    +
    +

    {{trait.desc}}

    +