Exemplo n.º 1
0
    def from_critterdb(cls, data):
        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 errors.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)

        return cls(data['name'],
                   data['stats']['size'],
                   data['stats']['race'],
                   data['stats']['alignment'],
                   data['stats']['armorClass'],
                   data['stats']['armorType'],
                   hp,
                   hitdice,
                   data['stats']['speed'],
                   ability_scores,
                   cr,
                   data['stats']['experiencePoints'],
                   None,
                   ', '.join(data['stats']['senses']),
                   data['stats']['damageVulnerabilities'],
                   data['stats']['damageResistances'],
                   data['stats']['damageImmunities'],
                   data['stats']['conditionImmunities'],
                   saves,
                   skills,
                   data['stats']['languages'],
                   traits,
                   actions,
                   reactions,
                   legactions,
                   data['stats']['legendaryActionsPerRound'],
                   True,
                   'homebrew',
                   attacks,
                   data['flavor']['nameIsProper'],
                   data['flavor']['imageUrl'],
                   spellcasting=spellcasting)
Exemplo n.º 2
0
    def from_critterdb(cls, data):
        ability_scores = AbilityScores(
            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 errors.ExternalImportError(
                f"Monster's proficiency bonus is nonexistent ({data['name']})."
            )

        skills = {}
        raw_skills = []
        for skill in data['stats']['skills']:
            name = skill['name'].lower()
            if skill['proficient']:
                mod = ability_scores.get_mod(SKILL_MAP.get(name)) + proficiency
            else:
                try:
                    mod = skill['value']
                except KeyError:
                    continue
            if mod is not None:
                skills[name] = mod
                raw_skills.append(f"{skill['name']} {mod:+}")
        raw_skills = ', '.join(raw_skills)

        saves = {}
        raw_saves = []
        for save in data['stats']['savingThrows']:
            name = save['ability'].lower() + 'Save'
            if save['proficient']:
                mod = ability_scores.get_mod(SAVE_MAP.get(name)) + proficiency
            else:
                mod = save.get('value') or ability_scores.get_mod(
                    SAVE_MAP.get(name))
            saves[name] = mod
            raw_saves.append(f"{save['ability'].title()} {mod:+}")
        raw_saves = ', '.join(raw_saves)

        traits = parse_critterdb_traits(data, 'additionalAbilities')
        actions = parse_critterdb_traits(data, 'actions')
        reactions = parse_critterdb_traits(data, 'reactions')
        legactions = parse_critterdb_traits(data, 'legendaryActions')

        attacks = []
        for atk_src in (traits, actions, reactions, legactions):
            for trait in atk_src:
                attacks.extend(trait.attacks)

        resists = {
            "resist": data['stats']['damageResistances'],
            "immune": data['stats']['damageImmunities'],
            "vuln": data['stats']['damageVulnerabilities']
        }

        spellcasting = parse_critterdb_spellcasting(traits)

        return cls(data['name'],
                   data['stats']['size'],
                   data['stats']['race'],
                   data['stats']['alignment'],
                   data['stats']['armorClass'],
                   data['stats']['armorType'],
                   hp,
                   hitdice,
                   data['stats']['speed'],
                   ability_scores,
                   cr,
                   data['stats']['experiencePoints'],
                   None,
                   ', '.join(data['stats']['senses']),
                   data['stats']['damageVulnerabilities'],
                   data['stats']['damageResistances'],
                   data['stats']['damageImmunities'],
                   data['stats']['conditionImmunities'],
                   raw_saves,
                   saves,
                   raw_skills,
                   skills,
                   data['stats']['languages'],
                   traits,
                   actions,
                   reactions,
                   legactions,
                   data['stats']['legendaryActionsPerRound'],
                   True,
                   'homebrew',
                   attacks,
                   data['flavor']['nameIsProper'],
                   data['flavor']['imageUrl'],
                   raw_resists=resists,
                   spellcasting=spellcasting)