adding conversion utils for 5e.tools json data

This commit is contained in:
evilchili 2023-12-19 23:52:09 -08:00
parent bc9052242a
commit e073647e5d
6 changed files with 579 additions and 5 deletions

View File

@ -1,15 +1,19 @@
import logging
import os
from pathlib import Path
import typer
from rich.logging import RichHandler
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_state = {}
@app.callback()
@ -22,9 +26,20 @@ def main():
)
logging.getLogger('markdown_it').setLevel(logging.ERROR)
app_state['data'] = Path(__file__).parent / Path("sources")
@app.command()
def item(count: int = typer.Option(1, help="The number of items to generate.")):
console = Console(width=80)
for _ in range(count):
console.print(Item())
items = random_item(count)
console = Console()
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
View 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

View 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
View 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

View File

@ -1,2 +1,21 @@
from rolltable import tables
from pathlib import Path
sources = Path(__file__).parent / Path("sources")
class Item:
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

View File

@ -14,6 +14,8 @@ rich = "^13.7.0"
typer = "^0.9.0"
dice = "^4.0.0"
dnd-rolltable = { git = "https://github.com/evilchili/dnd-rolltable", branch='main' }
[tool.poetry.group.dev.dependencies]
pytest = "^7.4.3"
black = "^23.3.0"