async def game_spellslot(self, ctx, level: int = None, value: str = None, *args): """ Views or sets your remaining spell slots. __Valid Arguments__ nopact - Modifies normal spell slots first instead of a Pact Magic slots, if applicable. """ if level is not None: try: assert 0 < level < 10 except AssertionError: return await ctx.send("Invalid spell level.") character: Character = await Character.from_ctx(ctx) embed = EmbedWithCharacter(character) if level is None and value is None: # show remaining embed.description = f"__**Remaining Spell Slots**__\n{character.spellbook.slots_str()}" elif value is None: embed.description = f"__**Remaining Level {level} Spell Slots**__\n" \ f"{character.spellbook.slots_str(level)}" else: old_slots = character.spellbook.get_slots(level) value = maybe_mod(value, old_slots) character.spellbook.set_slots(level, value, pact='nopact' not in args) await character.commit(ctx) embed.description = f"__**Remaining Level {level} Spell Slots**__\n" \ f"{character.spellbook.slots_str(level)} ({(value - old_slots):+})" # footer - pact vs non pact if character.spellbook.max_pact_slots is not None: embed.set_footer(text=f"{constants.FILLED_BUBBLE} = Available / {constants.EMPTY_BUBBLE} = Used\n" f"{constants.FILLED_BUBBLE_ALT} / {constants.EMPTY_BUBBLE_ALT} = Pact Slot") else: embed.set_footer(text=f"{constants.FILLED_BUBBLE} = Available / {constants.EMPTY_BUBBLE} = Used") await ctx.send(embed=embed)
def run(self, autoctx): super(Save, self).run(autoctx) save = autoctx.args.last('save') or self.stat auto_pass = autoctx.args.last('pass', type_=bool, ephem=True) auto_fail = autoctx.args.last('fail', type_=bool, ephem=True) hide = autoctx.args.last('h', type_=bool) dc_override = None if self.dc: try: dc_override = autoctx.parse_annostr(self.dc) dc_override = int(dc_override) except (TypeError, ValueError): raise AutomationException( f"{dc_override} cannot be interpreted as a DC.") # dc hierarchy: arg > self.dc > spell cast override > spellbook dc dc = dc_override or autoctx.dc_override or autoctx.caster.spellbook.dc if 'dc' in autoctx.args: dc = maybe_mod(autoctx.args.last('dc'), dc) if dc is None: raise NoSpellDC( "No spell save DC found. Use the `-dc` argument to specify one!" ) try: save_skill = next(s for s in ('strengthSave', 'dexteritySave', 'constitutionSave', 'intelligenceSave', 'wisdomSave', 'charismaSave') if 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 {"total": damage}
def run(self, autoctx): super().run(autoctx) if autoctx.target is None: raise TargetException("Tried to make a save without a target! Make sure all Save effects are inside " "of a Target effect.") # ==== args ==== save = autoctx.args.last('save') or self.stat sb = autoctx.args.get('sb', ephem=True) auto_pass = autoctx.args.last('pass', type_=bool, ephem=True) auto_fail = autoctx.args.last('fail', type_=bool, ephem=True) hide = autoctx.args.last('h', type_=bool) # ==== dc ==== dc_override = None if self.dc: try: dc_override = autoctx.parse_intexpression(self.dc) except Exception: raise AutomationException(f"{self.dc!r} cannot be interpreted as a DC.") # dc hierarchy: arg > self.dc > spell cast override > spellbook dc dc = dc_override or autoctx.dc_override or autoctx.caster.spellbook.dc if 'dc' in autoctx.args: dc = maybe_mod(autoctx.args.last('dc'), dc) if dc is None: raise NoSpellDC("No spell save DC found. Use the `-dc` argument to specify one!") try: save_skill = next(s for s in ('strengthSave', 'dexteritySave', 'constitutionSave', 'intelligenceSave', 'wisdomSave', 'charismaSave') if save.lower() in s.lower()) stat = save_skill[:3] except StopIteration: raise InvalidSaveType() # ==== ieffects ==== if autoctx.target.combatant: # Combine args/ieffect advantages - adv/dis (#1552) sadv_effects = autoctx.target.combatant.active_effects('sadv') sdis_effects = autoctx.target.combatant.active_effects('sdis') sadv = 'all' in sadv_effects or stat in sadv_effects sdis = 'all' in sdis_effects or stat in sdis_effects adv = reconcile_adv( adv=autoctx.args.last('sadv', type_=bool, ephem=True) or sadv, dis=autoctx.args.last('sdis', type_=bool, ephem=True) or sdis ) else: adv = autoctx.args.adv(custom={'adv': 'sadv', 'dis': 'sdis'}) # ==== execution ==== save_roll = None autoctx.metavars['lastSaveRollTotal'] = 0 autoctx.metavars['lastSaveNaturalRoll'] = 0 # 1495 autoctx.metavars['lastSaveDC'] = dc autoctx.metavars['lastSaveAbility'] = verbose_stat(stat) autoctx.meta_queue(f"**DC**: {dc}") if not autoctx.target.is_simple: save_blurb = f'{stat.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: save_dice = autoctx.target.get_save_dice(save_skill, adv=adv, sb=sb) save_roll = d20.roll(save_dice) is_success = save_roll.total >= dc # get natural roll d20_value = d20.utils.leftmost(save_roll.expr).total autoctx.metavars['lastSaveRollTotal'] = save_roll.total # 1362 autoctx.metavars['lastSaveNaturalRoll'] = d20_value # 1495 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(f'{stat.upper()} Save') is_success = False # Disable critical damage state for children (#1556) original = autoctx.in_save autoctx.in_save = True if is_success: children = self.on_success(autoctx) else: children = self.on_fail(autoctx) autoctx.in_save = original # Restore proper crit state (#1556) return SaveResult(dc=dc, ability=save_skill, save_roll=save_roll, adv=adv, did_save=is_success, children=children)
def ac(self): _ac = self._ac or self.character.ac for e in self.active_effects('ac'): _ac = maybe_mod(e, base=_ac) return _ac