Beispiel #1
0
    def get_skills_and_saves(self):
        """Returns a dict of all the character's skills."""
        if self.character_data is None:
            raise Exception('You must call get_character() first.')
        stats = self.get_stats()
        profBonus = stats.prof_bonus

        profs = dict()
        bonuses = dict()
        advantages = collections.defaultdict(lambda: [])

        for mod in self.modifiers():
            mod['subType'] = mod['subType'].replace("-saving-throws", "Save")
            if mod['type'] == 'half-proficiency':
                profs[mod['subType']] = max(profs.get(mod['subType'], 0), 0.5)
            elif mod['type'] == 'proficiency':
                profs[mod['subType']] = max(profs.get(mod['subType'], 0), 1)
            elif mod['type'] == 'expertise':
                profs[mod['subType']] = 2
            elif mod['type'] == 'bonus':
                if not mod['isGranted']:
                    continue
                if mod['statId'] is not None:
                    bonuses[mod['subType']] = bonuses.get(
                        mod['subType'], 0) + self.stat_from_id(mod['statId'])
                else:
                    bonuses[mod['subType']] = bonuses.get(
                        mod['subType'], 0) + (mod['value'] or 0)
            elif mod['type'] == 'advantage' and not mod[
                    'restriction']:  # unconditional adv
                advantages[mod['subType']].append(True)
            elif mod['type'] == 'disadvantage' and not mod[
                    'restriction']:  # unconditional dis
                advantages[mod['subType']].append(False)

        profs['animalHandling'] = profs.get('animal-handling', 0)
        profs['sleightOfHand'] = profs.get('sleight-of-hand', 0)
        advantages['animalHandling'] = advantages['animal-handling']
        advantages['sleightOfHand'] = advantages['sleight-of-hand']

        def _simplify_adv(adv_list):
            adv_set = set(adv_list)
            if len(adv_set) == 1:
                return adv_set.pop()
            return None

        skills = {}
        for skill in SKILL_NAMES:  # add proficiency and bonuses to skills
            relevantprof = profs.get(skill, 0)
            relevantbonus = bonuses.get(skill, 0)
            relevantadv = _simplify_adv(advantages[skill])
            if 'ability-checks' in profs and skill != 'initiative':
                relevantprof = max(relevantprof, profs['ability-checks'])
            if 'ability-checks' in bonuses and skill != 'initiative':
                relevantbonus += bonuses['ability-checks']
            skills[skill] = Skill(floor(
                stats.get_mod(SKILL_MAP[skill]) + (profBonus * relevantprof) +
                relevantbonus),
                                  relevantprof,
                                  relevantbonus,
                                  adv=relevantadv)

        # saves
        saves = {}
        for save in SAVE_NAMES:  # add proficiency and bonuses to skills
            relevantprof = profs.get(save, 0)
            relevantbonus = bonuses.get(save, 0)
            relevantadv = _simplify_adv(advantages[save])
            if 'saving-throws' in profs:
                relevantprof = max(relevantprof, profs['saving-throws'])
            if 'saving-throws' in bonuses:
                relevantbonus += bonuses['saving-throws']
            saves[save] = Skill(floor(
                stats.get_mod(SKILL_MAP[save]) + (profBonus * relevantprof) +
                relevantbonus),
                                relevantprof,
                                relevantbonus,
                                adv=relevantadv)

        # values
        ignored_ids = set()
        for charval in self.character_data['characterValues']:
            if charval['value'] is None:
                continue

            if charval['typeId'] == 39:  # misc saving throw bonus
                save_id = SAVE_NAMES[charval['valueId'] - 1]
                save_bonus = charval['value']
                saves[save_id].value += save_bonus
                saves[save_id].bonus += save_bonus
            elif charval['valueId'] in HOUSERULE_SKILL_MAP and charval[
                    'valueId'] not in ignored_ids:
                skill_name = HOUSERULE_SKILL_MAP[charval['valueId']]
                if charval['typeId'] == 23:  # override
                    skills[skill_name] = Skill(charval['value'])
                    ignored_ids.add(
                        charval['valueId']
                    )  # this must be the final value so we stop looking
                elif charval['typeId'] in {
                        24, 25
                }:  # PROBABLY skill magic/misc bonus
                    skills[skill_name].value += charval['value']
                    skills[skill_name].bonus += charval['value']
                elif charval['typeId'] == 26:  # proficiency stuff
                    relevantprof = profs.get(skill_name, 0)
                    skills[skill_name].value -= relevantprof * profBonus
                    if charval[
                            'value'] == 0:  # no prof, don't need to do anything
                        skills[skill_name].prof = 0
                    elif charval['value'] == 1:  # half prof, round down
                        skills[skill_name].value += profBonus // 2
                        skills[skill_name].prof = 0.5
                    elif charval['value'] == 2:  # half, round up
                        skills[skill_name].value += ceil(profBonus / 2)
                        skills[skill_name].prof = 0.5
                    elif charval['value'] == 3:  # full
                        skills[skill_name].value += profBonus
                        skills[skill_name].prof = 1
                    elif charval['value'] == 4:  # double
                        skills[skill_name].value += profBonus * 2
                        skills[skill_name].prof = 2

        skills = Skills(skills)
        saves = Saves(saves)

        return skills, saves
