Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
if effect_d:
if d:
d = f"{d}+{effect_d}"
else:
d = effect_d
dice_ast = copy.copy(d20.parse(self.dice))
dice_ast = _upcast_scaled_dice(self, autoctx, dice_ast)
if not self.hidden:
# -mi # (#527)
if mi:
dice_ast = d20.utils.tree_map(_mi_mapper(mi), dice_ast)
if d:
d_ast = d20.parse(d)
dice_ast.roll = d20.ast.BinOp(dice_ast.roll, '+', d_ast.roll)
if maxdmg:
dice_ast = d20.utils.tree_map(_max_mapper, dice_ast)
rolled = roll(dice_ast)
if not self.hidden:
autoctx.meta_queue(f"**{self.name.title()}**: {rolled.result}")
d20.utils.simplify_expr(rolled.expr)
autoctx.metavars[self.name] = RerollableStringifier().stringify(rolled.expr.roll)
# check if we actually need to care about the -d tag
if self.is_meta(autoctx):
d_arg = None # d was likely applied in the Roll effect already
# set up damage AST
damage = autoctx.parse_annostr(damage)
dice_ast = copy.copy(d20.parse(damage))
dice_ast = _upcast_scaled_dice(self, autoctx, dice_ast)
# -mi # (#527)
if mi_arg:
dice_ast = d20.utils.tree_map(_mi_mapper(mi_arg), dice_ast)
# -d #
if d_arg:
d_ast = d20.parse(d_arg)
dice_ast.roll = d20.ast.BinOp(dice_ast.roll, '+', d_ast.roll)
# crit
in_crit = autoctx.in_crit or crit_arg
roll_for = "Damage" if not in_crit else "Damage (CRIT!)"
if in_crit:
dice_ast = d20.utils.tree_map(_crit_mapper, dice_ast)
if critdice and not autoctx.is_spell:
# add X critdice to the leftmost node if it's dice
left = d20.utils.leftmost(dice_ast)
if isinstance(left, d20.ast.Dice):
left.num += int(critdice)
# -c #
if c_arg and in_crit:
c_ast = d20.parse(c_arg)
async def _roll_many(self, ctx, iterations, roll_str, dc=None, adv=None):
if iterations < 1 or iterations > 100:
return await ctx.send("Too many or too few iterations.")
if adv is None:
adv = d20.AdvType.NONE
results = []
successes = 0
ast = d20.parse(roll_str, allow_comments=True)
roller = d20.Roller(context=PersistentRollContext())
for _ in range(iterations):
res = roller.roll(ast, advantage=adv)
if dc is not None and res.total >= dc:
successes += 1
results.append(res)
if dc is None:
header = f"Rolling {iterations} iterations..."
footer = f"{sum(o.total for o in results)} total."
else:
header = f"Rolling {iterations} iterations, DC {dc}..."
footer = f"{successes} successes, {sum(o.total for o in results)} total."
if ast.comment:
def run(self, autoctx):
super(TempHP, self).run(autoctx)
args = autoctx.args
amount = self.amount
maxdmg = args.last('max', None, bool, ephem=True)
# check if we actually need to run this damage roll (not in combat and roll is redundant)
if autoctx.target.is_simple and self.is_meta(autoctx, True):
return
amount = autoctx.parse_annostr(amount)
dice_ast = copy.copy(d20.parse(amount))
dice_ast = _upcast_scaled_dice(self, autoctx, dice_ast)
if maxdmg:
dice_ast = d20.utils.tree_map(_max_mapper, dice_ast)
dmgroll = roll(dice_ast)
autoctx.queue(f"**THP**: {dmgroll.result}")
if autoctx.target.combatant:
autoctx.target.combatant.temp_hp = max(dmgroll.total, 0)
autoctx.footer_queue(
"{}: {}".format(autoctx.target.combatant.name, autoctx.target.combatant.hp_str()))
elif autoctx.target.character:
autoctx.target.character.temp_hp = max(dmgroll.total, 0)
autoctx.footer_queue(
"{}: {}".format(autoctx.target.character.name, autoctx.target.character.hp_str()))
def get_roll_comment(expr):
"""Gets the dice and comment from a roll expression."""
result = d20.parse(expr, allow_comments=True)
return str(result.roll), (result.comment or '')
elif level < 17:
level_dice = 3
else:
level_dice = 4
def mapper(node):
if isinstance(node, d20.ast.Dice):
node.num = level_dice
return node
dice_ast = d20.utils.tree_map(mapper, dice_ast)
if effect.higher and not autoctx.get_cast_level() == autoctx.spell.level:
higher = effect.higher.get(str(autoctx.get_cast_level()))
if higher:
higher_ast = d20.parse(higher)
dice_ast.roll = d20.ast.BinOp(dice_ast.roll, '+', higher_ast.roll)
return dice_ast
def run(self, autoctx):
super(Roll, self).run(autoctx)
d = autoctx.args.join('d', '+', ephem=True)
maxdmg = autoctx.args.last('max', None, bool, ephem=True)
mi = autoctx.args.last('mi', None, int)
# add on combatant damage effects (#224)
if autoctx.combatant:
effect_d = '+'.join(autoctx.combatant.active_effects('d'))
if effect_d:
if d:
d = f"{d}+{effect_d}"
else:
d = effect_d
dice_ast = copy.copy(d20.parse(self.dice))
dice_ast = _upcast_scaled_dice(self, autoctx, dice_ast)
if not self.hidden:
# -mi # (#527)
if mi:
dice_ast = d20.utils.tree_map(_mi_mapper(mi), dice_ast)
if d:
d_ast = d20.parse(d)
dice_ast.roll = d20.ast.BinOp(dice_ast.roll, '+', d_ast.roll)
if maxdmg:
dice_ast = d20.utils.tree_map(_max_mapper, dice_ast)
rolled = roll(dice_ast)
if not self.hidden: