Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
# 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)
dice_ast.roll = d20.ast.BinOp(dice_ast.roll, '+', c_ast.roll)
# max
if max_arg:
dice_ast = d20.utils.tree_map(_max_mapper, dice_ast)
# evaluate damage
dmgroll = roll(dice_ast)
# magic arg (#853)
always = {'magical'} if (autoctx.is_spell or magic_arg) else None
# dtype transforms/overrides (#876)
transforms = {}
for dtype in dtype_args:
if '>' in dtype:
*froms, to = dtype.split('>')
for frm in froms:
transforms[frm.strip()] = to.strip()
else:
transforms[None] = dtype
# display damage transforms (#1103)
if None in transforms:
autoctx.meta_queue(f"**Damage Type**: {transforms[None]}")
elif transforms:
mi/ma (min/max result)
e (explode dice of value)
ra (reroll and add)
__Supported Selectors__
X (literal X)
lX (lowest X)
hX (highest X)
>X (greater than X)
1999:
out = f"{ctx.author.mention} :game_die:\n" \
f"{str(res)[:100]}...\n" \
f"**Total:** {res.total}"
await try_delete(ctx.message)
await ctx.send(out)
await Stats.increase_stat(ctx, "dice_rolled_life")
: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:`~cogs5e.funcs.scripting.functions.SimpleRollResult`
"""
try:
save = self._combatant.saves.get(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)
save.lower() in s.lower())
except StopIteration:
raise InvalidSaveType()
autoctx.meta_queue(f"**DC**: {dc}")
if not autoctx.target.is_simple:
save_blurb = f'{save_skill[:3].upper()} Save'
if auto_pass:
is_success = True
autoctx.queue(f"**{save_blurb}:** Automatic success!")
elif auto_fail:
is_success = False
autoctx.queue(f"**{save_blurb}:** Automatic failure!")
else:
saveroll = autoctx.target.get_save_dice(save_skill, adv=autoctx.args.adv(boolwise=True))
save_roll = roll(saveroll)
is_success = save_roll.total >= dc
success_str = ("; Success!" if is_success else "; Failure!")
out = f"**{save_blurb}**: {save_roll.result}{success_str}"
if not hide:
autoctx.queue(out)
else:
autoctx.add_pm(str(autoctx.ctx.author.id), out)
autoctx.queue(f"**{save_blurb}**: 1d20...{success_str}")
else:
autoctx.meta_queue('{} Save'.format(save_skill[:3].upper()))
is_success = False
if is_success:
damage = self.on_success(autoctx)
else:
damage = self.on_fail(autoctx)
return await ctx.send("You must pass in a positive, nonzero HP with the -hp tag.")
if args.last('ac'):
ac = args.last('ac', type_=int)
for k in ('resist', 'immune', 'vuln'):
resists[k] = args.get(k)
combat = await Combat.from_ctx(ctx)
if combat.get_combatant(name) is not None:
await ctx.send("Combatant already exists.")
return
if not place:
init_skill = Skill(modifier, adv=adv)
init_roll = roll(init_skill.d20())
init = init_roll.total
init_roll_skeleton = init_roll.result
else:
init_skill = Skill(0, adv=adv)
init = place
init_roll_skeleton = str(init)
me = Combatant.new(name, controller, init, init_skill, hp, ac, private, Resistances.from_dict(resists), ctx,
combat)
# -thp (#1142)
if thp and thp > 0:
me.temp_hp = thp
if group is None:
combat.add_combatant(me)
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)
async def game_deathsave(self, ctx, *args):
"""Commands to manage character death saves.
__Valid Arguments__
See `!help save`."""
character: Character = await Character.from_ctx(ctx)
args = argparse(args)
adv = args.adv()
b = args.join('b', '+')
phrase = args.join('phrase', '\n')
if b:
save_roll = d20.roll(f"{d20_with_adv(adv)}+{b}")
else:
save_roll = d20.roll(d20_with_adv(adv))
embed = discord.Embed()
embed.title = args.last('title', '') \
.replace('[name]', character.name) \
.replace('[sname]', 'Death') \
or f'{character.name} makes a Death Save!'
embed.colour = character.get_color()
death_phrase = ''
if save_roll.crit == d20.CritType.CRIT:
character.hp = 1
elif save_roll.crit == d20.CritType.FAIL:
character.death_saves.fail(2)
elif save_roll.total >= 10:
character.death_saves.succeed()
else:
def reroll_dynamic(self):
"""
Rerolls all combatant initiatives. Returns a string representing the new init order.
"""
rolls = {}
for c in self._combatants:
init_roll = roll(c.init_skill.d20())
c.init = init_roll.total
rolls[c.name] = init_roll
self.sort_combatants()
# reset current turn
self._turn = 0
self._current_index = None
order = []
for combatant_name, init_roll in sorted(rolls.items(), key=lambda r: r[1].total, reverse=True):
order.append(f"{init_roll.result}: {combatant_name}")
order = "\n".join(order)
return order