Beispiel #2
0
    def get_skills_and_saves(self):
        """Returns a dict of all the character's skills."""
        if self.character_data is None:
            raise Exception('You must call get_character() first.')
        character = self.character_data
        stats = self.get_stats()
        profBonus = stats.prof_bonus

        profs = dict()
        bonuses = dict()

        for modtype in character['modifiers'].values(
        ):  # calculate proficiencies in all skills
            for mod in modtype:
                mod['subType'] = mod['subType'].replace(
                    "-saving-throws", "Save")
                if mod['type'] == 'half-proficiency':
                    profs[mod['subType']] = max(profs.get(mod['subType'], 0),
                                                0.5)
                elif mod['type'] == 'proficiency':
                    profs[mod['subType']] = max(profs.get(mod['subType'], 0),
                                                1)
                elif mod['type'] == 'expertise':
                    profs[mod['subType']] = 2
                elif mod['type'] == 'bonus':
                    if not mod['isGranted']:
                        continue
                    if mod['statId'] is not None:
                        bonuses[mod['subType']] = bonuses.get(
                            mod['subType'], 0) + self.stat_from_id(
                                mod['statId'])
                    else:
                        bonuses[mod['subType']] = bonuses.get(
                            mod['subType'], 0) + (mod['value'] or 0)

        profs['animalHandling'] = profs.get('animal-handling', 0)
        profs['sleightOfHand'] = profs.get('sleight-of-hand', 0)

        skills = {}
        for skill in SKILL_NAMES:  # add proficiency and bonuses to skills
            relevantprof = profs.get(skill, 0)
            relevantbonus = bonuses.get(skill, 0)
            if 'ability-checks' in profs:
                relevantprof = max(relevantprof, profs['ability-checks'])
            if 'ability-checks' in bonuses:
                relevantbonus += bonuses['ability-checks']
            skills[skill] = Skill(
                floor(
                    stats.get_mod(SKILL_MAP[skill]) +
                    (profBonus * relevantprof) + relevantbonus), relevantprof,
                relevantbonus)

        saves = {}
        for save in SAVE_NAMES:  # add proficiency and bonuses to skills
            relevantprof = profs.get(save, 0)
            relevantbonus = bonuses.get(save, 0)
            if 'saving-throws' in profs:
                relevantprof = max(relevantprof, profs['saving-throws'])
            if 'saving-throws' in bonuses:
                relevantbonus += bonuses['saving-throws']
            saves[save] = Skill(
                floor(
                    stats.get_mod(SKILL_MAP[save]) +
                    (profBonus * relevantprof) + relevantbonus), relevantprof,
                relevantbonus)

        ignored_ids = set()
        for charval in self.character_data['characterValues']:
            if charval['valueId'] in HOUSERULE_SKILL_MAP and charval[
                    'valueId'] not in ignored_ids:
                skill_name = HOUSERULE_SKILL_MAP[charval['valueId']]
                if charval['typeId'] == 23:  # override
                    skills[skill_name] = Skill(charval['value'])
                    ignored_ids.add(
                        charval['valueId']
                    )  # this must be the final value so we stop looking
                elif charval['typeId'] in {
                        24, 25
                }:  # PROBABLY skill magic/misc bonus
                    skills[skill_name].value += charval['value']
                    skills[skill_name].bonus += charval['value']
                elif charval['typeId'] == 26:  # proficiency stuff
                    relevantprof = profs.get(skill_name, 0)
                    skills[skill_name].value -= relevantprof * profBonus
                    if charval[
                            'value'] == 0:  # no prof, don't need to do anything
                        skills[skill_name].prof = 0
                    elif charval['value'] == 1:  # half prof, round down
                        skills[skill_name].value += profBonus // 2
                        skills[skill_name].prof = 0.5
                    elif charval['value'] == 2:  # half, round up
                        skills[skill_name].value += ceil(profBonus / 2)
                        skills[skill_name].prof = 0.5
                    elif charval['value'] == 3:  # full
                        skills[skill_name].value += profBonus
                        skills[skill_name].prof = 1
                    elif charval['value'] == 4:  # double
                        skills[skill_name].value += profBonus * 2
                        skills[skill_name].prof = 2

        skills = Skills(skills)
        saves = Saves(saves)

        return skills, saves