def run(self, autoctx): super(Save, self).run(autoctx) save = autoctx.args.last('save') or self.stat adv = autoctx.args.adv(False) dc_override = None if self.dc: try: dc_override = autoctx.evaluator.parse(self.dc, autoctx.metavars) dc_override = int(dc_override) except (TypeError, ValueError): raise AutomationException( f"{dc_override} cannot be interpreted as a DC.") dc = autoctx.args.last( 'dc', type_=int ) or dc_override or autoctx.dc_override or autoctx.caster.spellcasting.dc if not dc: raise NoSpellDC() 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 autoctx.target.target: # character save effects (#408) if autoctx.target.character: save_args = autoctx.target.character.get_skill_effects().get( save_skill) if save_args: adv = argparse(save_args).adv() + adv adv = max(-1, min(1, adv)) # bound, cancel out double dis/adv saveroll = autoctx.target.get_save_dice(save_skill) save_roll = roll(saveroll, adv=adv, rollFor='{} Save'.format(save_skill[:3].upper()), inline=True, show_blurbs=False) is_success = save_roll.total >= dc autoctx.queue(save_roll.result + ("; Success!" if is_success else "; Failure!")) else: autoctx.meta_queue('{} Save'.format(save_skill[:3].upper())) is_success = False if is_success: self.on_success(autoctx) else: self.on_fail(autoctx)
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 = autoctx.args.last('dc', type_=int) or dc_override or autoctx.dc_override or autoctx.caster.spellbook.dc if dc is None: raise NoSpellDC() 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, rollFor=save_blurb, inline=True, show_blurbs=False) is_success = save_roll.total >= dc success_str = ("; Success!" if is_success else "; Failure!") if not hide: autoctx.queue(f"{save_roll.result}{success_str}") else: autoctx.add_pm(str(autoctx.ctx.author.id), f"{save_roll.result}{success_str}") 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(Save, self).run(autoctx) save = autoctx.args.last('save') or self.stat dc_override = None if self.dc: try: dc_override = autoctx.evaluator.parse(self.dc, autoctx.metavars) dc_override = int(dc_override) except (TypeError, ValueError): raise AutomationException( f"{dc_override} cannot be interpreted as a DC.") dc = autoctx.args.last( 'dc', type_=int ) or dc_override or autoctx.dc_override or autoctx.caster.spellbook.dc if dc is None: raise NoSpellDC() 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: saveroll = autoctx.target.get_save_dice( save_skill, adv=autoctx.args.adv(boolwise=True)) save_roll = roll(saveroll, rollFor='{} Save'.format(save_skill[:3].upper()), inline=True, show_blurbs=False) is_success = save_roll.total >= dc autoctx.queue(save_roll.result + ("; Success!" if is_success else "; Failure!")) 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 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) adv = autoctx.args.adv(custom={'adv': 'sadv', 'dis': 'sdis'}) dc_override = None if self.dc: try: dc_override = autoctx.parse_annostr(self.dc, is_full_expression=True) 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() save_roll = None autoctx.meta_queue(f"**DC**: {dc}") autoctx.metavars['lastSaveRollTotal'] = 0 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=adv) save_roll = roll(saveroll) is_success = save_roll.total >= dc autoctx.metavars['lastSaveRollTotal'] = save_roll.total # 1362 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: children = self.on_success(autoctx) else: children = self.on_fail(autoctx) return SaveResult(dc=dc, ability=save_skill, save_roll=save_roll, adv=adv, did_save=is_success, children=children)