aboutsummaryrefslogtreecommitdiff
path: root/parser/scrapeToJson.py
diff options
context:
space:
mode:
authorYour Name <you@example.com>2021-04-15 15:23:23 -0400
committerYour Name <you@example.com>2021-04-15 15:23:23 -0400
commitdfce4d0398a8bafbb7ad7a31345af181c0269c09 (patch)
tree695162ff8cc25e146f52d9e26fe19ffa9934b3d6 /parser/scrapeToJson.py
parent9034c3d2533177f7cb7a7ce939ec53f7fa63f60e (diff)
downloaddmtool-dfce4d0398a8bafbb7ad7a31345af181c0269c09.tar.gz
dmtool-dfce4d0398a8bafbb7ad7a31345af181c0269c09.tar.bz2
dmtool-dfce4d0398a8bafbb7ad7a31345af181c0269c09.zip
Added spells
Diffstat (limited to 'parser/scrapeToJson.py')
-rwxr-xr-xparser/scrapeToJson.py70
1 files changed, 64 insertions, 6 deletions
diff --git a/parser/scrapeToJson.py b/parser/scrapeToJson.py
index d9444c7..24980a1 100755
--- a/parser/scrapeToJson.py
+++ b/parser/scrapeToJson.py
@@ -4,7 +4,7 @@ import json
import re
import utils
-def processMonster(data, weapons, armors):
+def processMonster(data, weapons, armors, spells):
names2names = {'ac': 'Armor Class', 'hp': 'Hit Points', 'speed': 'Speed', 'saves': 'Saving Throws', 'd_resistances': 'Damage Resistances?', 'd_vulnerabilities': 'Damage Vulnerabilities', 'd_immunities': 'Damage Immunities', 'c_immunities': 'Condition Immunities', 'senses': 'Senses', 'langs': 'Languages', 'skills': 'Skills'}
desc = {}
for name in names2names:
@@ -74,7 +74,8 @@ def processMonster(data, weapons, armors):
found = True
bonus = armorDict['ac']
typ = armorDict['type']
- desc['inventory'].append(armorDict)
+ #desc['inventory'].append(armorDict)
+ desc['inventory'].append({'name': a, 'type': 'armor', 'text': '{} armor'.format(a)})
break
if not found:
print('Cound not identify armor: {}'.format(a))
@@ -188,8 +189,6 @@ def processMonster(data, weapons, armors):
if isOr and toAppend['dmg_type'] == details['damage'][-1]['dmg_type'] and toAppend['dmg_die_sides'] == details['damage'][-1]['dmg_die_sides'] + 2:
details['properties'].append('versatile')
else:
- if isOr:
- print('We got here for {}!!!!!!!!!!!!!!'.format(desc['name']))
details['damage'].append(toAppend)
details['text'] = re.search('(?s)(_Hit:_ (?:\d+ [^\.]*\.)?)(.*)', action['text']).group(2).strip()
if len(details['damage']) == 0:
@@ -198,7 +197,66 @@ def processMonster(data, weapons, armors):
for name, value in utils.formatWeapon(action['name'], details['range'][0], details['range'][1], details['reach'], details['damage'][0]['dmg_type'], details['damage'][0]['dmg_die_count'], details['damage'][0]['dmg_die_sides'], action['text']).items():
action['attack'][name] = value
if action['attack']['type'] != 'unknown':
- desc['inventory'].append(action['attack'])
+ #desc['inventory'].append(action['attack'])
+ desc['inventory'].append({'name': action['attack']['name'], 'type': 'weapon', 'text': action['text']})
+ elif 'spellcasting' in action['name']:
+ action['type'] = 'spellcasting'
+ print('{} has spellcasting!'.format(desc['name']))
+ abilities = ['Intelligence', 'Wisdom', 'Charisma']
+ for ability in abilities:
+ if ability in action['text']:
+ if 'spellcasting_ability' in action:
+ print('Uh oh, both {} and {} present!'.format(action['spellcasting_ability'], ability))
+ exit(1)
+ action['spellcasting_ability'] = ability.lower()[:3]
+ if 'spellcasting_ability' not in action:
+ print('Uh oh, no spellcasting ability!')
+ exit(1)
+ # Interpretation of slots differs if is innate or not
+ action['innate'] = 'innate' in action['text']
+ # Now, break down by level
+ action['levels'] = []
+ def getSpells(text):
+ names = []
+ [names.extend(m.split(', ')) for m in re.findall('(?<=\*\*_).*?(?=_\*\*)', text)]
+ #ret = []
+ for name in names:
+ found = False
+ for spell in spells:
+ if spell['name'] == name:
+ #ret.append(spell)
+ found = True
+ break
+ if not found:
+ print('Could not find spell: {}!!!!!!!!!!!!'.format(name))
+ #return ret
+ return names
+ # Sometimes it is in the name (as is case with mephits)
+ if '/day' in action['name']:
+ slots = int(re.search('(?<=\()\d+', action['name']).group(0))
+ spellNames = getSpells(action['text'])
+ action['levels'].append({'slots': slots, 'spells': spellNames})
+ else:
+ # Repair pit fiend
+ m = re.match('(?sm)^(.+) \d+/day each: ', action['text'])
+ if m:
+ action['text'] = re.sub(re.escape(m.group(0)), m.group(0) + '**_', action['text'])
+ action['text'] = re.sub(re.escape(m.group(1)), m.group(1) + '_**\n', action['text'])
+ for line in action['text'].split('\n')[1:]:
+ line = line.lower()
+ if all(string not in line for string in ['(', '/day', 'at will']):
+ continue
+ #print('Searching line {}'.format(line))
+ # If it's "at will", then slots = 0
+ if 'at will' in line:
+ slots = 0
+ else:
+ slots = int(re.search('(\d+)( slot|/day)', line).group(1))
+ spellNames = getSpells(line)
+ action['levels'].append({'slots': slots, 'spells': spellNames})
+
+ action['name'] = 'spellcasting'
+
# Remove weapon actions from features (they were just added to inventory)
desc['features'] = [a for a in desc['features'] if 'attack' not in a or a['attack']['type'] == 'unknown']
# Get rid of precalculated passive perception
@@ -233,4 +291,4 @@ for monster in Path('../../5thSRD/docs/gamemaster_rules/monsters/').glob('*.md')
data = f.read()
Path('monsters/').mkdir(exist_ok=True)
with open('monsters/' + monster.stem + '.json', 'w') as f:
- json.dump(processMonster(data, weapons, armors), f, indent=2)
+ json.dump(processMonster(data, weapons, armors, spells), f, indent=2)