def from_dict(cls, d): if 'monsters' in d: d['monsters'] = [ Monster.from_bestiary(m, d['name']) for m in d['monsters'] ] if 'published' not in d: # versions prior to v1.5.11 don't have this tag, default to True d['published'] = True return cls(**d)
async def load_monsters(self, ctx): if not self._monsters: bestiary = await ctx.bot.mdb.bestiaries.find_one( {"_id": self.id}, projection=['monsters']) self._monsters = [ Monster.from_bestiary(m, self.name) for m in bestiary['monsters'] ] return self._monsters
def load_common(self): self.backgrounds = [ Background.from_data(b) for b in self.raw_backgrounds ] self.classes = [Class.from_data(c) for c in self.raw_classes] self.races = [Race.from_data(r) for r in self.raw_races] self.subraces = [Race.from_data(r) for r in self.raw_subraces] self.feats = [Feat.from_data(f) for f in self.raw_feats] self.items = [Item.from_data(i) for i in self.raw_items] self.monsters = [Monster.from_data(m) for m in self.raw_monsters] self.spells = [Spell.from_data(s) for s in self.raw_spells] # generated self._load_classfeats() self._load_subclasses() self._load_racefeats()
def _monster_factory(data, bestiary_name): ability_scores = BaseStats(data['stats']['proficiencyBonus'] or 0, data['stats']['abilityScores']['strength'] or 10, data['stats']['abilityScores']['dexterity'] or 10, data['stats']['abilityScores']['constitution'] or 10, data['stats']['abilityScores']['intelligence'] or 10, data['stats']['abilityScores']['wisdom'] or 10, data['stats']['abilityScores']['charisma'] or 10) cr = {0.125: '1/8', 0.25: '1/4', 0.5: '1/2'}.get(data['stats']['challengeRating'], str(data['stats']['challengeRating'])) num_hit_die = data['stats']['numHitDie'] hit_die_size = data['stats']['hitDieSize'] con_by_level = num_hit_die * ability_scores.get_mod('con') hp = floor(((hit_die_size + 1) / 2) * num_hit_die) + con_by_level hitdice = f"{num_hit_die}d{hit_die_size} + {con_by_level}" proficiency = data['stats']['proficiencyBonus'] if proficiency is None: raise ExternalImportError(f"Monster's proficiency bonus is nonexistent ({data['name']}).") skills = Skills.default(ability_scores) skill_updates = {} for skill in data['stats']['skills']: name = spaced_to_camel(skill['name']) if skill['proficient']: mod = skills[name].value + proficiency else: mod = skill.get('value') if mod is not None: skill_updates[name] = mod skills.update(skill_updates) saves = Saves.default(ability_scores) save_updates = {} for save in data['stats']['savingThrows']: name = save['ability'].lower() + 'Save' if save['proficient']: mod = saves.get(name).value + proficiency else: mod = save.get('value') if mod is not None: save_updates[name] = mod saves.update(save_updates) attacks = [] traits, atks = parse_critterdb_traits(data, 'additionalAbilities') attacks.extend(atks) actions, atks = parse_critterdb_traits(data, 'actions') attacks.extend(atks) reactions, atks = parse_critterdb_traits(data, 'reactions') attacks.extend(atks) legactions, atks = parse_critterdb_traits(data, 'legendaryActions') attacks.extend(atks) attacks = AttackList.from_dict(attacks) spellcasting = parse_critterdb_spellcasting(traits, ability_scores) resistances = Resistances.from_dict(dict(vuln=data['stats']['damageVulnerabilities'], resist=data['stats']['damageResistances'], immune=data['stats']['damageImmunities'])) return Monster(name=data['name'], size=data['stats']['size'], race=data['stats']['race'], alignment=data['stats']['alignment'], ac=data['stats']['armorClass'], armortype=data['stats']['armorType'], hp=hp, hitdice=hitdice, speed=data['stats']['speed'], ability_scores=ability_scores, saves=saves, skills=skills, senses=', '.join(data['stats']['senses']), resistances=resistances, display_resists=resistances, condition_immune=data['stats']['conditionImmunities'], languages=data['stats']['languages'], cr=cr, xp=data['stats']['experiencePoints'], traits=traits, actions=actions, reactions=reactions, legactions=legactions, la_per_round=data['stats']['legendaryActionsPerRound'], attacks=attacks, proper=data['flavor']['nameIsProper'], image_url=data['flavor']['imageUrl'], spellcasting=spellcasting, homebrew=True, source=bestiary_name)