This is a script to convert the DC20 TTRPG PDF into JSON and Obsidian flavored markdown.
Use the website to unlock and download the zip archive. (Output Unlock Tool) It requires owning a copy of the PDF to unlock, so if you don't own a copy, go ahead and buy one here.
Yes, Alan (AKA the Dungeon Coach) has graciously permitted us to share the player options for levels 1-2.
While the code in this repository is open source, DC20, both the source PDF and the output of this script, including the free section, is proprietary. This is under the same restrictions as the original PDF. Any questions regarding this should be directed to Alan thedungeoncoach@thedungeoncoach.com, or one of his discord moderators)
- spells
- tags
- schools
- sources
- maneuvers
- maneuvers types
- conditions
- overlapping conditions?
- ancestries
- talents
- the Wild Magic Table
- classes
- subclasses
- actions
- damage types
- attributes
- saves
- skills
- trades
- languages
- equipment
- weapons
- styles
- properties
- shields
- armor
- spell focuses
- weapons
- character sheets
- monster stat blocks
- Magazine content
- Monsters
- Magic items
- ancestries
- classes
- Psion
- Articicer
- Summoner
The free/publicly available version is missing the following:
- Spells with a base MP cost of 2 or more
- Banish, Confusion, Disintegrating Beam, Disintegrate, Gravity Shift, Increase Gravity, Revivify, Slumber, Time Stop
- Maneuvers with a base SP cost of 2 or more
- Sunder Strike
- Talents with a level requirement of 3 or more
- Adaptive Bond, Adept Multiclass, Big Game Hunter, Bountiful Blessings, Champion's Resolve, Coordinated Command, Crowned Sigil, Disciplined Combatant, Divine Cleanse, Expanded Repertoire, Expert Multiclass, Font of Magic, Greater Innate Power, Helping Hands, Internal Damage, M, Nature's Vortex, Overly Prepared Spellcaster, Pack Leader, Pact Bane, Seize Momentum, Sinister Shot, Sling-blade, Steel Fist, Unfathomable Strength, Unseen Ambusher, Warlock Subcontract, Wild Form Expansionaster Multiclass
- Level 3+ Class Features
- Subclasses
- Monsters
- Magazine Content (This will be locked behind their respective magazines)
- Input JSON Data
- Full git history
- Add the type to
dc_types/, inheriting fromItem(dc_types/item)- implement
__init__,from_json,markdown,get_default_page_range,get_save_file, andmarkdown_path
- implement
- Add to the
dc_obj_decoderfunction indc_types/serde.py - Add a parser to
parsers/ - Add to the
get_typefunction inutils/get_type.py
- Make sure you have the correct set of pages
- Make sure the proto items are split correctly
./main.py --type <type> --all --print --raw | jq '.[].name'- Lists all proto item names
./main.py --type <type> --all --print --raw | jq '.[].frags | .[0:3] + .[-4:-1]- This shows the first and last three fragments in all proto items
- View unprocessed fragments
- Add an early return to your parser
./main.py --type <type> --all --print --raw -u | jq '.[0].frags[0:<number of fragment to view>]'
git: version controlruff: python formatter/linterty: python type checkerjq: JSON utilityfx: JSON pager- ripgrep: find
sd: find and replacetypos: spell checker- obsidian: view final output
fzf: Fuzzy finder, used forstats.sh
This software is distributed separately form the input/output documents for legal reasons. Copy or symlink the dc-obsidian directory into this one in order to run this software. DO NOT include the input/output file(s) in commits/pull requests
The input file is in the encrypted zip file included on the website, unlock it with unlock.html using the source PDF as the key file. You shouldn't have to generate it manually, but the instructions are below if you need them.
Note: I have only tested this on Linux so your mileage may vary
To create to required JSON file install https://github.com/run-llama/liteparse and run:
NOTE the presence of the --no-ocr argument
cd <path to project>
mkdir -p dc-obsidian/json
lit parse --no-ocr --output dc-obsidian/json/dc20_0.10.5_pdf_orig.json --format json "DC20 RPG 0.10.5 Beta v1.0.pdf"
cat dc-obsidian/json/dc20_0.10.5_pdf_orig.json | jq '.pages | map(del(.boundingBoxes) | .textItems = (.textItems | map(del(.confidence))))' > ./dc-obsidian/json/dc20_0.10.5_pdf_filtered.json