adding conversion utils for 5e.tools json data
This commit is contained in:
parent
bc9052242a
commit
e073647e5d
|
@ -1,15 +1,19 @@
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
import typer
|
import typer
|
||||||
|
|
||||||
from rich.logging import RichHandler
|
from rich.logging import RichHandler
|
||||||
from rich.console import Console
|
from rich.console import Console
|
||||||
|
# from rich.table import Table
|
||||||
|
|
||||||
from dnd_item.types import Item
|
from dnd_item.types import random_item
|
||||||
|
from dnd_item import five_e
|
||||||
|
|
||||||
app = typer.Typer()
|
app = typer.Typer()
|
||||||
|
app_state = {}
|
||||||
|
|
||||||
|
|
||||||
@app.callback()
|
@app.callback()
|
||||||
|
@ -22,9 +26,20 @@ def main():
|
||||||
)
|
)
|
||||||
logging.getLogger('markdown_it').setLevel(logging.ERROR)
|
logging.getLogger('markdown_it').setLevel(logging.ERROR)
|
||||||
|
|
||||||
|
app_state['data'] = Path(__file__).parent / Path("sources")
|
||||||
|
|
||||||
|
|
||||||
@app.command()
|
@app.command()
|
||||||
def item(count: int = typer.Option(1, help="The number of items to generate.")):
|
def item(count: int = typer.Option(1, help="The number of items to generate.")):
|
||||||
console = Console(width=80)
|
items = random_item(count)
|
||||||
for _ in range(count):
|
console = Console()
|
||||||
console.print(Item())
|
for item in items:
|
||||||
|
console.print(f"{item['Name']} of {item['Enchantment Noun']} "
|
||||||
|
f"({item['Damage Dice']} {item['Damage Type']} + "
|
||||||
|
f"{item['Enchantment Damage']} {item['Enchantment Type']})")
|
||||||
|
|
||||||
|
|
||||||
|
@app.command()
|
||||||
|
def convert():
|
||||||
|
src = five_e.weapons()
|
||||||
|
print(src.as_yaml)
|
||||||
|
|
90
dnd_item/five_e.py
Normal file
90
dnd_item/five_e.py
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
import json
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
from collections import defaultdict
|
||||||
|
|
||||||
|
from rolltable.tables import DataSource
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
sources = Path(__file__).parent / Path("sources")
|
||||||
|
|
||||||
|
RARITY = {
|
||||||
|
'unknown': 'common',
|
||||||
|
'none': 'common',
|
||||||
|
'': ''
|
||||||
|
}
|
||||||
|
|
||||||
|
TYPE = {
|
||||||
|
'M': 'martial',
|
||||||
|
'R': 'ranged',
|
||||||
|
'': ''
|
||||||
|
}
|
||||||
|
|
||||||
|
DAMAGE = {
|
||||||
|
'S': 'Slashing',
|
||||||
|
'P': 'Piercing',
|
||||||
|
'B': 'Bludgeoning',
|
||||||
|
'': ''
|
||||||
|
}
|
||||||
|
|
||||||
|
PROPERTIES = {
|
||||||
|
'F': 'finesse',
|
||||||
|
'AF': 'firearm',
|
||||||
|
'A': 'ammmunition',
|
||||||
|
'T': 'thrown',
|
||||||
|
'L': 'light',
|
||||||
|
'2H': 'two-handed',
|
||||||
|
'V': 'versatile',
|
||||||
|
'RLD': 'reload',
|
||||||
|
'LD': 'loading',
|
||||||
|
'S': 'special',
|
||||||
|
'H': 'heavy',
|
||||||
|
'R': 'reach',
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Weapons(DataSource):
|
||||||
|
"""
|
||||||
|
A rolltables data source backed by a 5e.tools json data file. used to
|
||||||
|
convert the 5e.tools data to the yaml format consumed by dnd-rolltables.
|
||||||
|
"""
|
||||||
|
def read_source(self) -> None:
|
||||||
|
src = json.load(self.source)['baseitem']
|
||||||
|
self.data = defaultdict(list)
|
||||||
|
headers = ['Rarity', 'Name', 'Category', 'Type', 'Weight', 'Damage Type',
|
||||||
|
'Damage Dice', 'Range', 'Reload', 'Value', 'Properties']
|
||||||
|
|
||||||
|
for item in src:
|
||||||
|
if not item.get('weapon', False):
|
||||||
|
continue
|
||||||
|
if item.get('age', False):
|
||||||
|
continue
|
||||||
|
rarity = RARITY.get(item['rarity'], 'Common').capitalize()
|
||||||
|
itype = TYPE.get(item['type'], '_unknown').capitalize()
|
||||||
|
properties = ', '.join([PROPERTIES[p] for p in item.get('property', [])])
|
||||||
|
|
||||||
|
self.data[rarity].append({
|
||||||
|
item['name'].capitalize(): [
|
||||||
|
item['weaponCategory'],
|
||||||
|
itype,
|
||||||
|
str(item.get('weight', 0)),
|
||||||
|
DAMAGE.get(item.get('dmgType', '')),
|
||||||
|
item.get('dmg1', None),
|
||||||
|
item.get('range', None),
|
||||||
|
str(item.get('reload', '')),
|
||||||
|
str(item.get('value', '')),
|
||||||
|
properties,
|
||||||
|
]
|
||||||
|
})
|
||||||
|
self.metadata = {'headers': headers}
|
||||||
|
|
||||||
|
@property
|
||||||
|
def as_yaml(self) -> str:
|
||||||
|
return yaml.dump({'metadata': self.metadata}) + yaml.dump(dict(self.data))
|
||||||
|
|
||||||
|
|
||||||
|
def weapons(source_path: str = 'items-base.json') -> dict:
|
||||||
|
with open(sources / Path(source_path)) as filehandle:
|
||||||
|
ds = Weapons(source=filehandle)
|
||||||
|
return ds
|
13
dnd_item/sources/enchantments.yaml
Normal file
13
dnd_item/sources/enchantments.yaml
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
metadata:
|
||||||
|
headers:
|
||||||
|
- Rarity
|
||||||
|
- Enchantment Type
|
||||||
|
- Enchantment Noun
|
||||||
|
- Enchantment Adjective
|
||||||
|
Common:
|
||||||
|
Fire:
|
||||||
|
- Flames
|
||||||
|
- Flaming
|
||||||
|
Ice:
|
||||||
|
- Ice
|
||||||
|
- Freezing
|
435
dnd_item/sources/types.yaml
Normal file
435
dnd_item/sources/types.yaml
Normal file
|
@ -0,0 +1,435 @@
|
||||||
|
metadata:
|
||||||
|
headers:
|
||||||
|
- Rarity
|
||||||
|
- Name
|
||||||
|
- Category
|
||||||
|
- Type
|
||||||
|
- Weight
|
||||||
|
- Damage Type
|
||||||
|
- Damage Dice
|
||||||
|
- Range
|
||||||
|
- Reload
|
||||||
|
- Value
|
||||||
|
- Properties
|
||||||
|
Common:
|
||||||
|
- Battleaxe:
|
||||||
|
- martial
|
||||||
|
- Martial
|
||||||
|
- '4'
|
||||||
|
- Slashing
|
||||||
|
- 1d8
|
||||||
|
- null
|
||||||
|
- ''
|
||||||
|
- '1000'
|
||||||
|
- versatile
|
||||||
|
- Blowgun:
|
||||||
|
- martial
|
||||||
|
- Ranged
|
||||||
|
- '1'
|
||||||
|
- Piercing
|
||||||
|
- '1'
|
||||||
|
- 25/100
|
||||||
|
- ''
|
||||||
|
- '1000'
|
||||||
|
- ammmunition, loading
|
||||||
|
- Club:
|
||||||
|
- simple
|
||||||
|
- Martial
|
||||||
|
- '2'
|
||||||
|
- Bludgeoning
|
||||||
|
- 1d4
|
||||||
|
- null
|
||||||
|
- ''
|
||||||
|
- '10'
|
||||||
|
- light
|
||||||
|
- Dagger:
|
||||||
|
- simple
|
||||||
|
- Martial
|
||||||
|
- '1'
|
||||||
|
- Piercing
|
||||||
|
- 1d4
|
||||||
|
- 20/60
|
||||||
|
- ''
|
||||||
|
- '200'
|
||||||
|
- finesse, light, thrown
|
||||||
|
- Dart:
|
||||||
|
- simple
|
||||||
|
- Ranged
|
||||||
|
- '0.25'
|
||||||
|
- Piercing
|
||||||
|
- 1d4
|
||||||
|
- 20/60
|
||||||
|
- ''
|
||||||
|
- '5'
|
||||||
|
- finesse, thrown
|
||||||
|
- Double-bladed scimitar:
|
||||||
|
- martial
|
||||||
|
- Martial
|
||||||
|
- '6'
|
||||||
|
- Slashing
|
||||||
|
- 2d4
|
||||||
|
- null
|
||||||
|
- ''
|
||||||
|
- '10000'
|
||||||
|
- special, two-handed
|
||||||
|
- Flail:
|
||||||
|
- martial
|
||||||
|
- Martial
|
||||||
|
- '2'
|
||||||
|
- Bludgeoning
|
||||||
|
- 1d8
|
||||||
|
- null
|
||||||
|
- ''
|
||||||
|
- '1000'
|
||||||
|
- ''
|
||||||
|
- Glaive:
|
||||||
|
- martial
|
||||||
|
- Martial
|
||||||
|
- '6'
|
||||||
|
- Slashing
|
||||||
|
- 1d10
|
||||||
|
- null
|
||||||
|
- ''
|
||||||
|
- '2000'
|
||||||
|
- heavy, reach, two-handed
|
||||||
|
- Greataxe:
|
||||||
|
- martial
|
||||||
|
- Martial
|
||||||
|
- '7'
|
||||||
|
- Slashing
|
||||||
|
- 1d12
|
||||||
|
- null
|
||||||
|
- ''
|
||||||
|
- '3000'
|
||||||
|
- heavy, two-handed
|
||||||
|
- Greatclub:
|
||||||
|
- simple
|
||||||
|
- Martial
|
||||||
|
- '10'
|
||||||
|
- Bludgeoning
|
||||||
|
- 1d8
|
||||||
|
- null
|
||||||
|
- ''
|
||||||
|
- '20'
|
||||||
|
- two-handed
|
||||||
|
- Greatsword:
|
||||||
|
- martial
|
||||||
|
- Martial
|
||||||
|
- '6'
|
||||||
|
- Slashing
|
||||||
|
- 2d6
|
||||||
|
- null
|
||||||
|
- ''
|
||||||
|
- '5000'
|
||||||
|
- heavy, two-handed
|
||||||
|
- Halberd:
|
||||||
|
- martial
|
||||||
|
- Martial
|
||||||
|
- '6'
|
||||||
|
- Slashing
|
||||||
|
- 1d10
|
||||||
|
- null
|
||||||
|
- ''
|
||||||
|
- '2000'
|
||||||
|
- heavy, reach, two-handed
|
||||||
|
- Hand crossbow:
|
||||||
|
- martial
|
||||||
|
- Ranged
|
||||||
|
- '3'
|
||||||
|
- Piercing
|
||||||
|
- 1d6
|
||||||
|
- 30/120
|
||||||
|
- ''
|
||||||
|
- '7500'
|
||||||
|
- ammmunition, light, loading
|
||||||
|
- Handaxe:
|
||||||
|
- simple
|
||||||
|
- Martial
|
||||||
|
- '2'
|
||||||
|
- Slashing
|
||||||
|
- 1d6
|
||||||
|
- 20/60
|
||||||
|
- ''
|
||||||
|
- '500'
|
||||||
|
- light, thrown
|
||||||
|
- Heavy crossbow:
|
||||||
|
- martial
|
||||||
|
- Ranged
|
||||||
|
- '18'
|
||||||
|
- Piercing
|
||||||
|
- 1d10
|
||||||
|
- 100/400
|
||||||
|
- ''
|
||||||
|
- '5000'
|
||||||
|
- ammmunition, heavy, loading, two-handed
|
||||||
|
- Hooked shortspear:
|
||||||
|
- martial
|
||||||
|
- Martial
|
||||||
|
- '2'
|
||||||
|
- Piercing
|
||||||
|
- 1d4
|
||||||
|
- null
|
||||||
|
- ''
|
||||||
|
- ''
|
||||||
|
- light
|
||||||
|
- Hoopak:
|
||||||
|
- martial
|
||||||
|
- Martial
|
||||||
|
- '2'
|
||||||
|
- Piercing
|
||||||
|
- 1d6
|
||||||
|
- 40/160
|
||||||
|
- ''
|
||||||
|
- '10'
|
||||||
|
- ammmunition, finesse, special, two-handed
|
||||||
|
- Javelin:
|
||||||
|
- simple
|
||||||
|
- Martial
|
||||||
|
- '2'
|
||||||
|
- Piercing
|
||||||
|
- 1d6
|
||||||
|
- 30/120
|
||||||
|
- ''
|
||||||
|
- '50'
|
||||||
|
- thrown
|
||||||
|
- Lance:
|
||||||
|
- martial
|
||||||
|
- Martial
|
||||||
|
- '6'
|
||||||
|
- Piercing
|
||||||
|
- 1d12
|
||||||
|
- null
|
||||||
|
- ''
|
||||||
|
- '1000'
|
||||||
|
- reach, special
|
||||||
|
- Light crossbow:
|
||||||
|
- simple
|
||||||
|
- Ranged
|
||||||
|
- '5'
|
||||||
|
- Piercing
|
||||||
|
- 1d8
|
||||||
|
- 80/320
|
||||||
|
- ''
|
||||||
|
- '2500'
|
||||||
|
- ammmunition, loading, two-handed
|
||||||
|
- Light hammer:
|
||||||
|
- simple
|
||||||
|
- Martial
|
||||||
|
- '2'
|
||||||
|
- Bludgeoning
|
||||||
|
- 1d4
|
||||||
|
- 20/60
|
||||||
|
- ''
|
||||||
|
- '200'
|
||||||
|
- light, thrown
|
||||||
|
- Light repeating crossbow:
|
||||||
|
- simple
|
||||||
|
- Ranged
|
||||||
|
- '5'
|
||||||
|
- Piercing
|
||||||
|
- 1d8
|
||||||
|
- 40/160
|
||||||
|
- ''
|
||||||
|
- ''
|
||||||
|
- ammmunition, two-handed
|
||||||
|
- Longbow:
|
||||||
|
- martial
|
||||||
|
- Ranged
|
||||||
|
- '2'
|
||||||
|
- Piercing
|
||||||
|
- 1d8
|
||||||
|
- 150/600
|
||||||
|
- ''
|
||||||
|
- '5000'
|
||||||
|
- ammmunition, heavy, two-handed
|
||||||
|
- Longsword:
|
||||||
|
- martial
|
||||||
|
- Martial
|
||||||
|
- '3'
|
||||||
|
- Slashing
|
||||||
|
- 1d8
|
||||||
|
- null
|
||||||
|
- ''
|
||||||
|
- '1500'
|
||||||
|
- versatile
|
||||||
|
- Mace:
|
||||||
|
- simple
|
||||||
|
- Martial
|
||||||
|
- '4'
|
||||||
|
- Bludgeoning
|
||||||
|
- 1d6
|
||||||
|
- null
|
||||||
|
- ''
|
||||||
|
- '500'
|
||||||
|
- ''
|
||||||
|
- Maul:
|
||||||
|
- martial
|
||||||
|
- Martial
|
||||||
|
- '10'
|
||||||
|
- Bludgeoning
|
||||||
|
- 2d6
|
||||||
|
- null
|
||||||
|
- ''
|
||||||
|
- '1000'
|
||||||
|
- heavy, two-handed
|
||||||
|
- Morningstar:
|
||||||
|
- martial
|
||||||
|
- Martial
|
||||||
|
- '4'
|
||||||
|
- Piercing
|
||||||
|
- 1d8
|
||||||
|
- null
|
||||||
|
- ''
|
||||||
|
- '1500'
|
||||||
|
- ''
|
||||||
|
- Net:
|
||||||
|
- martial
|
||||||
|
- Ranged
|
||||||
|
- '3'
|
||||||
|
- ''
|
||||||
|
- null
|
||||||
|
- 5/15
|
||||||
|
- ''
|
||||||
|
- '100'
|
||||||
|
- special, thrown
|
||||||
|
- Pike:
|
||||||
|
- martial
|
||||||
|
- Martial
|
||||||
|
- '18'
|
||||||
|
- Piercing
|
||||||
|
- 1d10
|
||||||
|
- null
|
||||||
|
- ''
|
||||||
|
- '500'
|
||||||
|
- heavy, reach, two-handed
|
||||||
|
- Quarterstaff:
|
||||||
|
- simple
|
||||||
|
- Martial
|
||||||
|
- '4'
|
||||||
|
- Bludgeoning
|
||||||
|
- 1d6
|
||||||
|
- null
|
||||||
|
- ''
|
||||||
|
- '20'
|
||||||
|
- versatile
|
||||||
|
- Rapier:
|
||||||
|
- martial
|
||||||
|
- Martial
|
||||||
|
- '2'
|
||||||
|
- Piercing
|
||||||
|
- 1d8
|
||||||
|
- null
|
||||||
|
- ''
|
||||||
|
- '2500'
|
||||||
|
- finesse
|
||||||
|
- Scimitar:
|
||||||
|
- martial
|
||||||
|
- Martial
|
||||||
|
- '3'
|
||||||
|
- Slashing
|
||||||
|
- 1d6
|
||||||
|
- null
|
||||||
|
- ''
|
||||||
|
- '2500'
|
||||||
|
- finesse, light
|
||||||
|
- Shortbow:
|
||||||
|
- simple
|
||||||
|
- Ranged
|
||||||
|
- '2'
|
||||||
|
- Piercing
|
||||||
|
- 1d6
|
||||||
|
- 80/320
|
||||||
|
- ''
|
||||||
|
- '2500'
|
||||||
|
- ammmunition, two-handed
|
||||||
|
- Shortsword:
|
||||||
|
- martial
|
||||||
|
- Martial
|
||||||
|
- '2'
|
||||||
|
- Piercing
|
||||||
|
- 1d6
|
||||||
|
- null
|
||||||
|
- ''
|
||||||
|
- '1000'
|
||||||
|
- finesse, light
|
||||||
|
- Sickle:
|
||||||
|
- simple
|
||||||
|
- Martial
|
||||||
|
- '2'
|
||||||
|
- Slashing
|
||||||
|
- 1d4
|
||||||
|
- null
|
||||||
|
- ''
|
||||||
|
- '100'
|
||||||
|
- light
|
||||||
|
- Sling:
|
||||||
|
- simple
|
||||||
|
- Ranged
|
||||||
|
- '0'
|
||||||
|
- Bludgeoning
|
||||||
|
- 1d4
|
||||||
|
- 30/120
|
||||||
|
- ''
|
||||||
|
- '10'
|
||||||
|
- ammmunition
|
||||||
|
- Spear:
|
||||||
|
- simple
|
||||||
|
- Martial
|
||||||
|
- '3'
|
||||||
|
- Piercing
|
||||||
|
- 1d6
|
||||||
|
- 20/60
|
||||||
|
- ''
|
||||||
|
- '100'
|
||||||
|
- thrown, versatile
|
||||||
|
- Trident:
|
||||||
|
- martial
|
||||||
|
- Martial
|
||||||
|
- '4'
|
||||||
|
- Piercing
|
||||||
|
- 1d6
|
||||||
|
- 20/60
|
||||||
|
- ''
|
||||||
|
- '500'
|
||||||
|
- thrown, versatile
|
||||||
|
- War pick:
|
||||||
|
- martial
|
||||||
|
- Martial
|
||||||
|
- '2'
|
||||||
|
- Piercing
|
||||||
|
- 1d8
|
||||||
|
- null
|
||||||
|
- ''
|
||||||
|
- '500'
|
||||||
|
- ''
|
||||||
|
- Warhammer:
|
||||||
|
- martial
|
||||||
|
- Martial
|
||||||
|
- '2'
|
||||||
|
- Bludgeoning
|
||||||
|
- 1d8
|
||||||
|
- null
|
||||||
|
- ''
|
||||||
|
- '1500'
|
||||||
|
- versatile
|
||||||
|
- Whip:
|
||||||
|
- martial
|
||||||
|
- Martial
|
||||||
|
- '3'
|
||||||
|
- Slashing
|
||||||
|
- 1d4
|
||||||
|
- null
|
||||||
|
- ''
|
||||||
|
- '200'
|
||||||
|
- finesse, reach
|
||||||
|
- Yklwa:
|
||||||
|
- simple
|
||||||
|
- Martial
|
||||||
|
- '3'
|
||||||
|
- Piercing
|
||||||
|
- 1d8
|
||||||
|
- 10/30
|
||||||
|
- ''
|
||||||
|
- '100'
|
||||||
|
- thrown
|
||||||
|
|
|
@ -1,2 +1,21 @@
|
||||||
|
from rolltable import tables
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
sources = Path(__file__).parent / Path("sources")
|
||||||
|
|
||||||
|
|
||||||
class Item:
|
class Item:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def random_item(count=1):
|
||||||
|
types = (sources / Path('types.yaml')).read_text()
|
||||||
|
enchantments = (sources / Path('enchantments.yaml')).read_text()
|
||||||
|
items = []
|
||||||
|
for _ in range(count):
|
||||||
|
rt = tables.RollTable([types, enchantments], die=1, hide_rolls=True)
|
||||||
|
item = dict(zip(rt.rows[0], rt.rows[1]))
|
||||||
|
item['Enchantment Damage'] = '1d4'
|
||||||
|
items.append(item)
|
||||||
|
|
||||||
|
return items
|
||||||
|
|
|
@ -14,6 +14,8 @@ rich = "^13.7.0"
|
||||||
typer = "^0.9.0"
|
typer = "^0.9.0"
|
||||||
dice = "^4.0.0"
|
dice = "^4.0.0"
|
||||||
|
|
||||||
|
dnd-rolltable = { git = "https://github.com/evilchili/dnd-rolltable", branch='main' }
|
||||||
|
|
||||||
[tool.poetry.group.dev.dependencies]
|
[tool.poetry.group.dev.dependencies]
|
||||||
pytest = "^7.4.3"
|
pytest = "^7.4.3"
|
||||||
black = "^23.3.0"
|
black = "^23.3.0"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user