Compare commits

...

51 Commits

Author SHA1 Message Date
Daniel Asher Resnick 32c91f437d Merge pull request 'Custom stock files and data' (#11) from custom-stocks into main 9 months ago
Daniel Asher Resnick 381c65d44d Version bump for 3.0.0 release 9 months ago
Daniel Asher Resnick 55e8b907b9 3.0.0 Changelog draft 9 months ago
Daniel Asher Resnick cc968e00e6 Merge branch 'main' into born-expansion 9 months ago
Daniel Asher Resnick 52ec9d5db7 Fix settings logic 1 year ago
Daniel Asher Resnick 63a8e05401 Check subsetting based on new born property 1 year ago
Daniel Asher Resnick e9361b625b Check for born using property instead of name 1 year ago
Daniel Asher Resnick bac1626f31 Add 'born' field to born lifepaths 1 year ago
Daniel Asher Resnick 2d6d534798 Denote intended release of 3.0 1 year ago
Daniel Asher Resnick 071ebe801d Use ko_deep_merge for incremental data removal 1 year ago
Daniel Asher Resnick 582379787f Introduce deep_merge 1 year ago
Daniel Asher Resnick 00e3f569fe Increase information in burning-service debugging 1 year ago
Daniel Asher Resnick c7306cbacf Add data for a test stock 1 year ago
Daniel Asher Resnick 2fd4b625ce Fix custom stock loading using put_or_merge 1 year ago
Daniel Asher Resnick 6e7c8237a7 Define put_or_merge 1 year ago
Daniel Asher Resnick 0b3e725c85 Actually implement custom stock loading... 1 year ago
Daniel Asher Resnick 48cda4860a Merge branch 'main' into custom-stocks 1 year ago
Daniel Asher Resnick a3fe5f508a Merge branch 'stock-ruby-class' into custom-stocks 1 year ago
Daniel Asher Resnick c8adc19846 Load stock data on stock change or char upload 1 year ago
Daniel Asher Resnick 30f477a2e0 Replace BurningData events with Promise handlers 1 year ago
Daniel Asher Resnick 0782b4465e Debug behaviour should default to false 1 year ago
Daniel Asher Resnick 42ffa31a3f Remove debug logging 1 year ago
Daniel Asher Resnick a98115c647 Use Fetch API and thenify BurningData 1 year ago
Daniel Asher Resnick 849b957a7b Wrap (and update loading of) resources 1 year ago
Daniel Asher Resnick 38a49c8327 Switch all lifepath files to wrapped format 1 year ago
Daniel Asher Resnick 4b4b847644 Move some lifepaths to wrapped format 1 year ago
Daniel Asher Resnick f5d94d1d67 wip 1 year ago
Daniel Asher Resnick 5091396638 Merge branch 'stock-ruby-class' into custom-stocks 1 year ago
Daniel Asher Resnick c4e93b2142 Merge branch 'main' into custom-stocks 1 year ago
Daniel Asher Resnick 74ed09d830 Lookup stocks by adjective field 1 year ago
Daniel Asher Resnick bb908d9bfd Add adjectives to stock files 1 year ago
Daniel Asher Resnick 117365ed8e Fix angular interpolation error 1 year ago
Daniel Asher Resnick fc9edd2b48 On demand data loading 1 year ago
Daniel Asher Resnick 302f758bf0 Replace references to stock_objs with just stocks 1 year ago
Daniel Asher Resnick 897b9ca58c Remove now-redundant stocks key in the data object 1 year ago
Daniel Asher Resnick e1b52b08f5 Fixed some code referencing starting starts 1 year ago
Daniel Asher Resnick e3077d6048 Delete starting stats files 1 year ago
Daniel Asher Resnick a6366b0c7b Remove common traits from lifepaths 1 year ago
Daniel Asher Resnick 4e7d70c51f Use starting stat data from stock objects 1 year ago
Daniel Asher Resnick e7b487f8a3 Remove settings from stock object 1 year ago
Daniel Asher Resnick 0d92d0beb2 Use common traits from stock object 1 year ago
Daniel Asher Resnick 19e2ba9657 Use stride data from stock objects 1 year ago
Daniel Asher Resnick c7a3335bec Load new-style stock files 1 year ago
Daniel Asher Resnick 9d3c8b8870 Add new style stock files for Gold stocks 1 year ago
Daniel Asher Resnick e5d478786e In js, load stock data from stock_objs 1 year ago
Daniel Asher Resnick 8ec40eba13 Load troll data 1 year ago
Daniel Asher Resnick cf351b0c24 wip 1 year ago
Daniel Asher Resnick 3f5b2f4219 Stub expanded stock class 1 year ago
Daniel Asher Resnick 43cca46dde Begin moving stock data to objects 1 year ago
Daniel Asher Resnick 7d8540d69a Stub custom stock parsing 1 year ago
Daniel Asher Resnick cbcbd23955 wip 1 year ago
  1. 12
      CHANGELOG.md
  2. 1
      Gemfile
  3. 2
      Gemfile.lock
  4. 16
      src/app.rb
  5. 1
      src/data/custom/.gitignore
  6. 551
      src/data/dark_elf/lifepaths.json
  7. 231
      src/data/dark_elf/resources.json
  8. 3837
      src/data/gold/lifepaths/dwarf.json
  9. 3969
      src/data/gold/lifepaths/elf.json
  10. 23373
      src/data/gold/lifepaths/man.json
  11. 3061
      src/data/gold/lifepaths/orc.json
  12. 3325
      src/data/gold/lifepaths/roden.json
  13. 1835
      src/data/gold/lifepaths/wolf.json
  14. 307
      src/data/gold/resources/dwarf.json
  15. 355
      src/data/gold/resources/elf.json
  16. 871
      src/data/gold/resources/man.json
  17. 425
      src/data/gold/resources/orc.json
  18. 281
      src/data/gold/resources/roden.json
  19. 87
      src/data/gold/resources/wolf.json
  20. 114
      src/data/gold/starting_stat_pts/dwarf.json
  21. 146
      src/data/gold/starting_stat_pts/elf.json
  22. 90
      src/data/gold/starting_stat_pts/man.json
  23. 98
      src/data/gold/starting_stat_pts/orc.json
  24. 74
      src/data/gold/starting_stat_pts/roden.json
  25. 58
      src/data/gold/starting_stat_pts/wolf.json
  26. 130
      src/data/gold/stocks/dwarf.json
  27. 161
      src/data/gold/stocks/elf.json
  28. 99
      src/data/gold/stocks/man.json
  29. 114
      src/data/gold/stocks/orc.json
  30. 90
      src/data/gold/stocks/roden.json
  31. 75
      src/data/gold/stocks/wolf.json
  32. 1151
      src/data/troll/lifepaths.json
  33. 117
      src/data/troll/resources.json
  34. 82
      src/data/troll/starting_stat_pts.json
  35. 100
      src/data/troll/stock.json
  36. 2330
      src/data/wizard/lifepaths.json
  37. 15
      src/lib/data.rb
  38. 27
      src/lib/data/custom.rb
  39. 8
      src/lib/data/dark_elf.rb
  40. 22
      src/lib/data/gold.rb
  41. 17
      src/lib/data/troll.rb
  42. 5
      src/lib/data/wizard.rb
  43. 34
      src/lib/stock.rb
  44. 47
      src/public/js/burning-serialize.js
  45. 205
      src/public/js/burning-service.js
  46. 452
      src/public/js/burning.js
  47. 4
      src/public/js/server_settings.js
  48. 9
      src/views/partials/main.erb
  49. 133
      tests/data/custom/test.lifepaths
  50. 25
      tests/data/custom/test.resources
  51. 39
      tests/data/custom/test.skills
  52. 95
      tests/data/custom/test.stock
  53. 55
      tests/data/custom/test.traits

@ -11,6 +11,16 @@ and this project adheres to [Semantic Versioning](semver).
- Custom upload for your own data files
- Updates to Roden and Great Wolves files (currently the data comes from Monster Burner and not Codex)
## [3.0.0] - 2023-09-03
### Added
- Custom stocks can now be added to a server
- Stock data moved from code to dedicated data file
- Data files split into stock, lifepath, skills, and traits files, with designated extensions
- "Born" lifepaths with arbitrary names
### Fixed
- Spite shade calculation
## [2.3.0] - 2019-07-28
### Added
- Display emotional attribute traits on PDF
@ -59,4 +69,4 @@ and this project adheres to [Semantic Versioning](semver).
[changelog]: https://keepachangelog.com/en/1.0.0/
[semver]: https://semver.org/spec/v2.0.0.html
[semver]: https://semver.org/spec/v2.0.0.html

@ -5,6 +5,7 @@ gem 'sinatra'
gem 'sinatra-contrib'
gem 'prawn'
gem 'prawn-templates'
gem 'deep_merge', '~> 1.2', '>= 1.2.1'
group :development do
gem 'rerun'

@ -4,6 +4,7 @@ GEM
Ascii85 (1.1.0)
afm (0.2.2)
daemons (1.4.1)
deep_merge (1.2.2)
eventmachine (1.2.7)
ffi (1.15.5)
hashery (2.1.2)
@ -58,6 +59,7 @@ PLATFORMS
x86_64-linux
DEPENDENCIES
deep_merge (~> 1.2, >= 1.2.1)
prawn
prawn-templates
rerun

@ -49,24 +49,20 @@ get '/traits' do
json DATA[:traits]
end
get '/lifepaths/:stock' do
if DATA[:stocks].include? params['stock']
json DATA[:lifepaths][params['stock']]
else
404
end
get '/stocks' do
json DATA[:stocks]
end
get '/starting_stat_pts/:stock' do
if DATA[:stocks].include? params['stock']
json DATA[:stat_pts][params['stock']]
get '/lifepaths/:stock' do
if DATA[:stocks].keys.include? params['stock']
json DATA[:lifepaths][params['stock']]
else
404
end
end
get '/resources/:stock' do
if DATA[:stocks].include? params['stock']
if DATA[:stocks].keys.include? params['stock']
json DATA[:resources][params['stock']]
else
404

@ -1,296 +1,299 @@
{
"Path Of Spite Subsetting": {
"Griever": {
"time": 3,
"res": 0,
"skills": [
[
3,
"Sorrow Of Truth",
"Dark Elf-wise"
]
],
"traits": [
1,
"Spite"
]
},
"Wastrel": {
"time": 25,
"res": 3,
"skills": [
[
6,
"Scavenging",
"Brawling",
"Forest-wise",
"Wasteland-wise",
"Animal-wise"
]
],
"traits": [
2,
"Filthy",
"Feral Elf"
],
"requires": "Griever",
"requires_expr": [
"griever"
]
},
"Thief": {
"time": 18,
"res": 6,
"stat": [
[
"stock": "elf",
"settings": {
"Path Of Spite Subsetting": {
"Griever": {
"time": 3,
"res": 0,
"skills": [
[
3,
"Sorrow Of Truth",
"Dark Elf-wise"
]
],
"traits": [
1,
"pm"
"Spite"
]
],
"skills": [
[
6,
"Lock Pick",
"Stealthy",
"Climbing",
"Sleight Of Hand",
"Dirge Of Night"
},
"Wastrel": {
"time": 25,
"res": 3,
"skills": [
[
6,
"Scavenging",
"Brawling",
"Forest-wise",
"Wasteland-wise",
"Animal-wise"
]
],
"traits": [
2,
"Filthy",
"Feral Elf"
],
"requires": "Griever",
"requires_expr": [
"griever"
]
],
"traits": [
1,
"Thief"
],
"requires": "Griever",
"requires_expr": [
"griever"
]
},
"Assassin": {
"time": 15,
"res": 6,
"stat": [
[
},
"Thief": {
"time": 18,
"res": 6,
"stat": [
[
1,
"pm"
]
],
"skills": [
[
6,
"Lock Pick",
"Stealthy",
"Climbing",
"Sleight Of Hand",
"Dirge Of Night"
]
],
"traits": [
1,
"p"
]
],
"skills": [
[
7,
"Intimidation",
"Poisons",
"Escape Artist",
"Knives",
"Garotte",
"Keen Of Terror"
]
],
"traits": [
1,
"Murderous",
"Callous",
"Cold Blooded"
],
"requires": "Griever",
"requires_expr": [
"griever"
]
},
"Stalker": {
"time": 20,
"res": 8,
"skills": [
[
8,
"Hunting",
"Elf-wise",
"Tracking",
"Trapper",
"Observation",
"Stealthy",
"Throwing",
"Javelin",
"Supplication To Shadows"
"Thief"
],
"requires": "Griever",
"requires_expr": [
"griever"
]
],
"traits": [
1,
"Saturnine"
],
"requires": "Griever",
"requires_expr": [
"griever"
]
},
"Deceiver": {
"time": 35,
"res": 10,
"stat": [
[
},
"Assassin": {
"time": 15,
"res": 6,
"stat": [
[
1,
"p"
]
],
"skills": [
[
7,
"Intimidation",
"Poisons",
"Escape Artist",
"Knives",
"Garotte",
"Keen Of Terror"
]
],
"traits": [
1,
"m"
]
],
"skills": [
[
7,
"Sleight Of Hand",
"Disguise",
"Inconspicuous",
"Rhyme Of The Unraveller"
"Murderous",
"Callous",
"Cold Blooded"
],
"requires": "Griever",
"requires_expr": [
"griever"
]
],
"traits": [
1,
"Deceptive"
],
"requires": "Griever",
"requires_expr": [
"griever"
]
},
"Liar": {
"time": 25,
"res": 8,
"stat": [
[
},
"Stalker": {
"time": 20,
"res": 8,
"skills": [
[
8,
"Hunting",
"Elf-wise",
"Tracking",
"Trapper",
"Observation",
"Stealthy",
"Throwing",
"Javelin",
"Supplication To Shadows"
]
],
"traits": [
1,
"m"
]
],
"skills": [
[
6,
"Falsehood",
"Soothing Platitudes",
"Persuasion",
"Twisted Tongue"
"Saturnine"
],
"requires": "Griever",
"requires_expr": [
"griever"
]
],
"traits": [
1,
"Compulsive Liar"
],
"requires": "Griever",
"requires_expr": [
"griever"
]
},
"Siren": {
"time": 55,
"res": 20,
"stat": [
[
},
"Deceiver": {
"time": 35,
"res": 10,
"stat": [
[
1,
"m"
]
],
"skills": [
[
7,
"Sleight Of Hand",
"Disguise",
"Inconspicuous",
"Rhyme Of The Unraveller"
]
],
"traits": [
1,
"pm"
]
],
"skills": [
[
9,
"Seduction",
"Etiquette",
"Persuasion",
"Soothing Platitudes",
"Gossip-wise",
"Fugue Of Discord",
"Litany Of Fools"
"Deceptive"
],
"requires": "Griever",
"requires_expr": [
"griever"
]
],
"traits": [
2,
"Charismatic",
"Femme Fatale/Homme Fatale"
],
"requires": "Assassin, Deceiver or Liar",
"requires_expr": [
"assassin",
"deceiver",
"liar"
]
},
"Eremite": {
"time": 150,
"res": 15,
"stat": [
[
},
"Liar": {
"time": 25,
"res": 8,
"stat": [
[
1,
"m"
]
],
"skills": [
[
6,
"Falsehood",
"Soothing Platitudes",
"Persuasion",
"Twisted Tongue"
]
],
"traits": [
1,
"m"
]
],
"skills": [
[
12,
"Philosophy",
"Ugly Truth",
"Obscure History",
"Symbology",
"Strategy",
"Elf-wise",
"Orc-wise",
"Dwarf-wise",
"Man-wise",
"Paean To The Dark Fire"
"Compulsive Liar"
],
"requires": "Griever",
"requires_expr": [
"griever"
]
],
"traits": [
2,
"Remote",
"Cold"
],
"requires": "Siren, Wastrel or Stalker",
"requires_expr": [
"siren",
"wastrel",
"stalker"
]
},
"Recluse": {
"time": 225,
"res": 25,
"stat": [
[
1,
"p"
},
"Siren": {
"time": 55,
"res": 20,
"stat": [
[
1,
"pm"
]
],
"skills": [
[
9,
"Seduction",
"Etiquette",
"Persuasion",
"Soothing Platitudes",
"Gossip-wise",
"Fugue Of Discord",
"Litany Of Fools"
]
],
"traits": [
2,
"Charismatic",
"Femme Fatale/Homme Fatale"
],
"requires": "Assassin, Deceiver or Liar",
"requires_expr": [
"assassin",
"deceiver",
"liar"
]
],
"skills": [
[
},
"Eremite": {
"time": 150,
"res": 15,
"stat": [
[
1,
"m"
]
],
"skills": [
[
12,
"Philosophy",
"Ugly Truth",
"Obscure History",
"Symbology",
"Strategy",
"Elf-wise",
"Orc-wise",
"Dwarf-wise",
"Man-wise",
"Paean To The Dark Fire"
]
],
"traits": [
2,
"Ancient History",
"Dwarf-wise",
"Elven Politics-wise",
"Cut Of The Quickened Mind"
"Remote",
"Cold"
],
[
5,
"General"
"requires": "Siren, Wastrel or Stalker",
"requires_expr": [
"siren",
"wastrel",
"stalker"
]
],
"traits": [
1,
"Vengeful"
],
"requires": "Eremite or any three Dark Elf lifepaths",
"requires_expr": [
"+or",
[
"eremite"
},
"Recluse": {
"time": 225,
"res": 25,
"stat": [
[
1,
"p"
]
],
"skills": [
[
2,
"Ancient History",
"Dwarf-wise",
"Elven Politics-wise",
"Cut Of The Quickened Mind"
],
[
5,
"General"
]
],
"traits": [
1,
"Vengeful"
],
[
"+has_n_lifepaths_in",
3,
"path of spite subsetting:griever",
"path of spite subsetting:wastrel",
"path of spite subsetting:thief",
"path of spite subsetting:assassin",
"path of spite subsetting:stalker",
"path of spite subsetting:deceiver",
"path of spite subsetting:liar",
"path of spite subsetting:siren"
"requires": "Eremite or any three Dark Elf lifepaths",
"requires_expr": [
"+or",
[
"eremite"
],
[
"+has_n_lifepaths_in",
3,
"path of spite subsetting:griever",
"path of spite subsetting:wastrel",
"path of spite subsetting:thief",
"path of spite subsetting:assassin",
"path of spite subsetting:stalker",
"path of spite subsetting:deceiver",
"path of spite subsetting:liar",
"path of spite subsetting:siren"
]
]
]
}
}
}
}
}

@ -1,114 +1,117 @@
[
{
"name": "Bitter Poison",
"type": "gear",
"rp": 10
},
{
"name": "Spiteful Poison",
"type": "gear",
"rp": 20
},
{
"name": "Lock Picks",
"type": "gear",
"rp": 10
},
{
"name": "Long Knife",
"type": "gear",
"rp": 5
},
{
"name": "Barbed Javelins",
"type": "gear",
"rp": 3
},
{
"name": "Garrote",
"type": "gear",
"rp": 3
},
{
"name": "Caltrops",
"type": "gear",
"rp": 3
},
{
"name": "Tools Of The Trade",
"type": "gear",
"rp": 9
},
{
"name": "Cloak Of Darkness",
"type": "gear",
"rp": 30
},
{
"name": "Climbing Claws",
"type": "gear",
"rp": 5
},
{
"name": "Remote Refuge",
"type": "property",
"resources": [
{
"name": "Wasteland",
"rp": 20
},
{
"name": "Isolated Manor And Moorland",
"rp": 50
},
{
"name": "Hidden Fortress",
"rp": 100
},
{
"name": "Dark Forest, Cove Or Lonely Mountain",
"rp": 150
},
{
"name": "Safe House",
"rp": 25
}
]
},
{
"name": "Morlin Armor",
"type": "gear",
"resources": [
{
"name": "Light Mail",
"rp": 30
},
{
"name": "Heavy Mail",
"rp": 40
},
{
"name": "Plated Mail",
"rp": 100
}
]
},
{
"name": "Morlin Weapons",
"type": "gear",
"resources": [
{
"name": "+1 speed",
"rp": 15
},
{
"name": "+1 VA",
"rp": 15
},
{
"name": "+1 Power",
"rp": 30
}
]
}
]
{
"stock": "elf",
"resources": [
{
"name": "Bitter Poison",
"type": "gear",
"rp": 10
},
{
"name": "Spiteful Poison",
"type": "gear",
"rp": 20
},
{
"name": "Lock Picks",
"type": "gear",
"rp": 10
},
{
"name": "Long Knife",
"type": "gear",
"rp": 5
},
{
"name": "Barbed Javelins",
"type": "gear",
"rp": 3
},
{
"name": "Garrote",
"type": "gear",
"rp": 3
},
{
"name": "Caltrops",
"type": "gear",
"rp": 3
},
{
"name": "Tools Of The Trade",
"type": "gear",
"rp": 9
},
{
"name": "Cloak Of Darkness",
"type": "gear",
"rp": 30
},
{
"name": "Climbing Claws",
"type": "gear",
"rp": 5
},
{
"name": "Remote Refuge",
"type": "property",
"resources": [
{
"name": "Wasteland",
"rp": 20
},
{
"name": "Isolated Manor And Moorland",
"rp": 50
},
{
"name": "Hidden Fortress",
"rp": 100
},
{
"name": "Dark Forest, Cove Or Lonely Mountain",
"rp": 150
},
{
"name": "Safe House",
"rp": 25
}
]
},
{
"name": "Morlin Armor",
"type": "gear",
"resources": [
{
"name": "Light Mail",
"rp": 30
},
{
"name": "Heavy Mail",
"rp": 40
},
{
"name": "Plated Mail",
"rp": 100
}
]
},
{
"name": "Morlin Weapons",
"type": "gear",
"resources": [
{
"name": "+1 speed",
"rp": 15
},
{
"name": "+1 VA",
"rp": 15
},
{
"name": "+1 Power",
"rp": 30
}
]
}
]
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,152 +1,155 @@
[
{
"name": "Shoddy Arms",
"rp": 5,
"type": "gear"
},
{
"name": "Dwarven Arms",
"rp": 20,
"type": "gear"
},
{
"name": "Shoddy Crossbow",
"rp": 6,
"type": "gear"
},
{
"name": "Dwarven Arbalest",
"rp": 20,
"type": "gear"
},
{
"name": "Dwarven-made Light Mail",
"rp": 9,
"type": "gear"
},
{
"name": "Dwarven-made Heavy Mail",
"rp": 10,
"type": "gear"
},
{
"name": "Dwarven-made Plated Mail",
"rp": 20,
"type": "gear"
},
{
"name": "Dwarven Mail",
"rp": 100,
"type": "gear"
},
{
"name": "Forge Mask",
"rp": 40,
"type": "gear"
},
{
"name": "Dwarven Shield",
"rp": 20,
"type": "gear"
},
{
"name": "Riding Mount Or Pack Animal",
"rp": 8,
"type": "gear"
},
{
"name": "Clothes",
"rp": 1,
"type": "gear"
},
{
"name": "Traveling Gear",
"rp": 1,
"type": "gear"
},
{
"name": "Sturdy Shoes",
"rp": 1,
"type": "gear"
},
{
"name": "Finery",
"rp": 5,
"type": "gear"
},
{
"name": "Chronicles",
"rp": 15,
"type": "gear"
},
{
"name": "Keg O' Nog",
"rp": 20,
"type": "gear"
},
{
"name": "Small Dwarven House",
"rp": 10,
"type": "property"
},
{
"name": "Large Dwarven House",
"rp": 15,
"type": "property"
},
{
"name": "A Dwarven Hall",
"rp": 30,
"type": "property"
},
{
"name": "A Graybeard's Hold",
"rp": 40,
"type": "property"
},
{
"name": "An Engineer's Hold",
"rp": 45,
"type": "property"
},
{
"name": "A Master Artificer's Hold",
"rp": 60,
"type": "property"
},
{
"name": "A Warden's Hold",
"rp": 75,
"type": "property"
},
{
"name": "A High Captain's Hold",
"rp": 90,
"type": "property"
},
{
"name": "A Prince's Hold",
"rp": 105,
"type": "property"
},
{
"name": "A Workshop",
"rp": 60,
"type": "property"
},
{
"name": "Dwarven Tools",
"rp": 10,
"type": "gear"
},
{
"name": "Shoddy Tools",
"rp": 5,
"type": "gear"
},
{
"name": "Carts And Baggage",
"rp": 15,
"type": "gear"
}
]
{
"stock": "dwarf",
"resources": [
{
"name": "Shoddy Arms",
"rp": 5,
"type": "gear"
},
{
"name": "Dwarven Arms",
"rp": 20,
"type": "gear"
},
{
"name": "Shoddy Crossbow",
"rp": 6,
"type": "gear"
},
{
"name": "Dwarven Arbalest",
"rp": 20,
"type": "gear"
},
{
"name": "Dwarven-made Light Mail",
"rp": 9,
"type": "gear"
},
{
"name": "Dwarven-made Heavy Mail",
"rp": 10,
"type": "gear"
},
{
"name": "Dwarven-made Plated Mail",
"rp": 20,
"type": "gear"
},
{
"name": "Dwarven Mail",
"rp": 100,
"type": "gear"
},
{
"name": "Forge Mask",
"rp": 40,
"type": "gear"
},
{
"name": "Dwarven Shield",
"rp": 20,
"type": "gear"
},
{
"name": "Riding Mount Or Pack Animal",
"rp": 8,
"type": "gear"
},
{
"name": "Clothes",
"rp": 1,
"type": "gear"
},
{
"name": "Traveling Gear",
"rp": 1,
"type": "gear"
},
{
"name": "Sturdy Shoes",
"rp": 1,
"type": "gear"
},
{
"name": "Finery",
"rp": 5,
"type": "gear"
},
{
"name": "Chronicles",
"rp": 15,
"type": "gear"
},
{
"name": "Keg O' Nog",
"rp": 20,
"type": "gear"
},
{
"name": "Small Dwarven House",
"rp": 10,
"type": "property"
},
{
"name": "Large Dwarven House",
"rp": 15,
"type": "property"
},
{
"name": "A Dwarven Hall",
"rp": 30,
"type": "property"
},
{
"name": "A Graybeard's Hold",
"rp": 40,
"type": "property"
},
{
"name": "An Engineer's Hold",
"rp": 45,
"type": "property"
},
{
"name": "A Master Artificer's Hold",
"rp": 60,
"type": "property"
},
{
"name": "A Warden's Hold",
"rp": 75,
"type": "property"
},
{
"name": "A High Captain's Hold",
"rp": 90,
"type": "property"
},
{
"name": "A Prince's Hold",
"rp": 105,
"type": "property"
},
{
"name": "A Workshop",
"rp": 60,
"type": "property"
},
{
"name": "Dwarven Tools",
"rp": 10,
"type": "gear"
},
{
"name": "Shoddy Tools",
"rp": 5,
"type": "gear"
},
{
"name": "Carts And Baggage",
"rp": 15,
"type": "gear"
}
]
}

@ -1,176 +1,179 @@
[
{
"name": "Run Of The Mill Bow",
"type": "gear",
"rp": 5
},
{
"name": "Run Of The Mill Arms",
"type": "gear",
"rp": 5
},
{
"name": "Reinforced Leather",
"type": "gear",
"rp": 3
},
{
"name": "Light Mail",
"type": "gear",
"rp": 6
},
{
"name": "Heavy Mail",
"type": "gear",
"rp": 10
},
{
"name": "Plated Mail",
"type": "gear",
"rp": 20
},
{
"name": "Elven Armor",
"type": "gear",
"resources": [
{
"name": "Gambeson",
"rp": 9
},
{
"name": "Reinforced Leather",
"resources": null,
"rp": 20
},
{
"name": "Light Mail",
"resources": null,
"rp": 30
},
{
"name": "Heavy Mail",
"rp": 40
},
{
"name": "Plated Mail",
"rp": 75
}
]
},
{
"name": "Elven Arms",
"type": "gear",
"rp": 15
},
{
"name": "Elven Bow",
"type": "gear",
"rp": 25
},
{
"name": "Elven Cloak",
"type": "gear",
"rp": 30
},
{
"name": "Elven Steed",
"type": "gear",
"rp": 8
},
{
"name": "Elven Clothes",
"type": "gear",
"rp": 2
},
{
"name": "Elven Shoes",
"type": "gear",
"rp": 1
},
{
"name": "Elven Finery",
"type": "gear",
"rp": 5
},
{
"name": "Elven Rope",
"type": "gear",
"rp": 12
},
{
"name": "Elven Bread",
"type": "gear",
"rp": 10
},
{
"name": "Elven Mirrorwine",
"type": "gear",
"rp": 8
},
{
"name": "Starlight",
"type": "gear",
"rp": 50
},
{
"name": "Tome Of Lore",
"type": "gear",
"rp": 20
},
{
"name": "Elven Instrument",
"type": "gear",
"rp": 6
},
{
"name": "Personal Effects",
"type": "gear",
"rp": 1
},
{
"name": "Elven Smithy",
"type": "property",
"rp": 50
},
{
"name": "Artisan's Shop",
"type": "property",
"rp": 60
},
{
"name": "Skill Tools",
"type": "gear",
"rp": 9
},
{
"name": "Elven Ship",
"type": "gear",
"rp": 80
},
{
"name": "Elven Land",
"type": "property",
"resources": [
{
"name": "Pastoral",
"rp": 20
},
{
"name": "Large Country Manor And Land",
"rp": 50
},
{
"name": "Palace",
"rp": 100
},
{
"name": "A Forest, Bay Or Mountain",
"rp": 150
},
{
"name": "Apartment In The Citadel",
"rp": 25
}
]
}
]
{
"stock": "elf",
"resources": [
{
"name": "Run Of The Mill Bow",
"type": "gear",
"rp": 5
},
{
"name": "Run Of The Mill Arms",
"type": "gear",
"rp": 5
},
{
"name": "Reinforced Leather",
"type": "gear",
"rp": 3
},
{
"name": "Light Mail",
"type": "gear",
"rp": 6
},
{
"name": "Heavy Mail",
"type": "gear",
"rp": 10
},
{
"name": "Plated Mail",
"type": "gear",
"rp": 20
},
{
"name": "Elven Armor",
"type": "gear",
"resources": [
{
"name": "Gambeson",
"rp": 9
},
{
"name": "Reinforced Leather",
"resources": null,
"rp": 20
},
{
"name": "Light Mail",
"resources": null,
"rp": 30
},
{
"name": "Heavy Mail",
"rp": 40
},
{
"name": "Plated Mail",
"rp": 75
}
]
},
{
"name": "Elven Arms",
"type": "gear",
"rp": 15
},
{
"name": "Elven Bow",
"type": "gear",
"rp": 25
},
{
"name": "Elven Cloak",
"type": "gear",
"rp": 30
},
{
"name": "Elven Steed",
"type": "gear",
"rp": 8
},
{
"name": "Elven Clothes",
"type": "gear",
"rp": 2
},
{
"name": "Elven Shoes",
"type": "gear",
"rp": 1
},
{
"name": "Elven Finery",
"type": "gear",
"rp": 5
},
{
"name": "Elven Rope",
"type": "gear",
"rp": 12
},
{
"name": "Elven Bread",
"type": "gear",
"rp": 10
},
{
"name": "Elven Mirrorwine",
"type": "gear",
"rp": 8
},
{
"name": "Starlight",
"type": "gear",
"rp": 50
},
{
"name": "Tome Of Lore",
"type": "gear",
"rp": 20
},
{
"name": "Elven Instrument",
"type": "gear",
"rp": 6
},
{
"name": "Personal Effects",
"type": "gear",
"rp": 1
},
{
"name": "Elven Smithy",
"type": "property",
"rp": 50
},
{
"name": "Artisan's Shop",
"type": "property",
"rp": 60
},
{
"name": "Skill Tools",
"type": "gear",
"rp": 9
},
{
"name": "Elven Ship",
"type": "gear",
"rp": 80
},
{
"name": "Elven Land",
"type": "property",
"resources": [
{
"name": "Pastoral",
"rp": 20
},
{
"name": "Large Country Manor And Land",
"rp": 50
},
{
"name": "Palace",
"rp": 100
},
{
"name": "A Forest, Bay Or Mountain",
"rp": 150
},
{
"name": "Apartment In The Citadel",
"rp": 25
}
]
}
]
}

@ -1,434 +1,437 @@
[
{
"name": "Arms",
"type": "gear",
"resources": [
{
"name": "Poor Quality",
"rp": 3
},
{
"name": "Run Of The Mill Quality",
"rp": 5
},
{
"name": "Superior Quality",
"rp": 20
}
]
},
{
"name": "Missile Weapons",
"type": "gear",
"resources": [
{
"name": "Throwing Weapons",
"resources": [
{
"name": "Poor Quality",
"rp": 2
},
{
"name": "Run Of The Mill Quality",
"rp": 3
},
{
"name": "Superior Quality",
"rp": 9
}
]
},
{
"name": "Hunting Bow",
"resources": [
{
"name": "Poor Quality",
"rp": 3
},
{
"name": "Run Of The Mill Quality",
"rp": 5
},
{
"name": "Superior Quality",
"rp": 15
}
]
},
{
"name": "Great Bow",
"resources": [
{
"name": "Poor Quality",
"rp": 5
},
{
"name": "Run Of The Mill Quality",
"rp": 10
},
{
"name": "Superior Quality",
"rp": 30
}
]
},
{
"name": "Crossbow",
"resources": [
{
"name": "Poor Quality",
"rp": 4
},
{
"name": "Run Of The Mill Quality",
"rp": 7
},
{
"name": "Superior Quality",
"rp": 21
}
]
},
{
"name": "Heavy Crossbow",
"resources": [
{
"name": "Poor Quality",
"rp": 6
},
{
"name": "Run Of The Mill Quality",
"rp": 12
},
{
"name": "Superior Quality",
"rp": 36
}
]
},
{
"name": "Pistol",
"resources": [
{
"name": "Poor Quality",
"rp": 8
},
{
"name": "Run Of The Mill Quality",
"rp": 15
},
{
"name": "Superior Quality",
"rp": 45
}
]
},
{
"name": "Arquebus",
"resources": [
{
"name": "Poor Quality",
"rp": 10
},
{
"name": "Run Of The Mill Quality",
"rp": 20
},
{
"name": "Superior Quality",
"rp": 60
}
]
}
]
},
{
"name": "Armor",
"type": "gear",
"resources": [
{
"name": "Gambeson",
"resources": [
{
"name": "Poor Quality",
"rp": 2
},
{
"name": "Run Of The Mill Quality",
"rp": 3
},
{
"name": "Superior Quality",
"rp": 12
}
]
},
{
"name": "Reinforced Leather",
"resources": [
{
"name": "Poor Quality",
"rp": 3
},
{
"name": "Run Of The Mill Quality",
"rp": 6
},
{
"name": "Superior Quality",
"rp": 24
}
]
},
{
"name": "Light Mail",
"resources": [
{
"name": "Poor Quality",
"rp": 5
},
{
"name": "Run Of The Mill Quality",
"rp": 10
},
{
"name": "Superior Quality",
"rp": 40
}
]
},
{
"name": "Heavy Mail",
"resources": [
{
"name": "Poor Quality",
"rp": 8
},
{
"name": "Run Of The Mill Quality",
"rp": 15
},
{
"name": "Superior Quality",
"rp": 60
}
]
},
{
"name": "Plated Mail",
"resources": [
{
"name": "Poor Quality",
"rp": 10
},
{
"name": "Run Of The Mill Quality",
"rp": 20
},
{
"name": "Superior Quality",
"rp": 80
}
]
},
{
"name": "Full Plated Mail",
"resources": [
{
"name": "Poor Quality",
"rp": 25
},
{
"name": "Run Of The Mill Quality",
"rp": 50
},
{
"name": "Superior Quality",
"rp": 200
}
]
}
]
},
{
"name": "Riding Mount Or Pack Animal",
"rp": 5,
"type": "gear"
},
{
"name": "Warhorse",
"rp": 12,
"type": "gear"
},
{
"name": "Clothes",
"rp": 1,
"type": "gear"
},
{
"name": "Traveling Gear",
"rp": 1,
"type": "gear"
},
{
"name": "Shoes",
"rp": 1,
"type": "gear"
},
{
"name": "Personal Effects",
"rp": 1,
"type": "gear"
},
{
"name": "Finery",
"rp": 5,
"type": "gear"
},
{
"name": "Cash",
"rp": 6,
"type": "gear"
},
{
"name": "Skill Toolkit",
"rp": 8,
"type": "gear"
},
{
"name": "Workshop",
"rp": 20,
"type": "property"
},
{
"name": "Companion Animal",
"rp": 3,
"type": "gear"
},
{
"name": "Herd Of Animals",
"rp": 20,
"type": "property"
},
{
"name": "Rent",
"rp": 5,
"type": "property"
},
{
"name": "Property",
"type": "property",
"resources": [
{
"name": "A Leaky Shack",
"rp": 1
},
{
"name": "A Small Cottage",
"rp": 3
},
{
"name": "A House",
"rp": 10
},
{
"name": "A \"Cottage Industry\" Like A Weaver",
"rp": 10
},
{
"name": "A Villa Or Farm",
"rp": 15
},
{
"name": "A Small Business",
"rp": 20
},
{
"name": "Moderate-sized Business",
"rp": 30
},
{
"name": "A Manor Or Small Estate",
"rp": 40
},
{
"name": "An Urban Hotel",
"rp": 40
},
{
"name": "A Well-paid Position (Like Mayor)",
"rp": 45
},
{
"name": "A Successful Small Business",
"rp": 60
},
{
"name": "A Large Business",
"rp": 60
},
{
"name": "A Keep",
"rp": 60
},
{
"name": "A Fortress",
"rp": 75
},
{
"name": "A Moderate-sized Estate",
"rp": 75
},
{
"name": "A Castle With Attendant Town",
"rp": 90
},
{
"name": "A Large Estate",
"rp": 90
},
{
"name": "A Palace",
"rp": 105
},
{
"name": "A Government Position In A Prosperous Town",
"rp": 105
}
]
},
{
"name": "Boat",
"type": "property",
"resources": [
{
"name": "A Rowboat Or Skiff",
"rp": 5
},
{
"name": "A Longboat",
"rp": 10
},
{
"name": "A Junk",
"rp": 15
},
{
"name": "A Felucca",
"rp": 30
},
{
"name": "A Carrack",
"rp": 60
},
{
"name": "A Caravel",
"rp": 75
},
{
"name": "Treasure Ship",
"rp": 105
}
]
}
]
{
"stock": "man",
"resources": [
{
"name": "Arms",
"type": "gear",
"resources": [
{
"name": "Poor Quality",
"rp": 3
},
{
"name": "Run Of The Mill Quality",
"rp": 5
},
{
"name": "Superior Quality",
"rp": 20
}
]
},
{
"name": "Missile Weapons",
"type": "gear",
"resources": [
{
"name": "Throwing Weapons",
"resources": [
{
"name": "Poor Quality",
"rp": 2
},
{
"name": "Run Of The Mill Quality",
"rp": 3
},
{
"name": "Superior Quality",
"rp": 9
}
]
},
{
"name": "Hunting Bow",
"resources": [
{
"name": "Poor Quality",
"rp": 3
},
{
"name": "Run Of The Mill Quality",
"rp": 5
},
{
"name": "Superior Quality",
"rp": 15
}
]
},
{
"name": "Great Bow",
"resources": [
{
"name": "Poor Quality",
"rp": 5
},
{
"name": "Run Of The Mill Quality",
"rp": 10
},
{
"name": "Superior Quality",
"rp": 30
}
]
},
{
"name": "Crossbow",
"resources": [
{
"name": "Poor Quality",
"rp": 4
},
{
"name": "Run Of The Mill Quality",
"rp": 7
},
{
"name": "Superior Quality",
"rp": 21
}
]
},
{
"name": "Heavy Crossbow",
"resources": [
{
"name": "Poor Quality",
"rp": 6
},
{
"name": "Run Of The Mill Quality",
"rp": 12
},
{
"name": "Superior Quality",
"rp": 36
}
]
},
{
"name": "Pistol",
"resources": [
{
"name": "Poor Quality",
"rp": 8
},
{
"name": "Run Of The Mill Quality",
"rp": 15
},
{
"name": "Superior Quality",
"rp": 45
}
]
},
{
"name": "Arquebus",
"resources": [
{
"name": "Poor Quality",
"rp": 10
},
{
"name": "Run Of The Mill Quality",
"rp": 20
},
{
"name": "Superior Quality",
"rp": 60
}
]
}
]
},
{
"name": "Armor",
"type": "gear",
"resources": [
{
"name": "Gambeson",
"resources": [
{
"name": "Poor Quality",
"rp": 2
},
{
"name": "Run Of The Mill Quality",
"rp": 3
},
{
"name": "Superior Quality",
"rp": 12
}
]
},
{
"name": "Reinforced Leather",
"resources": [
{
"name": "Poor Quality",
"rp": 3
},
{
"name": "Run Of The Mill Quality",
"rp": 6
},
{
"name": "Superior Quality",
"rp": 24
}
]
},
{
"name": "Light Mail",
"resources": [
{
"name": "Poor Quality",
"rp": 5
},
{
"name": "Run Of The Mill Quality",
"rp": 10
},
{
"name": "Superior Quality",
"rp": 40
}
]
},
{
"name": "Heavy Mail",
"resources": [
{
"name": "Poor Quality",
"rp": 8
},
{
"name": "Run Of The Mill Quality",
"rp": 15
},
{
"name": "Superior Quality",
"rp": 60
}
]
},
{
"name": "Plated Mail",
"resources": [
{
"name": "Poor Quality",
"rp": 10
},
{
"name": "Run Of The Mill Quality",
"rp": 20
},
{
"name": "Superior Quality",
"rp": 80
}
]
},
{
"name": "Full Plated Mail",
"resources": [
{
"name": "Poor Quality",
"rp": 25
},
{
"name": "Run Of The Mill Quality",
"rp": 50
},
{
"name": "Superior Quality",
"rp": 200
}
]
}
]
},
{
"name": "Riding Mount Or Pack Animal",
"rp": 5,
"type": "gear"
},
{
"name": "Warhorse",
"rp": 12,
"type": "gear"
},
{
"name": "Clothes",
"rp": 1,
"type": "gear"
},
{
"name": "Traveling Gear",
"rp": 1,
"type": "gear"
},
{
"name": "Shoes",
"rp": 1,
"type": "gear"
},
{
"name": "Personal Effects",
"rp": 1,
"type": "gear"
},
{
"name": "Finery",
"rp": 5,
"type": "gear"
},
{
"name": "Cash",
"rp": 6,
"type": "gear"
},
{
"name": "Skill Toolkit",
"rp": 8,
"type": "gear"
},
{
"name": "Workshop",
"rp": 20,
"type": "property"
},
{
"name": "Companion Animal",
"rp": 3,
"type": "gear"
},
{
"name": "Herd Of Animals",
"rp": 20,
"type": "property"
},
{
"name": "Rent",
"rp": 5,
"type": "property"
},
{
"name": "Property",
"type": "property",
"resources": [
{
"name": "A Leaky Shack",
"rp": 1
},
{
"name": "A Small Cottage",
"rp": 3
},
{
"name": "A House",
"rp": 10
},
{
"name": "A \"Cottage Industry\" Like A Weaver",
"rp": 10
},
{
"name": "A Villa Or Farm",
"rp": 15
},
{
"name": "A Small Business",
"rp": 20
},
{
"name": "Moderate-sized Business",
"rp": 30
},
{
"name": "A Manor Or Small Estate",
"rp": 40
},
{
"name": "An Urban Hotel",
"rp": 40
},
{
"name": "A Well-paid Position (Like Mayor)",
"rp": 45
},
{
"name": "A Successful Small Business",
"rp": 60
},
{
"name": "A Large Business",
"rp": 60
},
{
"name": "A Keep",
"rp": 60
},
{
"name": "A Fortress",
"rp": 75
},
{
"name": "A Moderate-sized Estate",
"rp": 75
},
{
"name": "A Castle With Attendant Town",
"rp": 90
},
{
"name": "A Large Estate",
"rp": 90
},
{
"name": "A Palace",
"rp": 105
},
{
"name": "A Government Position In A Prosperous Town",
"rp": 105
}
]
},
{
"name": "Boat",
"type": "property",
"resources": [
{
"name": "A Rowboat Or Skiff",
"rp": 5
},
{
"name": "A Longboat",
"rp": 10
},
{
"name": "A Junk",
"rp": 15
},
{
"name": "A Felucca",
"rp": 30
},
{
"name": "A Carrack",
"rp": 60
},
{
"name": "A Caravel",
"rp": 75
},
{
"name": "Treasure Ship",
"rp": 105
}
]
}
]
}

@ -1,211 +1,214 @@
[
{
"name": "Rags",
"rp": 1,
"type": "gear"
},
{
"name": "Traveling Gear",
"rp": 3,
"type": "gear"
},
{
"name": "Hobnailed Boots",
"rp": 1,
"type": "gear"
},
{
"name": "Orc Arms",
"type": "gear",
"resources": [
{
"name": "Poor Quality",
"rp": 3
},
{
"name": "Run Of The Mill Quality",
"rp": 5
}
]
},
{
"name": "Armor",
"type": "gear",
"resources": [
{
"name": "Hides",
"resources": [
{
"name": "Poor Quality",
"rp": 1
}
]
},
{
"name": "Reinforced Hides",
"resources": [
{
"name": "Poor Quality",
"rp": 3
}
]
},
{
"name": "Reinforced Leather",
"resources": [
{
"name": "Run Of The Mill Quality",
"rp": 8
},
{
"name": "Superior Quality",
"rp": 25
}
]
},
{
"name": "Light Mail",
"resources": [
{
"name": "Poor Quality",
"rp": 5
},
{
"name": "Run Of The Mill Quality",
"rp": 12
}
]
},
{
"name": "Heavy Mail",
"resources": [
{
"name": "Poor Quality",
"rp": 8
},
{
"name": "Run Of The Mill Quality",
"rp": 20
}
]
}
]
},
{
"name": "Missile Weapons",
"type": "gear",
"resources": [
{
"name": "Bow",
"resources": [
{
"name": "Poor Quality",
"rp": 3
},
{
"name": "Run Of The Mill Quality",
"rp": 5
}
]
},
{
"name": "Crossbow",
"resources": [
{
"name": "Poor Quality",
"rp": 4
},
{
"name": "Run Of The Mill Quality",
"rp": 6
}
]
},
{
"name": "Iron-cased Bombs",
"resources": null,
"rp": 10
}
]
},
{
"name": "Black Iron Helmet",
"rp": 5,
"type": "gear"
},
{
"name": "Black Iron Shield",
"rp": 4,
"type": "gear"
},
{
"name": "Riding Mount Or Pack Animal",
"rp": 5,
"type": "gear"
},
{
"name": "Great Wolf Mount",
"rp": 15,
"type": "gear"
},
{
"name": "Whip",
"rp": 2,
"type": "gear"
},
{
"name": "Poison",
"rp": 5,
"type": "gear"
},
{
"name": "Brazen Horn",
"rp": 9,
"type": "gear"
},
{
"name": "Clan Banner",
"rp": 9,
"type": "gear"
},
{
"name": "Skill Tools",
"rp": 9,
"type": "gear"
},
{
"name": "Riding Harness For Wolf",
"rp": 5,
"type": "gear"
},
{
"name": "Servant's Black Robes",
"rp": 1,
"type": "gear"
},
{
"name": "Servant's Leather Apron",
"rp": 1,
"type": "gear"
},
{
"name": "Ceremonial Knives",
"rp": 3,
"type": "gear"
},
{
"name": "Ceremonial Axe Or Sword",
"rp": 7,
"type": "gear"
},
{
"name": "Servant's Tools Of The Trade",
"rp": 7,
"type": "gear"
},
{
"name": "Poisoner's Toolkit",
"rp": 7,
"type": "gear"
}
]
{
"stock": "orc",
"resources": [
{
"name": "Rags",
"rp": 1,
"type": "gear"
},
{
"name": "Traveling Gear",
"rp": 3,
"type": "gear"
},
{
"name": "Hobnailed Boots",
"rp": 1,
"type": "gear"
},
{
"name": "Orc Arms",
"type": "gear",
"resources": [
{
"name": "Poor Quality",
"rp": 3
},
{
"name": "Run Of The Mill Quality",
"rp": 5
}
]
},
{
"name": "Armor",
"type": "gear",
"resources": [
{
"name": "Hides",
"resources": [
{
"name": "Poor Quality",
"rp": 1
}
]
},
{
"name": "Reinforced Hides",
"resources": [
{
"name": "Poor Quality",
"rp": 3
}
]
},
{
"name": "Reinforced Leather",
"resources": [
{
"name": "Run Of The Mill Quality",
"rp": 8
},
{
"name": "Superior Quality",
"rp": 25
}
]
},
{
"name": "Light Mail",
"resources": [
{
"name": "Poor Quality",
"rp": 5
},
{
"name": "Run Of The Mill Quality",
"rp": 12
}
]
},
{
"name": "Heavy Mail",
"resources": [
{
"name": "Poor Quality",
"rp": 8
},
{
"name": "Run Of The Mill Quality",
"rp": 20
}
]
}
]
},
{
"name": "Missile Weapons",
"type": "gear",
"resources": [
{
"name": "Bow",
"resources": [
{
"name": "Poor Quality",
"rp": 3
},
{
"name": "Run Of The Mill Quality",
"rp": 5
}
]
},
{
"name": "Crossbow",
"resources": [
{
"name": "Poor Quality",
"rp": 4
},
{
"name": "Run Of The Mill Quality",
"rp": 6
}
]
},
{
"name": "Iron-cased Bombs",
"resources": null,
"rp": 10
}
]
},
{
"name": "Black Iron Helmet",
"rp": 5,
"type": "gear"
},
{
"name": "Black Iron Shield",
"rp": 4,
"type": "gear"
},
{
"name": "Riding Mount Or Pack Animal",
"rp": 5,
"type": "gear"
},
{
"name": "Great Wolf Mount",
"rp": 15,
"type": "gear"
},
{
"name": "Whip",
"rp": 2,
"type": "gear"
},
{
"name": "Poison",
"rp": 5,
"type": "gear"
},
{
"name": "Brazen Horn",
"rp": 9,
"type": "gear"
},
{
"name": "Clan Banner",
"rp": 9,
"type": "gear"
},
{
"name": "Skill Tools",
"rp": 9,
"type": "gear"
},
{
"name": "Riding Harness For Wolf",
"rp": 5,
"type": "gear"
},
{
"name": "Servant's Black Robes",
"rp": 1,
"type": "gear"
},
{
"name": "Servant's Leather Apron",
"rp": 1,
"type": "gear"
},
{
"name": "Ceremonial Knives",
"rp": 3,
"type": "gear"
},
{
"name": "Ceremonial Axe Or Sword",
"rp": 7,
"type": "gear"
},
{
"name": "Servant's Tools Of The Trade",
"rp": 7,
"type": "gear"
},
{
"name": "Poisoner's Toolkit",
"rp": 7,
"type": "gear"
}
]
}

@ -1,139 +1,142 @@
[
{
"name": "Arms",
"rp": 5,
"type": "gear"
},
{
"name": "Roden Throwing Blades",
"rp": 15,
"type": "gear"
},
{
"name": "Wooden Shield",
"rp": 2,
"type": "gear"
},
{
"name": "Armor",
"type": "gear",
"resources": [
{
"name": "Gambeson",
"rp": 5
},
{
"name": "Reinforced Leather",
"rp": 10
},
{
"name": "Light Mail",
"rp": 15
},
{
"name": "Heavy Mail",
"rp": 20
}
]
},
{
"name": "Property",
"type": "property",
"resources": [
{
"name": "Rat's Nest Property",
"resources": [
{
"name": "Den",
"rp": 7
},
{
"name": "Nest",
"rp": 10
},
{
"name": "Apiary",
"rp": 10
},
{
"name": "Fields",
"rp": 15
}
]
}
]
},
{
"name": "Workshop",
"type": "property",
"rp": 20
},
{
"name": "Animal Herd",
"type": "property",
"rp": 10
},
{
"name": "Clothes",
"type": "gear",
"rp": 1
},
{
"name": "Traveling Gear",
"type": "gear",
"rp": 1
},
{
"name": "Shoes",
"type": "gear",
"rp": 3
},
{
"name": "Tool Kit",
"type": "gear",
"rp": 9
},
{
"name": "Firebombs",
"type": "gear",
"rp": 20
},
{
"name": "Robes Of The Ordained",
"type": "gear",
"rp": 1
},
{
"name": "Honeyed Oatcakes",
"type": "gear",
"rp": 5
},
{
"name": "Dandewine",
"type": "gear",
"rp": 5
},
{
"name": "Blood Blossom",
"type": "gear",
"rp": 5
},
{
"name": "Visionary Cult",
"type": "affiliation",
"resources": [
{
"name": "1d Cult",
"rp": 10
},
{
"name": "2d Cult",
"rp": 25
},
{
"name": "3d Cult",
"rp": 50
}
]
}
]
{
"stock": "roden",
"resources": [
{
"name": "Arms",
"rp": 5,
"type": "gear"
},
{
"name": "Roden Throwing Blades",
"rp": 15,
"type": "gear"
},
{
"name": "Wooden Shield",
"rp": 2,
"type": "gear"
},
{
"name": "Armor",
"type": "gear",
"resources": [
{
"name": "Gambeson",
"rp": 5
},
{
"name": "Reinforced Leather",
"rp": 10
},
{
"name": "Light Mail",
"rp": 15
},
{
"name": "Heavy Mail",
"rp": 20
}
]
},
{
"name": "Property",
"type": "property",
"resources": [
{
"name": "Rat's Nest Property",
"resources": [
{
"name": "Den",
"rp": 7
},
{
"name": "Nest",
"rp": 10
},
{
"name": "Apiary",
"rp": 10
},
{
"name": "Fields",
"rp": 15
}
]
}
]
},
{
"name": "Workshop",
"type": "property",
"rp": 20
},
{
"name": "Animal Herd",
"type": "property",
"rp": 10
},
{
"name": "Clothes",
"type": "gear",
"rp": 1
},
{
"name": "Traveling Gear",
"type": "gear",
"rp": 1
},
{
"name": "Shoes",
"type": "gear",
"rp": 3
},
{
"name": "Tool Kit",
"type": "gear",
"rp": 9
},
{
"name": "Firebombs",
"type": "gear",
"rp": 20
},
{
"name": "Robes Of The Ordained",
"type": "gear",
"rp": 1
},
{
"name": "Honeyed Oatcakes",
"type": "gear",
"rp": 5
},
{
"name": "Dandewine",
"type": "gear",
"rp": 5
},
{
"name": "Blood Blossom",
"type": "gear",
"rp": 5
},
{
"name": "Visionary Cult",
"type": "affiliation",
"resources": [
{
"name": "1d Cult",
"rp": 10
},
{
"name": "2d Cult",
"rp": 25
},
{
"name": "3d Cult",
"rp": 50
}
]
}
]
}

@ -1,42 +1,45 @@
[
{
"name": "Territory",
"type": "property",
"resources": [
{
"name": "Barren",
"rp": 5
},
{
"name": "Wild Grounds",
"rp": 10
},
{
"name": "Plentiful Range",
"rp": 15
}
]
},
{
"name": "Armor",
"type": "gear",
"resources": [
{
"name": "Plated Leather Chanfron",
"rp": 3
},
{
"name": "Leather Collar",
"rp": 2
},
{
"name": "Plated Body Armor",
"rp": 6
},
{
"name": "Leather Greaves And Cuissarts",
"rp": 2
}
]
}
]
{
"stock": "wolf",
"resources": [
{
"name": "Territory",
"type": "property",
"resources": [
{
"name": "Barren",
"rp": 5
},
{
"name": "Wild Grounds",
"rp": 10
},
{
"name": "Plentiful Range",
"rp": 15
}
]
},
{
"name": "Armor",
"type": "gear",
"resources": [
{
"name": "Plated Leather Chanfron",
"rp": 3
},
{
"name": "Leather Collar",
"rp": 2
},
{
"name": "Plated Body Armor",
"rp": 6
},
{
"name": "Leather Greaves And Cuissarts",
"rp": 2
}
]
}
]
}

@ -1,114 +0,0 @@
[
{
"range": [
1,
20
],
"m": 6,
"p": 13
},
{
"range": [
21,
30
],
"m": 7,
"p": 13
},
{
"range": [
31,
50
],
"m": 7,
"p": 14
},
{
"range": [
51,
76
],
"m": 8,
"p": 15
},
{
"range": [
77,
111
],
"m": 8,
"p": 16
},
{
"range": [
112,
151
],
"m": 9,
"p": 16
},
{
"range": [
152,
199
],
"m": 9,
"p": 17
},
{
"range": [
200,
245
],
"m": 10,
"p": 18
},
{
"range": [
246,
300
],
"m": 11,
"p": 17
},
{
"range": [
301,
345
],
"m": 11,
"p": 16
},
{
"range": [
346,
396
],
"m": 12,
"p": 15
},
{
"range": [
397,
445
],
"m": 11,
"p": 14
},
{
"range": [
446,
525
],
"m": 11,
"p": 13
},
{
"range": [
526,
600
],
"m": 10,
"p": 12
}
]

@ -1,146 +0,0 @@
[
{
"range": [
1,
25
],
"m": 7,
"p": 13
},
{
"range": [
26,
60
],
"m": 8,
"p": 13
},
{
"range": [
61,
100
],
"m": 9,
"p": 14
},
{
"range": [
101,
125
],
"m": 9,
"p": 15
},
{
"range": [
126,
160
],
"m": 10,
"p": 16
},
{
"range": [
161,
225
],
"m": 10,
"p": 17
},
{
"range": [
226,
325
],
"m": 11,
"p": 17
},
{
"range": [
326,
425
],
"m": 12,
"p": 17
},
{
"range": [
426,
525
],
"m": 13,
"p": 18
},
{
"range": [
526,
625
],
"m": 13,
"p": 19
},
{
"range": [
626,
725
],
"m": 14,
"p": 19
},
{
"range": [
726,
825
],
"m": 14,
"p": 20
},
{
"range": [
826,
925
],
"m": 15,
"p": 20
},
{
"range": [
926,
1025
],
"m": 15,
"p": 21
},
{
"range": [
1026,
1125
],
"m": 15,
"p": 22
},
{
"range": [
1126,
1225
],
"m": 15,
"p": 23
},
{
"range": [
1226,
1325
],
"m": 15,
"p": 24
},
{
"range": [
1326,
9999
],
"m": 16,
"p": 24
}
]

@ -1,90 +0,0 @@
[
{
"range": [
1,
10
],
"m": 5,
"p": 10
},
{
"range": [
11,
14
],
"m": 6,
"p": 13
},
{
"range": [
15,
16
],
"m": 6,
"p": 16
},
{
"range": [
17,
25
],
"m": 7,
"p": 16
},
{
"range": [
26,
29
],
"m": 7,
"p": 15
},
{
"range": [
30,
35
],
"m": 7,
"p": 14
},
{
"range": [
36,
40
],
"m": 7,
"p": 13
},
{
"range": [
41,
55
],
"m": 7,
"p": 12
},
{
"range": [
56,
65
],
"m": 7,
"p": 11
},
{
"range": [
66,
79
],
"m": 7,
"p": 10
},
{
"range": [
80,
100
],
"m": 6,
"p": 9
}
]

@ -1,98 +0,0 @@
[
{
"range": [
1,
10
],
"m": 3,
"p": 10
},
{
"range": [
11,
16
],
"m": 4,
"p": 11
},
{
"range": [
17,
22
],
"m": 5,
"p": 12
},
{
"range": [
23,
30
],
"m": 5,
"p": 13
},
{
"range": [
31,
40
],
"m": 6,
"p": 14
},
{
"range": [
41,
50
],
"m": 6,
"p": 15
},
{
"range": [
51,
60
],
"m": 7,
"p": 16
},
{
"range": [
61,
80
],
"m": 7,
"p": 17
},
{
"range": [
81,
99
],
"m": 8,
"p": 17
},
{
"range": [
100,
125
],
"m": 8,
"p": 18
},
{
"range": [
126,
150
],
"m": 9,
"p": 18
},
{
"range": [
151,
9999
],
"m": 9,
"p": 19
}
]

@ -1,74 +0,0 @@
[
{
"range": [
1,
5
],
"m": 6,
"p": 10
},
{
"range": [
6,
9
],
"m": 7,
"p": 13
},
{
"range": [
10,
15
],
"m": 7,
"p": 14
},
{
"range": [
16,
24
],
"m": 8,
"p": 15
},
{
"range": [
25,
30
],
"m": 8,
"p": 14
},
{
"range": [
31,
36
],
"m": 7,
"p": 13
},
{
"range": [
37,
40
],
"m": 7,
"p": 12
},
{
"range": [
41,
45
],
"m": 7,
"p": 11
},
{
"range": [
46,
49
],
"m": 6,
"p": 10
}
]

@ -1,58 +0,0 @@
[
{
"range": [
1,
1.5
],
"m": 6,
"p": 12
},
{
"range": [
2,
3.5
],
"m": 7,
"p": 16
},
{
"range": [
4,
5.5
],
"m": 7,
"p": 17
},
{
"range": [
6,
7.5
],
"m": 7,
"p": 16
},
{
"range": [
8,
9.5
],
"m": 6,
"p": 14
},
{
"range": [
10,
11.5
],
"m": 6,
"p": 12
},
{
"range": [
12,
15.5
],
"m": 5,
"p": 10
}
]

@ -0,0 +1,130 @@
{
"key": "dwarf",
"name": "Dwarf",
"stride": 6,
"adjective": "dwarven",
"common_traits": [
"Accustomed To The Dark",
"Bearded",
"Greed",
"Oathsworn",
"Shaped From Earth And Stone",
"Stout",
"Tough"
],
"starting_stats":
[
{
"range": [
1,
20
],
"m": 6,
"p": 13
},
{
"range": [
21,
30
],
"m": 7,
"p": 13
},
{
"range": [
31,
50
],
"m": 7,
"p": 14
},
{
"range": [
51,
76
],
"m": 8,
"p": 15
},
{
"range": [
77,
111
],
"m": 8,
"p": 16
},
{
"range": [
112,
151
],
"m": 9,
"p": 16
},
{
"range": [
152,
199
],
"m": 9,
"p": 17
},
{
"range": [
200,
245
],
"m": 10,
"p": 18
},
{
"range": [
246,
300
],
"m": 11,
"p": 17
},
{
"range": [
301,
345
],
"m": 11,
"p": 16
},
{
"range": [
346,
396
],
"m": 12,
"p": 15
},
{
"range": [
397,
445
],
"m": 11,
"p": 14
},
{
"range": [
446,
525
],
"m": 11,
"p": 13
},
{
"range": [
526,
600
],
"m": 10,
"p": 12
}
]
}

@ -0,0 +1,161 @@
{
"key": "elf",
"name": "Elf",
"stride": 8,
"adjective": "elven",
"common_traits": [
"Born Under The Silver Stars",
"Essence Of The Earth",
"Fair And Statuesque",
"First Born",
"Grief",
"Keen Sight"
],
"starting_stats":
[
{
"range": [
1,
25
],
"m": 7,
"p": 13
},
{
"range": [
26,
60
],
"m": 8,
"p": 13
},
{
"range": [
61,
100
],
"m": 9,
"p": 14
},
{
"range": [
101,
125
],
"m": 9,
"p": 15
},
{
"range": [
126,
160
],
"m": 10,
"p": 16
},
{
"range": [
161,
225
],
"m": 10,
"p": 17
},
{
"range": [
226,
325
],
"m": 11,
"p": 17
},
{
"range": [
326,
425
],
"m": 12,
"p": 17
},
{
"range": [
426,
525
],
"m": 13,
"p": 18
},
{
"range": [
526,
625
],
"m": 13,
"p": 19
},
{
"range": [
626,
725
],
"m": 14,
"p": 19
},
{
"range": [
726,
825
],
"m": 14,
"p": 20
},
{
"range": [
826,
925
],
"m": 15,
"p": 20
},
{
"range": [
926,
1025
],
"m": 15,
"p": 21
},
{
"range": [
1026,
1125
],
"m": 15,
"p": 22
},
{
"range": [
1126,
1225
],
"m": 15,
"p": 23
},
{
"range": [
1226,
1325
],
"m": 15,
"p": 24
},
{
"range": [
1326,
9999
],
"m": 16,
"p": 24
}
]
}

@ -0,0 +1,99 @@
{
"key": "man",
"name": "Man",
"stride": 7,
"adjective": "mannish",
"common_traits": [
],
"starting_stats":
[
{
"range": [
1,
10
],
"m": 5,
"p": 10
},
{
"range": [
11,
14
],
"m": 6,
"p": 13
},
{
"range": [
15,
16
],
"m": 6,
"p": 16
},
{
"range": [
17,
25
],
"m": 7,
"p": 16
},
{
"range": [
26,
29
],
"m": 7,
"p": 15
},
{
"range": [
30,
35
],
"m": 7,
"p": 14
},
{
"range": [
36,
40
],
"m": 7,
"p": 13
},
{
"range": [
41,
55
],
"m": 7,
"p": 12
},
{
"range": [
56,
65
],
"m": 7,
"p": 11
},
{
"range": [
66,
79
],
"m": 7,
"p": 10
},
{
"range": [
80,
100
],
"m": 6,
"p": 9
}
]
}

@ -0,0 +1,114 @@
{
"key": "orc",
"name": "Orc",
"stride": 7,
"adjective": "orcish",
"common_traits": [
"Cannibal",
"Cold Black Blood",
"Breeder",
"Fanged And Clawed",
"Loathsome And Twisted",
"Lynx-eyed, Like Burning Coals",
"Vile Language"
],
"starting_stats":
[
{
"range": [
1,
10
],
"m": 3,
"p": 10
},
{
"range": [
11,
16
],
"m": 4,
"p": 11
},
{
"range": [
17,
22
],
"m": 5,
"p": 12
},
{
"range": [
23,
30
],
"m": 5,
"p": 13
},
{
"range": [
31,
40
],
"m": 6,
"p": 14
},
{
"range": [
41,
50
],
"m": 6,
"p": 15
},
{
"range": [
51,
60
],
"m": 7,
"p": 16
},
{
"range": [
61,
80
],
"m": 7,
"p": 17
},
{
"range": [
81,
99
],
"m": 8,
"p": 17
},
{
"range": [
100,
125
],
"m": 8,
"p": 18
},
{
"range": [
126,
150
],
"m": 9,
"p": 18
},
{
"range": [
151,
9999
],
"m": 9,
"p": 19
}
]
}

@ -0,0 +1,90 @@
{
"key": "roden",
"name": "Roden",
"stride": 8,
"adjective": "roden",
"common_traits": [
"Aecer's Likeness",
"Coat Of Fur",
"Communal",
"Enlarged Incisors",
"Quick-blooded",
"Tail",
"Large Ears"
],
"starting_stats":
[
{
"range": [
1,
5
],
"m": 6,
"p": 10
},
{
"range": [
6,
9
],
"m": 7,
"p": 13
},
{
"range": [
10,
15
],
"m": 7,
"p": 14
},
{
"range": [
16,
24
],
"m": 8,
"p": 15
},
{
"range": [
25,
30
],
"m": 8,
"p": 14
},
{
"range": [
31,
36
],
"m": 7,
"p": 13
},
{
"range": [
37,
40
],
"m": 7,
"p": 12
},
{
"range": [
41,
45
],
"m": 7,
"p": 11
},
{
"range": [
46,
49
],
"m": 6,
"p": 10
}
]
}

@ -0,0 +1,75 @@
{
"key": "wolf",
"name": "Wolf",
"stride": 11,
"adjective": "wolfish",
"common_traits": [
"Crushing Jaws",
"Deep Fur",
"Great Lupine Form",
"Lupine Intellect",
"Long-legged",
"Wolf's Eyes",
"Wolf's Snout",
"Woodland Ear"
],
"starting_stats":
[
{
"range": [
1,
1.5
],
"m": 6,
"p": 12
},
{
"range": [
2,
3.5
],
"m": 7,
"p": 16
},
{
"range": [
4,
5.5
],
"m": 7,
"p": 17
},
{
"range": [
6,
7.5
],
"m": 7,
"p": 16
},
{
"range": [
8,
9.5
],
"m": 6,
"p": 14
},
{
"range": [
10,
11.5
],
"m": 6,
"p": 12
},
{
"range": [
12,
15.5
],
"m": 5,
"p": 10
}
]
}

File diff suppressed because it is too large Load Diff

@ -1,57 +1,60 @@
[
{
"name": "Rags",
"type": "gear",
"rp": 1
},
{
"name": "Troll Shoes",
"type": "gear",
"rp": 1
},
{
"name": "Sack",
"type": "gear",
"rp": 1
},
{
"name": "Chest or Footlocker",
"type": "gear",
"rp": 3
},
{
"name": "Trophies",
"type": "gear",
"rp": 3
},
{
"name": "Shiny Trophies",
"type": "gear",
"rp": 7
},
{
"name": "Pile of Rocks",
"type": "gear",
"rp": 2
},
{
"name": "Troll Lash",
"type": "gear",
"rp": 5
},
{
"name": "Mattock",
"type": "gear",
"rp": 10
},
{
"name": "Black Iron Shield",
"type": "gear",
"rp": 5
},
{
"name": "Cave Hole",
"type": "property",
"rp": 5
}
]
{
"stock": "troll",
"resources": [
{
"name": "Rags",
"type": "gear",
"rp": 1
},
{
"name": "Troll Shoes",
"type": "gear",
"rp": 1
},
{
"name": "Sack",
"type": "gear",
"rp": 1
},
{
"name": "Chest or Footlocker",
"type": "gear",
"rp": 3
},
{
"name": "Trophies",
"type": "gear",
"rp": 3
},
{
"name": "Shiny Trophies",
"type": "gear",
"rp": 7
},
{
"name": "Pile of Rocks",
"type": "gear",
"rp": 2
},
{
"name": "Troll Lash",
"type": "gear",
"rp": 5
},
{
"name": "Mattock",
"type": "gear",
"rp": 10
},
{
"name": "Black Iron Shield",
"type": "gear",
"rp": 5
},
{
"name": "Cave Hole",
"type": "property",
"rp": 5
}
]
}

@ -1,82 +0,0 @@
[
{
"range": [
1,
5
],
"m": 3,
"p": 11
},
{
"range": [
6,
12
],
"m": 4,
"p": 14
},
{
"range": [
13,
19
],
"m": 4,
"p": 17
},
{
"range": [
20,
27
],
"m": 4,
"p": 19
},
{
"range": [
28,
57
],
"m": 4,
"p": 20
},
{
"range": [
58,
80
],
"m": 4,
"p": 19
},
{
"range": [
81,
124
],
"m": 4,
"p": 18
},
{
"range": [
125,
213
],
"m": 5,
"p": 17
},
{
"range": [
214,
390
],
"m": 5,
"p": 16
},
{
"range": [
391,
712
],
"m": 6,
"p": 15
}
]

@ -0,0 +1,100 @@
{
"key": "troll",
"name": "Troll",
"stride": 7,
"adjective": "trollish",
"common_traits": [
"Black Nails",
"Fangs",
"Night Blooded",
"Night Eyed (Troll)",
"Massive Stature (Troll)",
"Stone's Age",
"Tough (Troll)",
"Troll Skin",
"Voracious Carnivore"
],
"starting_stats":
[
{
"range": [
1,
5
],
"m": 3,
"p": 11
},
{
"range": [
6,
12
],
"m": 4,
"p": 14
},
{
"range": [
13,
19
],
"m": 4,
"p": 17
},
{
"range": [
20,
27
],
"m": 4,
"p": 19
},
{
"range": [
28,
57
],
"m": 4,
"p": 20
},
{
"range": [
58,
80
],
"m": 4,
"p": 19
},
{
"range": [
81,
124
],
"m": 4,
"p": 18
},
{
"range": [
125,
213
],
"m": 5,
"p": 17
},
{
"range": [
214,
390
],
"m": 5,
"p": 16
},
{
"range": [
391,
712
],
"m": 6,
"p": 15
}
]
}

File diff suppressed because it is too large Load Diff

@ -1,7 +1,11 @@
require 'deep_merge'
require_relative 'data/gold'
require_relative 'data/wizard'
require_relative 'data/dark_elf'
require_relative 'data/troll'
require_relative 'stock'
require_relative 'data/custom'
module Charred
class Data
@ -9,11 +13,13 @@ module Charred
include Charred::Wizard
include Charred::DarkElf
include Charred::Troll
include Charred::Custom
attr :data
def initialize
@data = {}
@data[:stocks] = {}
puts 'loading gold'
load_gold(@data)
@ -27,6 +33,9 @@ module Charred
puts 'loading trolls'
load_troll(@data)
puts 'loading custom stocks'
load_custom(@data)
@data[:traits] = @data[:traits].sort.to_h
@data[:skills] = @data[:skills].sort.to_h
end
@ -53,5 +62,9 @@ module Charred
[]
end
end
def json_get(filename)
JSON.parse(File.read(filename))
end
end
end
end

@ -0,0 +1,27 @@
require 'json'
module Charred
module Custom
def load_custom(data)
Dir.glob("data/custom/**/*") { |file|
if File.file?(file)
case File.extname(file)
when ".skills"
verbose_merge data[:skills], json_get(file)
when ".traits"
verbose_merge data[:traits], json_get(file)
when ".stock"
stock = Stock.new(json_get(file))
data[:stocks].deep_merge!({ stock.key => stock })
when ".lifepaths"
contents = json_get(file)
data[:lifepaths].ko_deep_merge!({ contents["stock"] => contents["settings"]})
when ".resources"
contents = json_get(file)
data[:resources].ko_deep_merge!({ contents["stock"] => contents["resources"]})
end
end
}
end
end
end

@ -12,10 +12,12 @@ module Charred
verbose_merge data[:traits], traits
file = File.read('data/dark_elf/lifepaths.json')
lifepaths = JSON.parse(file)
contents = JSON.parse(file)
lifepaths = contents["settings"]
file = File.read("data/dark_elf/resources.json")
resources = JSON.parse(file)
contents = JSON.parse(file)
resources = contents["resources"]
data[:resources]['elf'] += resources
elf = data[:lifepaths]['elf']
@ -32,4 +34,4 @@ module Charred
data[:lifepaths]['elf'] = elf
end
end
end
end

@ -1,4 +1,5 @@
require 'json'
require_relative '../stock'
module Charred
module Gold
@ -11,29 +12,30 @@ module Charred
lifepaths = {}
resources = {}
stat_pts = {}
stocks = {}
stocks = ['dwarf', 'elf', 'man', 'orc', 'roden', 'wolf']
gold_stocks = ['dwarf', 'elf', 'man', 'orc', 'roden', 'wolf']
stocks.each do |stock|
gold_stocks.each do |stock|
file = File.read("data/gold/lifepaths/#{stock}.json")
lifepaths[stock] = JSON.parse(file)
contents = JSON.parse(file)
lifepaths[stock] = contents["settings"]
file = File.read("data/gold/resources/#{stock}.json")
resources[stock] = JSON.parse(file)
contents = JSON.parse(file)
resources[stock] = contents["resources"]
file = File.read("data/gold/starting_stat_pts/#{stock}.json")
stat_pts[stock] = JSON.parse(file)
file = File.read("data/gold/stocks/#{stock}.json")
stocks[stock] = Stock.new(JSON.parse(file))
end
data.merge!({
:stocks => stocks,
:skills => skills,
:traits => traits,
:lifepaths => lifepaths,
:resources => resources,
:stat_pts => stat_pts
:stocks => stocks
})
end
end
end
end

@ -1,10 +1,9 @@
require 'json'
require_relative '../stock'
module Charred
module Troll
def load_troll(data)
data[:stocks] << 'troll'
file = File.read('data/troll/skills.json')
skills = JSON.parse(file)
verbose_merge data[:skills], skills
@ -14,16 +13,18 @@ module Charred
verbose_merge data[:traits], traits
file = File.read('data/troll/lifepaths.json')
lifepaths = JSON.parse(file)
contents = JSON.parse(file)
lifepaths = contents["settings"]
data[:lifepaths]['troll'] = lifepaths
file = File.read("data/troll/resources.json")
resources = JSON.parse(file)
contents = JSON.parse(file)
resources = contents["resources"]
data[:resources]['troll'] = resources
file = File.read("data/troll/starting_stat_pts.json")
stats = JSON.parse(file)
data[:stat_pts]['troll'] = stats
file = File.read("data/troll/stock.json")
stock = JSON.parse(file)
data[:stocks]['troll'] = Stock.new(stock)
end
end
end
end

@ -4,7 +4,8 @@ module Charred
module Wizard
def load_wizard(data)
file = File.read('data/wizard/lifepaths.json')
wizard_data = JSON.parse(file)
contents = JSON.parse(file)
wizard_data = contents["settings"]
file = File.read('data/wizard/skills.json')
wizard_skills = JSON.parse(file)
@ -116,4 +117,4 @@ module Charred
data
end
end
end
end

@ -0,0 +1,34 @@
module Charred
class Stock
@@default_stride = 7
attr :key
attr :name
attr :stride
attr :common_traits
attr :starting_stats
def initialize(h)
@key = h["key"]
@name = h["name"] || @key
@stride = h["stride"] || @@default_stride
@adjective = h["adjective"] || @key+"ish"
@common_traits = h["common_traits"]
@starting_stats = h["starting_stats"]
end
def as_json(options = {})
{
"key" => @key,
"name" => @name,
"stride" => @stride,
"adjective" => @adjective,
"common_traits" => @common_traits,
"starting_stats" => @starting_stats
}
end
def to_json(*a)
as_json.to_json(*a)
end
end
end

@ -1,8 +1,8 @@
function loadCurrentCharacterFromStruct($scope, charStruct, burningData, appropriateWeapons){
$scope.name = charStruct.name;
$scope.gender = charStruct.gender;
$scope.stock = charStruct.stock;
$scope.name = charStruct.name;
$scope.gender = charStruct.gender;
$scope.stock = charStruct.stock;
$scope.ensureStockLoaded($scope.stock).then(() => {
// Appropriate weapons must be loaded before calculateLifepathSkills is called.
if(serverSettings.storageType != 'server'){
appropriateWeapons.appropriateWeapons = charStruct.approp_weapons;
@ -15,8 +15,8 @@ function loadCurrentCharacterFromStruct($scope, charStruct, burningData, appropr
var selectedLifepaths = [];
for(var i = 0; i < charStruct.lifepaths.length; i++){
var lp = charStruct.lifepaths[i];
// lp[0] is setting name, lp[1] is lifepath name.
// lp[2] is brutalLifeDOF, lp[3] is brutalLifeTraitName,
// lp[0] is setting name, lp[1] is lifepath name.
// lp[2] is brutalLifeDOF, lp[3] is brutalLifeTraitName,
// lp[4] is lifepath time, if it's variable and the user selected a value
// lp[5] is the replacement skill for 'Weapon Of Choice' if it's present.
// lp[6] is the replacement stat array, if present. This is needed if the
@ -128,19 +128,19 @@ function loadCurrentCharacterFromStruct($scope, charStruct, burningData, appropr
// Load Resources
$scope.gear = {};
for(var i = 0; i < charStruct.gear.length; i++){
for(var i = 0; i < charStruct.gear.length; i++){
var gear = charStruct.gear[i];
$scope.gear[gear.desc] = new DisplayGear(gear.desc, gear.cost);
}
$scope.property = {};
for(var i = 0; i < charStruct.property.length; i++){
for(var i = 0; i < charStruct.property.length; i++){
var property = charStruct.property[i];
$scope.property[property.desc] = new DisplayGear(property.desc, property.cost);
}
$scope.relationships = {};
for(var i = 0; i < charStruct.relationships.length; i++){
for(var i = 0; i < charStruct.relationships.length; i++){
var rel = charStruct.relationships[i];
$scope.relationships[rel.desc] = new DisplayRelationship(
rel.desc,
@ -154,13 +154,13 @@ function loadCurrentCharacterFromStruct($scope, charStruct, burningData, appropr
}
$scope.affiliations = {};
for(var i = 0; i < charStruct.affiliations.length; i++){
for(var i = 0; i < charStruct.affiliations.length; i++){
var affil = charStruct.affiliations[i];
$scope.affiliations[affil.desc] = new DisplayAffiliation(affil.desc, affil.importance);
}
$scope.reputations = {};
for(var i = 0; i < charStruct.reputations.length; i++){
for(var i = 0; i < charStruct.reputations.length; i++){
var rep = charStruct.reputations[i];
$scope.reputations[rep.desc] = new DisplayReputation(rep.desc, rep.importance);
}
@ -173,14 +173,15 @@ function loadCurrentCharacterFromStruct($scope, charStruct, burningData, appropr
$scope.attributeModifierQuestionResults = loadAttributeModifierQuestionResultsFromSave($scope, charStruct.attr_mod_questions);
$scope.brutalLifeWithdrawn = charStruct.brutal_life_withdrawn;
$scope.$digest();
});
}
function convertCurrentCharacterToStruct($scope, appropriateWeapons) {
// To serialize:
// - Serialized version
// - Character name
// - Stock
// - Stock
// - Gender
// - A list Lifepath names, with setting: [setting, lifepath]
// - How many points were spent on which stat
@ -225,10 +226,10 @@ function convertCurrentCharacterToStruct($scope, appropriateWeapons) {
var displayStat = $scope.stats[i];
stats.push({
"name" : displayStat.name,
"shade" : displayStat.shade,
"mentalPoints" : displayStat.mentalPointsSpent,
"physicalPoints" : displayStat.physicalPointsSpent,
"name" : displayStat.name,
"shade" : displayStat.shade,
"mentalPoints" : displayStat.mentalPointsSpent,
"physicalPoints" : displayStat.physicalPointsSpent,
"eitherPoints" : displayStat.eitherPointsSpent
});
}
@ -277,7 +278,7 @@ function convertCurrentCharacterToStruct($scope, appropriateWeapons) {
}
var res = serializeResource( $scope.gear, function(display){
return {
return {
"cost" : display.cost,
"desc" : display.desc
};
@ -285,7 +286,7 @@ function convertCurrentCharacterToStruct($scope, appropriateWeapons) {
chardata.gear = res;
var res = serializeResource( $scope.property, function(display){
return {
return {
"cost" : display.cost,
"desc" : display.desc
};
@ -293,7 +294,7 @@ function convertCurrentCharacterToStruct($scope, appropriateWeapons) {
chardata.property = res;
var res = serializeResource( $scope.relationships, function(display){
return {
return {
"desc" : display.desc,
"importance" : display.importance,
"isImmedFam" : display.isImmedFam,
@ -306,7 +307,7 @@ function convertCurrentCharacterToStruct($scope, appropriateWeapons) {
chardata.relationships = res;
var res = serializeResource( $scope.affiliations, function(display){
return {
return {
"desc" : display.desc,
"importance" : display.importance
};
@ -314,7 +315,7 @@ function convertCurrentCharacterToStruct($scope, appropriateWeapons) {
chardata.affiliations = res;
var res = serializeResource( $scope.reputations, function(display){
return {
return {
"desc" : display.desc,
"importance" : display.importance
};

@ -1,4 +1,4 @@
var DEBUG = false;
/**** Class Settings (Angular Service) ****/
function Settings() {
this.enforceLifepathReqts = true;
@ -9,7 +9,7 @@ function Settings() {
/**** Class AppropriateWeaponsService (Angular Service) ****/
function AppropriateWeaponsService($modal, $http) {
// This class will store a hash which maps lifepath names to a list of
// This class will store a hash which maps lifepath names to a list of
// weapons that are appropriate for that lifepath.
this.appropriateWeapons = {};
@ -167,7 +167,7 @@ function WeaponOfChoiceService($modal, $http) {
}
return has;
}
this.selectWeaponOfChoice = function (displayLp, onSelect){
if( this.hasWeaponOfChoice(displayLp) ){
this.selectWeaponOfChoiceByModal(displayLp.name, function(selected){
@ -218,13 +218,14 @@ function CharacterStorageService($http) {
/* Load character names from server */
this.loadCharacterNames = function(){
$http.get("/list_chars/user1", {'timeout': 3000} ).
success(function(data,status,headers,config){
fetch("/list_chars/user1")
.then((response) => response.json())
.then((data) => {
myself.characterIdAndNames = data;
console.log("Loaded saved character names");
}).
error(function(data,status,headers,config){
console.log("Error: Loading saved character names from server failed: HTTP code " + status + ": " + data);
})
.catch((error) => {
console.log("Error: Loading saved character names from server failed: "+error);
});
}
@ -236,6 +237,10 @@ function CharacterStorageService($http) {
/**** Class BurningDataService (Angular Service) ****/
// This service is used to load the lifepaths, skills, traits, etc. from the server.
function BurningDataService($http) {
// Used to reference the object from within functions and callbacks
var myself = this;
/* JSON Data structure representing lifepaths. The structure is:
stock:
setting_name:
@ -250,135 +255,101 @@ function BurningDataService($http) {
roots: [root1, root2, ...]
skill_name:
roots: [root1, root2, ...]
*/
this.skills = {};
/* JSON data structure representing all available traits */
this.traits = {};
/* JSON data structure representing all available resources (gear/property) */
this.resources = {};
// A hash of StartingStatPoints objects keyed by stock.
this.startingStatPts = {};
this.dataSetsLoaded = 0;
// Total data sets:
// lifepaths: 7 (man, dwarf, elf, orc, roden, wolf, troll)
// stat points: 7 (man, dwarf, elf, orc, roden, wolf, troll)
// skills
// traits
// resources: 7 (man, dwarf, elf, orc, roden, wolf. troll)
// TOTAL: 23
this.totalDataSets = 23;
this.onAllDatasetsLoaded = null;
this.registerOnAllDatasetsLoaded = function(callback){
if ( this.dataSetsLoaded >= this.totalDataSets ){
callback();
}
this.onAllDatasetsLoaded = callback;
}
this.datasetLoaded = function(){
this.dataSetsLoaded += 1;
if ( this.onAllDatasetsLoaded && (this.dataSetsLoaded >= this.totalDataSets) ){
this.onAllDatasetsLoaded();
}
if ( this.dataSetsLoaded > this.totalDataSets){
console.log("Error: the totalDataSets setting in BurningDataService is too low! This will cause wierd errors. Please adjust it");
}
}
var stocks = ["man", "dwarf", "elf", "orc", "roden", "wolf", "troll"];
var myself = this;
/* Load lifepaths from server */
var loadLifepathsForStock = function(stock){
if( ! isValidStock(stock) ){
console.log("Loading lifepaths failed: asked to load lifepaths for invalid stock " + stock);
return
}
$http.get("/lifepaths/" + stock, {'timeout': 3000} ).
success(function(data,status,headers,config){
myself.lifepaths[stock] = data;
myself.datasetLoaded();
console.log("Loaded "+stock+" lifepaths. " + Object.keys(myself.lifepaths).length + " settings");
}).
error(function(data,status,headers,config){
myself.datasetLoaded();
console.log("Error: Getting "+stock+" lifepaths from server failed: HTTP code " + status + ": " + data);
});
}
/* Load starting stat points table from server */
var loadStartingStatPtsForStock = function(stock){
if( ! isValidStock(stock) ){
console.log("Loading starting stat points failed: asked to load pts for invalid stock " + stock);
return
}
/* Loading of stocks, skills, and traits begins on initializing the service
$http.get("/starting_stat_pts/" + stock, {'timeout': 3000} ).
success(function(data,status,headers,config){
myself.startingStatPts[stock] = new StartingStatPoints(data);
myself.datasetLoaded();
console.log("Loaded "+stock+" starting stat points. ");
}).
error(function(data,status,headers,config){
myself.datasetLoaded();
console.log("Error: Getting "+stock+" stat points from server failed: HTTP code " + status + ": " + data);
});
}
/* Load starting stat points table from server */
var loadResourcesForStock = function(stock){
if( ! isValidStock(stock) ){
console.log("Loading resources failed: asked to load for invalid stock " + stock);
return
}
$http.get("/resources/" + stock, {'timeout': 3000} ).
success(function(data,status,headers,config){
myself.resources[stock] = data;
myself.datasetLoaded();
console.log("Loaded "+stock+" resources. ");
}).
error(function(data,status,headers,config){
myself.datasetLoaded();
console.log("Error: Getting "+stock+" stat points from server failed: HTTP code " + status + ": " + data);
});
}
for (var i = 0; i < stocks.length; i++) {
loadLifepathsForStock(stocks[i]);
loadStartingStatPtsForStock(stocks[i]);
loadResourcesForStock(stocks[i]);
}
/* Load stocks from server */
this.whenStocksLoaded = fetch("/stocks")
.then((response) => response.json())
.then((data) => {
if(DEBUG) {
console.log("Loaded stock data:");
console.log(data);
}
myself.stocks = data;
for (var stock of Object.keys(data)) {
myself.startingStatPts[stock] = new StartingStatPoints(myself.stocks[stock].starting_stats);
}
})
.catch((error) => {
console.log("Error: Getting stocks from server failed: "+error);
});
/* Load skills from server */
$http.get("/skills", {'timeout': 3000} ).
success(function(data,status,headers,config){
this.whenSkillsLoaded = fetch("/skills")
.then((response) => response.json())
.then((data) => {
myself.skills = data;
myself.datasetLoaded();
console.log("Loaded skills. ");
}).
error(function(data,status,headers,config){
myself.datasetLoaded();
console.log("Error: Getting skills from server failed: HTTP code " + status + ": " + data);
if(DEBUG) {
console.log("Loaded skill data:");
console.log(data);
}
})
.catch((error) => {
console.log("Error: Getting skills from server failed: "+error);
});
/* Load traits from server */
$http.get("/traits", {'timeout': 3000} ).
success(function(data,status,headers,config){
this.whenTraitsLoaded = fetch("/traits")
.then((response) => response.json())
.then((data) => {
myself.traits = data;
myself.datasetLoaded();
console.log("Loaded traits. ");
}).
error(function(data,status,headers,config){
myself.datasetLoaded();
console.log("Error: Getting traits from server failed: HTTP code " + status + ": " + data);
if(DEBUG) {
console.log("Loaded trait data:");
console.log(data);
}
})
.catch((error) => {
console.log("Error: Getting traits from server failed: "+error);
});
/* Lifepaths and resources defer until their stock is selected */
this.whenLifePathsLoadedForStock = {};
/* Load lifepaths from server */
this.loadLifepathsForStock = function(stock){
return myself.whenLifePathsLoadedForStock[stock] = fetch("/lifepaths/" + stock)
.then((response) => response.json())
.then((data) => {
myself.lifepaths[stock] = data;
if(DEBUG) {
console.log("Loaded "+stock+" lifepaths:");
console.log(data);
}
})
.catch((error) => {
console.log("Error: Getting "+stock+" lifepaths from server failed: "+error);
});
};
/* Load resources from server */
this.whenResourcesLoadedForStock = {};
this.loadResourcesForStock = function(stock){
return myself.whenResourcesLoadedForStock[stock] = fetch("/resources/" + stock)
.then((response) => response.json())
.then((data) => {
myself.resources[stock] = data;
if(DEBUG) {
console.log("Loaded "+stock+" resources:");
console.log(data);
}
})
.catch((error) => {
console.log("Error: Getting "+stock+" resources from server failed: "+error);
});
};
}
/**** End BurningDataService ****/

File diff suppressed because it is too large Load Diff

@ -1,5 +1,5 @@
var serverSettings = {
'versionString' : '2.3.0',
'storageType' : 'client',
'versionString' : '3.0.0',
'storageType' : 'client',
'displayAttrMath' : 'false'
}

@ -94,14 +94,7 @@
</strong>
</div>
<div class='col-md-2'>
<select class='form-control' ng-change='onStockChange()' ng-model='stock'>
<option value='man'>Man</option>
<option value='dwarf'>Dwarf</option>
<option value='elf'>Elf</option>
<option value='orc'>Orc</option>
<option value='roden'>Roden</option>
<option value='wolf'>Great Wolf</option>
<option value='troll'>Troll</option>
<select class='form-control' ng-change='onStockChange()' ng-model='stock' ng-options='s.key as s.name for s in stocks'>
</select>
</div>
<div class='col-md-1'>

@ -0,0 +1,133 @@
{
"stock": "test",
"settings": {
"Test Setting": {
"Born Test": {
"time": 7,
"res": 5,
"skills": [
[
1,
"General"
]
],
"traits": [
2
],
"leads": [
"Nowhere"
],
"key_leads": [
"Nowhere Setting"
]
},
"A thing": {
"time": 5,
"res": 2,
"stat": [
[
2,
"p"
]
],
"skills": [
[
4,
"Testing",
"Forest-wise",
"Stealthy"
]
],
"traits": [
1
],
"leads": [
"Nowhere"
],
"key_leads": [
"Nowhere Setting"
]
}
},
"Nowhere Setting": {
"Born Nothing": {
"time": 0,
"res": 0,
"skills": [
],
"traits": [
],
"leads": [
],
"key_leads": [
]
},
"Not A Thing": {
"time": 15,
"res": 1,
"stat": [
[
1,
"pm"
]
],
"skills": [
[
2,
"Nothinging",
"Voiding"
]
],
"traits": [
3
],
"leads": [
"Somewhere"
],
"key_leads": [
"Somewhere Subsetting"
]
}
},
"Somewhere Subsetting": {
"Something Special": {
"time": 30,
"res": 21,
"stat": [
[
1,
"m"
],[
1,
"p"
],[
1,
"pm"
]
],
"skills": [
[
7,
"Specializing",
"Soothing",
"History",
"Sorcery",
"Spirit Binding",
"Harming"
]
],
"traits": [
3,
"Stubborn",
"Shy"
],
"leads": [
"Nowhere"
],
"key_leads": [
"Nowhere Setting"
]
}
}
}
}

@ -0,0 +1,25 @@
{
"stock": "test",
"resources": [
{
"name": "Rags",
"type": "gear",
"rp": 1
},
{
"name": "Riches",
"type": "gear",
"rp": 50
},
{
"name": "A firey soul",
"type": "gear",
"rp": 3
},
{
"name": "Chest or Footlocker",
"type": "gear",
"rp": 3
}
]
}

@ -0,0 +1,39 @@
{
"Testing": {
"stock": "testish",
"roots": [
"Perception"
]
},
"Nothinging": {
"stock": "testish",
"roots": [
"Will",
"Agility"
]
},
"Voiding": {
"stock": "testish",
"roots": [
"Speed"
]
},
"Specializing": {
"stock": "testish",
"roots": [
"Forte"
]
},
"Soothing": {
"stock": "testish",
"roots": [
"Power"
]
},
"Harming": {
"stock": "testish",
"roots": [
"Will"
]
}
}

@ -0,0 +1,95 @@
{
"key": "test",
"name": "Test",
"stride": 9,
"adjective": "testish",
"common_traits": [
"Trait 1",
"testy",
"Trait #3",
"Night Eyed (Test)"
],
"starting_stats":
[
{
"range": [
1,
10
],
"m": 1,
"p": 2
},
{
"range": [
11,
20
],
"m": 2,
"p": 4
},
{
"range": [
21,
30
],
"m": 3,
"p": 6
},
{
"range": [
31,
40
],
"m": 4,
"p": 8
},
{
"range": [
41,
50
],
"m": 5,
"p": 10
},
{
"range": [
51,
60
],
"m": 6,
"p": 12
},
{
"range": [
61,
70
],
"m": 7,
"p": 14
},
{
"range": [
71,
80
],
"m": 8,
"p": 16
},
{
"range": [
81,
90
],
"m": 9,
"p": 18
},
{
"range": [
91,
100
],
"m": 10,
"p": 20
}
]
}

@ -0,0 +1,55 @@
{
"Trait 1": {
"cost": 0,
"type": "die",
"restrict": [
"testish",
"common"
],
"desc": ""
},
"testy": {
"cost": 0,
"type": "die",
"restrict": [
"testish",
"common"
],
"desc": ""
},
"Trait #3": {
"cost": 0,
"type": "die",
"restrict": [
"testish",
"common"
],
"desc": ""
},
"Night Eyed (Test)": {
"cost": 1,
"type": "die",
"restrict": [
"testish",
"common"
],
"desc": "The test version"
},
"Shy": {
"cost": 1,
"type": "character",
"restrict": [
"testish",
"lifepath"
]
},
"Special": {
"cost": 3,
"type": "die",
"restrict": [
"testish",
"special"
],
"desc": "Snowflake"
}
}
Loading…
Cancel
Save