Example #1
0
    def damage(self,
               dice_str,
               crit=False,
               d=None,
               c=None,
               critdice=0,
               overheal=False):
        """
        Does damage to a combatant, and returns the rolled result and total, accounting for resistances.

        :param str dice_str: The damage to do (e.g. ``"1d6[acid]"``).
        :param bool crit: Whether or not the damage should be rolled as a crit.
        :param str d: Any additional damage to add (equivalent of -d).
        :param str c: Any additional damage to add to crits (equivalent of -c).
        :param int critdice: How many extra weapon dice to roll on a crit (in addition to normal dice).
        :param bool overheal: Whether or not to allow this damage to exceed a target's HP max.
        :return: Dictionary representing the results of the Damage Automation.
        :rtype: dict
        """
        from cogs5e.models.automation import AutomationContext, AutomationTarget, \
            Damage  # this has to be here to avoid circular imports

        class _SimpleAutomationContext(AutomationContext):
            def __init__(self, caster, target, args, combat, crit=False):
                super(_SimpleAutomationContext,
                      self).__init__(None, None, caster, [target], args,
                                     combat)
                self.in_crit = crit
                self.target = AutomationTarget(target)

        args = ParsedArguments.from_dict({
            'critdice': [critdice],
            'resist':
            self._combatant.resistances['resist'],
            'immune':
            self._combatant.resistances['immune'],
            'vuln':
            self._combatant.resistances['vuln']
        })
        if d:
            args['d'] = d
        if c:
            args['c'] = c
        damage = Damage(dice_str, overheal=overheal)
        autoctx = _SimpleAutomationContext(StatBlock("generic"),
                                           self._combatant, args,
                                           self._combatant.combat, crit)

        result = damage.run(autoctx)
        roll_for = "Damage" if not result.in_crit else "Damage (CRIT!)"
        return {
            'damage': f"**{roll_for}**: {result.damage_roll.result}",
            'total': result.damage,
            'roll': SimpleRollResult(result.damage_roll)
        }
Example #2
0
    def save(self, ability: str, adv: bool = None):
        """
        Rolls a combatant's saving throw.

        :param str ability: The type of save ("str", "dexterity", etc).
        :param bool adv: Whether to roll the save with advantage. Rolls with advantage if ``True``, disadvantage if ``False``, or normally if ``None``.
        :returns: A SimpleRollResult describing the rolled save.
        :rtype: :class:`~aliasing.api.functions.SimpleRollResult`
        """  # noqa: E501
        try:
            save = self._combatant.saves.get(str(ability))
        except ValueError:
            raise InvalidSaveType

        sb = self._combatant.active_effects('sb')
        saveroll = save.d20(base_adv=adv)
        if sb:
            saveroll = f'{saveroll}+{"+".join(sb)}'

        save_roll = roll(saveroll)
        return SimpleRollResult(save_roll)