async def send_character_details(self, ctx, final_level, race=None, _class=None, subclass=None, background=None): loadingMessage = await ctx.channel.send("Generating character, please wait...") color = random.randint(0, 0xffffff) # Name Gen # DMG name gen name = self.old_name_gen() # Stat Gen # 4d6d1 # reroll if too low/high stats = [roll('4d6kh3').total for _ in range(6)] await ctx.author.send("**Stats for {0}:** `{1}`".format(name, stats)) # Race Gen # Racial Features race = race or random.choice(await get_race_choices(ctx)) embed = EmbedWithAuthor(ctx) embed.title = race.name embed.add_field(name="Speed", value=race.speed) embed.add_field(name="Size", value=race.size) for t in race.traits: embeds.add_fields_from_long_text(embed, t.name, t.text) embed.set_footer(text=f"Race | {race.source_str()}") embed.colour = color await ctx.author.send(embed=embed) # Class Gen # Class Features # class _class = _class or random.choice(await available(ctx, compendium.classes, 'class')) subclass = subclass or (random.choice(subclass_choices) if (subclass_choices := await available(ctx, _class.subclasses, 'class')) else None) embed = EmbedWithAuthor(ctx) embed.title = _class.name embed.add_field(name="Hit Points", value=_class.hit_points) levels = [] for level in range(1, final_level + 1): level = _class.levels[level - 1] levels.append(', '.join([feature.name for feature in level])) embed.add_field(name="Starting Proficiencies", value=_class.proficiencies, inline=False) embed.add_field(name="Starting Equipment", value=_class.equipment, inline=False) level_features_str = "" for i, l in enumerate(levels): level_features_str += f"`{i + 1}` {l}\n" embed.description = level_features_str await ctx.author.send(embed=embed) # level table embed = EmbedWithAuthor(ctx) embed.title = f"{_class.name}, Level {final_level}" for resource, value in zip(_class.table.headers, _class.table.levels[final_level - 1]): if value != '0': embed.add_field(name=resource, value=value) embed.colour = color await ctx.author.send(embed=embed) # features embed_queue = [EmbedWithAuthor(ctx)] num_fields = 0 def inc_fields(ftext): nonlocal num_fields num_fields += 1 if num_fields > 25: embed_queue.append(EmbedWithAuthor(ctx)) num_fields = 0 if len(str(embed_queue[-1].to_dict())) + len(ftext) > 5800: embed_queue.append(EmbedWithAuthor(ctx)) num_fields = 0 def add_levels(source): for level in range(1, final_level + 1): level_features = source.levels[level - 1] for f in level_features: for field in embeds.get_long_field_args(f.text, f.name): inc_fields(field['value']) embed_queue[-1].add_field(**field) add_levels(_class) if subclass: add_levels(subclass) for embed in embed_queue: embed.colour = color await ctx.author.send(embed=embed) # Background Gen # Inventory/Trait Gen background = background or random.choice(await available(ctx, compendium.backgrounds, 'background')) embed = EmbedWithAuthor(ctx) embed.title = background.name embed.set_footer(text=f"Background | {background.source_str()}") ignored_fields = ['suggested characteristics', 'personality trait', 'ideal', 'bond', 'flaw', 'specialty', 'harrowing event'] for trait in background.traits: if trait.name.lower() in ignored_fields: continue text = textwrap.shorten(trait.text, width=1020, placeholder="...") embed.add_field(name=trait.name, value=text, inline=False) embed.colour = color await ctx.author.send(embed=embed) out = f"{ctx.author.mention}\n" \ f"{name}, {race.name} {subclass.name if subclass else ''} {_class.name} {final_level}. " \ f"{background.name} Background.\n" \ f"Stat Array: `{stats}`\nI have PM'd you full character details." await loadingMessage.edit(content=out)
async def genChar(self, ctx, final_level, race=None, _class=None, subclass=None, background=None): loadingMessage = await self.bot.send_message(ctx.message.channel, "Generating character, please wait...") color = random.randint(0, 0xffffff) # Name Gen # DMG name gen name = self.nameGen() # Stat Gen # 4d6d1 # reroll if too low/high stats = self.genStats() await self.bot.send_message(ctx.message.author, "**Stats for {0}:** `{1}`".format(name, stats)) # Race Gen # Racial Features race = race or random.choice([r for r in c.fancyraces if r.source in ('PHB', 'VGM', 'MTF')]) embed = EmbedWithAuthor(ctx) embed.title = race.name embed.description = f"Source: {race.source}" embed.add_field(name="Speed", value=race.get_speed_str()) embed.add_field(name="Size", value=race.size) embed.add_field(name="Ability Bonuses", value=race.get_asi_str()) for t in race.get_traits(): f_text = t['text'] f_text = [f_text[i:i + 1024] for i in range(0, len(f_text), 1024)] embed.add_field(name=t['name'], value=f_text[0]) for piece in f_text[1:]: embed.add_field(name="** **", value=piece) embed.colour = color await self.bot.send_message(ctx.message.author, embed=embed) # Class Gen # Class Features _class = _class or random.choice([cl for cl in c.classes if not 'UA' in cl.get('source')]) subclass = subclass or random.choice([s for s in _class['subclasses'] if not 'UA' in s['source']]) embed = EmbedWithAuthor(ctx) embed.title = f"{_class['name']} ({subclass['name']})" embed.add_field(name="Hit Die", value=f"1d{_class['hd']['faces']}") embed.add_field(name="Saving Throws", value=', '.join(ABILITY_MAP.get(p) for p in _class['proficiency'])) levels = [] starting_profs = f"You are proficient with the following items, " \ f"in addition to any proficiencies provided by your race or background.\n" \ f"Armor: {', '.join(_class['startingProficiencies'].get('armor', ['None']))}\n" \ f"Weapons: {', '.join(_class['startingProficiencies'].get('weapons', ['None']))}\n" \ f"Tools: {', '.join(_class['startingProficiencies'].get('tools', ['None']))}\n" \ f"Skills: Choose {_class['startingProficiencies']['skills']['choose']} from " \ f"{', '.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}" for level in range(1, final_level + 1): level_str = [] level_features = _class['classFeatures'][level - 1] for feature in level_features: level_str.append(feature.get('name')) levels.append(', '.join(level_str)) embed.add_field(name="Starting Proficiencies", value=starting_profs) embed.add_field(name="Starting Equipment", value=starting_items) level_features_str = "" for i, l in enumerate(levels): level_features_str += f"`{i+1}` {l}\n" embed.description = level_features_str embed.colour = color await self.bot.send_message(ctx.message.author, embed=embed) embed = EmbedWithAuthor(ctx) level_resources = {} for table in _class['classTableGroups']: relevant_row = table['rows'][final_level - 1] for i, col in enumerate(relevant_row): level_resources[table['colLabels'][i]] = parse_data_entry([col]) for res_name, res_value in level_resources.items(): embed.add_field(name=res_name, value=res_value) embed.colour = color await self.bot.send_message(ctx.message.author, embed=embed) embed_queue = [EmbedWithAuthor(ctx)] num_subclass_features = 0 num_fields = 0 def inc_fields(text): nonlocal num_fields num_fields += 1 if num_fields > 25: embed_queue.append(EmbedWithAuthor(ctx)) num_fields = 0 if len(str(embed_queue[-1].to_dict())) + len(text) > 5800: embed_queue.append(EmbedWithAuthor(ctx)) num_fields = 0 for level in range(1, final_level + 1): level_features = _class['classFeatures'][level - 1] for f in level_features: if f.get('gainSubclassFeature'): num_subclass_features += 1 text = parse_data_entry(f['entries']) text = [text[i:i + 1024] for i in range(0, len(text), 1024)] inc_fields(text[0]) embed_queue[-1].add_field(name=f['name'], value=text[0]) for piece in text[1:]: inc_fields(piece) embed_queue[-1].add_field(name="\u200b", value=piece) 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': parse_data_entry(entry['entries'])} text = [fe['text'][i:i + 1024] for i in range(0, len(fe['text']), 1024)] inc_fields(text[0]) embed_queue[-1].add_field(name=fe['name'], value=text[0]) for piece in text[1:]: inc_fields(piece) embed_queue[-1].add_field(name="\u200b", value=piece) for embed in embed_queue: embed.colour = color await self.bot.send_message(ctx.message.author, embed=embed) # Background Gen # Inventory/Trait Gen background = background or random.choice(c.backgrounds) embed = EmbedWithAuthor(ctx) embed.title = background['name'] embed.description = f"*Source: {background.get('source', 'Unknown')}*" ignored_fields = ['suggested characteristics', 'specialty', 'harrowing event'] for trait in background['trait']: if trait['name'].lower() in ignored_fields: continue text = '\n'.join(t for t in trait['text'] if t) text = [text[i:i + 1024] for i in range(0, len(text), 1024)] embed.add_field(name=trait['name'], value=text[0]) for piece in text[1:]: embed.add_field(name="\u200b", value=piece) embed.colour = color await self.bot.send_message(ctx.message.author, embed=embed) out = "{6}\n{0}, {1} {7} {2} {3}. {4} Background.\nStat Array: `{5}`\nI have PM'd you full character details.".format( name, race.name, _class['name'], final_level, background['name'], stats, ctx.message.author.mention, subclass['name']) await self.bot.edit_message(loadingMessage, out)