async def monster_atk(self, ctx, monster_name, atk_name='list', *, args=''): """Rolls a monster's attack. Attack name can be "list" for a list of all of the monster's attacks. Valid Arguments: adv/dis -ac [target ac] -b [to hit bonus] -d [damage bonus] -d# [applies damage to the first # hits] -rr [times to reroll] -t [target] -phrase [flavor text] crit (automatically crit)""" try: await self.bot.delete_message(ctx.message) except: pass monster = await select_monster_full(ctx, monster_name) self.bot.rdb.incr('monsters_looked_up_life') attacks = monster.attacks monster_name = monster.get_title_name() if atk_name == 'list': attacks_string = '\n'.join( "**{0}:** +{1} To Hit, {2} damage.".format( a['name'], a['attackBonus'], a['damage'] or 'no') for a in attacks) return await self.bot.say("{}'s attacks:\n{}".format( monster_name, attacks_string)) attack = fuzzy_search(attacks, 'name', atk_name) if attack is None: return await self.bot.say("No attack with that name found.", delete_after=15) args = shlex.split(args) args = argparse(args) args['name'] = [monster_name] args['image'] = args.get('image') or [monster.get_image_url()] attack['details'] = attack.get('desc') or attack.get('details') result = sheet_attack(attack, args) embed = result['embed'] embed.colour = random.randint(0, 0xffffff) embeds.add_fields_from_args(embed, args.get('f')) if monster.source == 'homebrew': embed.set_footer(text="Homebrew content.", icon_url="https://avrae.io/static/homebrew.png") await self.bot.say(embed=embed)
async def monster_atk(self, ctx, monster_name, atk_name='list', *, args=''): """Rolls a monster's attack. Attack name can be "list" for a list of all of the monster's attacks. __Valid Arguments__ adv/dis -ac [target ac] -b [to hit bonus] -d [damage bonus] -d# [applies damage to the first # hits] -rr [times to reroll] -t [target] -phrase [flavor text] crit (automatically crit) -h (hides monster name, image, and attack details)""" try: await ctx.message.delete() except: pass monster = await select_monster_full(ctx, monster_name) self.bot.rdb.incr('monsters_looked_up_life') attacks = monster.attacks monster_name = monster.get_title_name() if atk_name == 'list': attacks_string = '\n'.join("**{0}:** +{1} To Hit, {2} damage.".format(a['name'], a['attackBonus'], a['damage'] or 'no') for a in attacks) return await ctx.send("{}'s attacks:\n{}".format(monster_name, attacks_string)) attack = await search_and_select(ctx, attacks, atk_name, lambda a: a['name']) args = await scripting.parse_snippets(args, ctx) args = argparse(args) if not args.last('h', type_=bool): args['name'] = monster_name args['image'] = args.get('image') or monster.get_image_url() else: args['name'] = "An unknown creature" attack['details'] = attack.get('desc') or attack.get('details') result = sheet_attack(attack, args) embed = result['embed'] embed.colour = random.randint(0, 0xffffff) embeds.add_fields_from_args(embed, args.get('f')) if monster.source == 'homebrew': embed.set_footer(text="Homebrew content.", icon_url="https://avrae.io/assets/img/homebrew.png") if args.last('h', type_=bool): try: await ctx.author.send(embed=result['full_embed']) except: pass await ctx.send(embed=embed)
async def _attack(self, ctx, combatant_name, target_name, atk_name, args): args = await scripting.parse_snippets(args, ctx) combat = await Combat.from_ctx(ctx) try: target = await combat.select_combatant(target_name, "Select the target.") if target is None: return await ctx.send("Target not found.") except SelectionException: return await ctx.send("Target not found.") if combatant_name is None: combatant = combat.current_combatant if combatant is None: return await ctx.send(f"You must start combat with `{ctx.prefix}init next` first.") else: try: combatant = await combat.select_combatant(combatant_name, "Select the attacker.") if combatant is None: return await ctx.send("Combatant not found.") except SelectionException: return await ctx.send("Combatant not found.") attacks = combatant.attacks if '-custom' in args: attack = {'attackBonus': None, 'damage': None, 'name': atk_name} else: try: attack = await get_selection(ctx, [(a['name'], a) for a in attacks if atk_name.lower() in a['name'].lower()], message="Select your attack.") except SelectionException: return await ctx.send("Attack not found.") is_player = isinstance(combatant, PlayerCombatant) if is_player and combatant.character_owner == str(ctx.author.id): args = await combatant.character.parse_cvars(args, ctx) args = argparse(shlex.split(args)) # set up all the arguments args['name'] = combatant.name if target.ac is not None: args['ac'] = target.ac args['t'] = target.name args['resist'] = args.get('resist') or target.resists['resist'] args['immune'] = args.get('immune') or target.resists['immune'] args['vuln'] = args.get('vuln') or target.resists['vuln'] args['neutral'] = args.get('neutral') or target.resists['neutral'] if is_player: args['c'] = combatant.character.get_setting('critdmg') or args.get('c') args['reroll'] = combatant.character.get_setting('reroll') or 0 args['crittype'] = combatant.character.get_setting('crittype') or 'default' args['critdice'] = (combatant.character.get_setting('critdice') or 0) + int( combatant.character.get_setting('hocrit', False)) args['criton'] = combatant.character.get_setting('criton') or args.get('criton') result = sheet_attack(attack, args) embed = result['embed'] if args.last('h', type_=bool): try: controller = ctx.guild.get_member(int(combatant.controller)) await controller.send(embed=result['full_embed']) except: pass if is_player: embed.colour = combatant.character.get_color() else: embed.colour = random.randint(0, 0xffffff) if target.ac is not None and target.hp is not None: target.mod_hp(-result['total_damage'], overheal=False) if target.ac is not None: if target.hp is not None: embed.set_footer(text="{}: {}".format(target.name, target.get_hp_str())) if target.isPrivate: try: controller = ctx.guild.get_member(int(target.controller)) await controller.send( f"{combatant.name} attacked with a {attack['name']}!" f"\n{target.name}'s HP: {target.get_hp_str(True)}") except: pass else: embed.set_footer(text="Dealt {} damage to {}!".format(result['total_damage'], target.name)) if target.is_concentrating() and result['total_damage'] > 0: dcs = [] for atk in result['raw_attacks']: if atk['crit'] == 2: continue dcs.append(int(max(atk['damage'] / 2, 10))) if len(dcs) > 1: dcs = ', '.join(map(str, dcs)) embed.add_field(name="Concentration", value=f"Check your concentration (DCs {dcs})!") else: embed.add_field(name="Concentration", value=f"Check your concentration (DC {dcs[0]})!") else: embed.set_footer(text="Target AC not set.") embeds.add_fields_from_args(embed, args.get('f', [])) await ctx.send(embed=embed) await combat.final()
async def attack(self, ctx, atk_name=None, *, args: str = ''): """Rolls an attack for the current active character. __Valid Arguments__ adv/dis adv#/dis# (applies adv to the first # attacks) ea (Elven Accuracy double advantage) -ac [target ac] -t [target] -b [to hit bonus] -criton [a number to crit on if rolled on or above] -d [damage bonus] -d# [applies damage to the first # hits] -c [damage bonus on crit] -rr [times to reroll] -mi [minimum weapon dice roll] -resist [damage resistance] -immune [damage immunity] -vuln [damage vulnerability] -neutral [damage non-resistance] hit (automatically hits) miss (automatically misses) crit (automatically crit) max (deals max damage) -phrase [flavor text] -title [title] *note: [charname], [aname], and [target] will be replaced automatically* -f "Field Title|Field Text" (see !embed) -h (hides attack details) [user snippet]""" if atk_name is None: return await ctx.invoke(self.attack_list) char: Character = await Character.from_ctx(ctx) attack = await search_and_select(ctx, char.attacks, atk_name, lambda a: a.name) args = await self.new_arg_stuff(args, ctx, char) args['name'] = char.name args['criton'] = args.last('criton') or char.get_setting('criton', 20) args['reroll'] = char.get_setting('reroll', 0) args['critdice'] = char.get_setting('critdice', 0) args['crittype'] = char.get_setting('crittype', 'default') result = sheet_attack(attack.to_old(), args, EmbedWithCharacter(char, name=False)) embed = result['embed'] if args.last('h', type_=bool): try: await ctx.author.send(embed=result['full_embed']) except: pass _fields = args.get('f') embeds.add_fields_from_args(embed, _fields) await ctx.send(embed=embed) try: await ctx.message.delete() except: pass
async def attack(self, ctx, atk_name=None, *, args: str = ''): """Rolls an attack for the current active character. __Valid Arguments__ adv/dis adv#/dis# (applies adv to the first # attacks) ea (Elven Accuracy double advantage) -ac [target ac] -t [target] -b [to hit bonus] -criton [a number to crit on if rolled on or above] -d [damage bonus] -d# [applies damage to the first # hits] -c [damage bonus on crit] -rr [times to reroll] -mi [minimum weapon dice roll] -rd [extra dice rolled for damage] -rh [extra dice rolled for to hit] -resist [damage resistance] -immune [damage immunity] -vuln [damage vulnerability] -neutral [damage non-resistance] hit (automatically hits) miss (automatically misses) crit (automatically crit) max (deals max damage) -phrase [flavor text] -title [title] *note: [charname], [aname], and [target] will be replaced automatically* -f "Field Title|Field Text" (see !embed) -h (hides attack details) [user snippet]""" if atk_name is None: return await ctx.invoke(self.attack_list) char = await Character.from_ctx(ctx) attacks = char.get_attacks() try: # fuzzy search for atk_name attack = next(a for a in attacks if atk_name.lower() == a.get('name').lower()) except StopIteration: try: attack = next(a for a in attacks if atk_name.lower() in a.get('name').lower()) except StopIteration: return await ctx.send('No attack with that name found.') args = await self.new_arg_stuff(args, ctx, char) args['name'] = char.get_name() args['criton'] = args.last('criton') or char.get_setting('criton', 20) args['reroll'] = char.get_setting('reroll', 0) args['critdice'] = int(char.get_setting('hocrit', False)) + char.get_setting('critdice', 0) args['crittype'] = char.get_setting('crittype', 'default') if attack.get('details') is not None: try: attack['details'] = await char.parse_cvars(attack['details'], ctx) except AvraeException: pass # failed to eval, probably DDB nonsense if args.last('rd') is not None: attack["damage"] = (attack.get("damage") + "+" + args.last('rd')) result = sheet_attack(attack, args, EmbedWithCharacter(char, name=False)) embed = result['embed'] if args.last('h', type_=bool): try: await ctx.author.send(embed=result['full_embed']) except: pass _fields = args.get('f') embeds.add_fields_from_args(embed, _fields) await ctx.send(embed=embed) try: await ctx.message.delete() except: pass