def __init__(self): with open('./static/races.json', 'r') as f: _raw = json.load(f) self.rfeats = [] self.fancyraces = [Race.from_data(r) for r in _raw] for race in _raw: for entry in race['entries']: if isinstance(entry, dict) and 'name' in entry: temp = { 'name': "{}: {}".format(race['name'], entry['name']), 'text': render(entry['entries']), 'srd': race['srd'] } self.rfeats.append(temp) with open('./static/classes.json', 'r') as f: self.classes = json.load(f) with open('./static/classfeats.json') as f: self.cfeats = json.load(f) with open('./static/spells.json', 'r') as f: self.spells = [Spell.from_data(r) for r in json.load(f)] with open('./static/items.json', 'r') as f: _items = json.load(f) self.items = [i for i in _items if i.get('type') is not '$'] with open('./static/backgrounds.json', 'r') as f: self.backgrounds = [Background.from_data(b) for b in json.load(f)] self.subclasses = self.load_subclasses()
def get_traits(self): traits = [] for entry in self.entries: if isinstance(entry, dict) and 'name' in entry: temp = {'name': entry['name'], 'text': render(entry['entries'])} traits.append(temp) return traits
def create_char(api_key, name, level, race, _class, subclass, background): # things to add in batches effects = [] features = [] profs_to_add = [] caveats = [] # a to do list for the user # setup client dc = DicecloudClient(None, None, api_key, no_meteor=True) # Name Gen + Setup # DMG name gen char_id = dc.create_character(name=name, race=race.name, backstory=background.name) # Stat Gen # Allow user to enter base values caveats.append( "**Base Ability Scores**: Enter your base ability scores (without modifiers) in the feature " "titled Base Ability Scores.") # Race Gen # Racial Features speed = race.get_speed_int() if speed: effects.append( Effect(Parent.race(char_id), 'base', value=int(speed), stat='speed')) for k, v in race.ability.items(): if not k == 'choose': effects.append( Effect(Parent.race(char_id), 'add', value=int(v), stat=ABILITY_MAP[k].lower())) else: effects.append( Effect(Parent.race(char_id), 'add', value=int(v[0].get('amount', 1)))) caveats.append( f"**Racial Ability Bonus ({int(v[0].get('amount', 1)):+})**: In your race (Journal tab), select the" f" score you want a bonus to (choose {v[0]['count']} from {', '.join(v[0]['from'])})." ) for t in race.get_traits(): features.append(Feature(t['name'], t['text'])) caveats.append( "**Racial Features**: Check that the number of uses for each feature is correct, and apply " "any effects they grant.") # Class Gen # Class Features class_id = dc.insert_class(char_id, Class(level, _class['name'])) effects.append( Effect(Parent.class_(class_id), 'add', stat=f"d{_class['hd']['faces']}HitDice", calculation=f"{_class['name']}Level")) hp_per_level = (int(_class['hd']['faces']) / 2) + 1 first_level_hp = int(_class['hd']['faces']) - hp_per_level effects.append( Effect( Parent.class_(class_id), 'add', stat='hitPoints', calculation=f"{hp_per_level}*{_class['name']}Level+{first_level_hp}" )) caveats.append( "**HP**: HP is currently calculated using class average; change the value in the Journal tab " "under your class if you wish to change it.") for saveProf in _class['proficiency']: prof_key = ABILITY_MAP.get(saveProf).lower() + 'Save' profs_to_add.append( Proficiency(Parent.class_(class_id), prof_key, type_='save')) for prof in _class['startingProficiencies'].get('armor', []): profs_to_add.append( Proficiency(Parent.class_(class_id), prof, type_='armor')) for prof in _class['startingProficiencies'].get('weapons', []): profs_to_add.append( Proficiency(Parent.class_(class_id), prof, type_='weapon')) for prof in _class['startingProficiencies'].get('tools', []): profs_to_add.append( Proficiency(Parent.class_(class_id), prof, type_='tool')) for _ in range(int(_class['startingProficiencies']['skills']['choose'])): profs_to_add.append(Proficiency(Parent.class_(class_id), type_='skill')) # add placeholders caveats.append( f"**Skill Proficiencies**: You get to choose your skill proficiencies. Under your class " f"in the Journal tab, you may select {_class['startingProficiencies']['skills']['choose']} " f"skills from {', '.join(_class['startingProficiencies']['skills']['from'])}." ) equip_choices = '\n'.join(f"• {i}" for i in _class['startingEquipment']['default']) gold_alt = f"Alternatively, you may start with {_class['startingEquipment']['goldAlternative']} gp " \ f"to buy your own equipment." if 'goldAlternative' in _class['startingEquipment'] else '' starting_items = f"You start with the following items, plus anything provided by your background. \n" \ f"{equip_choices} \n" \ f"{gold_alt}" caveats.append(f"**Starting Class Equipment**: {starting_items}") level_resources = {} for table in _class.get('classTableGroups', []): relevant_row = table['rows'][level - 1] for i, col in enumerate(relevant_row): level_resources[table['colLabels'][i]] = render([col]) for res_name, res_value in level_resources.items(): stat_name = CLASS_RESOURCE_NAMES.get(res_name) if stat_name: try: effects.append( Effect(Parent.class_(class_id), 'base', value=int(res_value), stat=stat_name)) except ValueError: # edge case: level 20 barb rage pass num_subclass_features = 0 for level in range(1, level + 1): level_features = _class['classFeatures'][level - 1] for f in level_features: if f.get('gainSubclassFeature'): num_subclass_features += 1 text = render(f['entries'], True) features.append(Feature(f['name'], text)) for num in range(num_subclass_features): level_features = subclass['subclassFeatures'][num] for feature in level_features: for entry in feature.get('entries', []): if not isinstance(entry, dict): continue if not entry.get('type') == 'entries': continue fe = { 'name': entry['name'], 'text': render(entry['entries'], True) } features.append(Feature(fe['name'], fe['text'])) caveats.append( "**Class Features**: Check that the number of uses for each feature is correct, and apply " "any effects they grant.") caveats.append( "**Spellcasting**: If your class can cast spells, be sure to set your number of known spells, " "max prepared, DC, attack bonus, and what spells you know in the Spells tab. You can add a " "spell to your spellbook by using the spellbook tool.") # Background Gen # Inventory/Trait Gen for trait in background.traits: text = trait['text'] if any(i in trait['name'].lower() for i in ('proficiency', 'language')): continue if trait['name'].lower().startswith('feature'): tname = trait['name'][9:] features.append(Feature(tname, text)) elif trait['name'].lower().startswith('equipment'): caveats.append( f"**Background Equipment**: Your background grants you {text}") for proftype, profs in background.proficiencies.items(): if proftype == 'tool': for prof in profs: profs_to_add.append( Proficiency(Parent.background(char_id), prof, type_='tool')) elif proftype == 'skill': for prof in profs: dc_prof = SKILL_MAP.get(prof, prof) if dc_prof: profs_to_add.append( Proficiency(Parent.background(char_id), dc_prof)) else: profs_to_add.append(Proficiency( Parent.background(char_id))) caveats.append( f"**Choose Skill**: Your background gives you proficiency in either {prof}. " f"Choose this in the Background section of the Persona tab." ) elif proftype == 'language': for prof in profs: profs_to_add.append( Proficiency(Parent.background(char_id), prof, type_='language')) caveats.append( "**Languages**: Some backgrounds' languages may ask you to choose one or more. Fill " "this out in the Background section of the Persona tab.") features.append( Feature( "!!! Caveats !!!", "**__Caveats__** \nNot everything is automagical! Here are some things you still " "have to do manually: \n" + '\n\n'.join(caveats))) dc.insert_features(char_id, features) dc.insert_effects(char_id, effects) dc.insert_proficiencies(char_id, profs_to_add) return char_id