def get_resistances(build: Build, force_display=False): """ Creates the resistance string :param build: build we want to output :param force_display: override threshold :return: string containing all resistances or and empty string if nothing is noteworthy """ output = "**Resistances**: " resistances = ['Fire', 'Cold', 'Lightning', 'Chaos'] emojis = [':fire:', ':snowflake:', ':zap:', ':skull:'] show = False for i, res in enumerate(resistances): res_val = build.get_stat( 'Player', res + 'Resist', OutputThresholds.CHAOS_RES.value if res == 'Chaos' else OutputThresholds.ELE_RES.value) res_over_cap = build.get_stat('Player', res + 'ResistOverCap') if res_val: output += emojis[i] + " {:.0f}".format(res_val) show = True if res_over_cap and res_over_cap > 0: output += "(+{:.0f}) ".format(res_over_cap) output += " " output += "\n" return output if show else ""
def has_offensive_ability(build: Build, consts): if not build.get_active_skill(): return False skill = build.get_active_skill().get_selected() if consts and skill and (skill.name in consts.aura_list or skill.name in consts.curse_list or skill.name in consts.utility_skills): return False return True
def get_charges(build: Build, charge_types=['Endurance', 'Frenzy', 'Power']): output = [] for charge_type in charge_types: val = build.get_stat('Player', charge_type + 'Charges') max_val = build.get_stat('Player', charge_type + 'ChargesMax') charge_is_active = build.config.get('use' + charge_type + "Charges") if charge_is_active and val and max_val: output.append('{}: {:.0f}/{:.0f}'.format(charge_type, val, max_val)) return ', '.join(output) if len(output) > 0 else None
def get_secondary_def(build: Build): """ Parse all secondary defenses such as armor, eva, dodge, block and display them if they are higher than the thresholds. :param build: current build :return: String containing noteworthy secondary defense, Empty string as default """ output = "" stats = [] effective_life = max( filter(None.__ne__, [build.get_stat('Player', 'Life'), build.get_stat('Player', 'EnergyShield'), 0])) armour = build.get_stat('Player', 'Armour', min(OutputThresholds.ARMOUR.value, effective_life)) stats.append("Armour: {:,.0f}".format(armour)) if armour and armour else None evasion = build.get_stat('Player', 'Evasion', min(OutputThresholds.EVASION.value, effective_life)) stats.append("Evasion: {:,.0f}".format(evasion)) if evasion else None dodge = build.get_stat('Player', 'AttackDodgeChance', OutputThresholds.DODGE.value) stats.append("Dodge: {:,.0f}%".format(dodge)) if dodge else None spell_dodge = build.get_stat('Player', 'SpellDodgeChance', OutputThresholds.SPELL_DODGE.value) stats.append("Spell Dodge: {:,.0f}%".format(spell_dodge)) if spell_dodge else None block = build.get_stat('Player', 'BlockChance', OutputThresholds.BLOCK.value) stats.append("Block: {:,.0f}%".format(block)) if block else None spell_block = build.get_stat('Player', 'SpellBlockChance', OutputThresholds.SPELL_BLOCK.value) stats.append("Spell Block: {:,.0f}%".format(spell_block)) if spell_block else None if len(stats) > 0: output += " | ".join([s for s in stats if s]) + "\n" return "**Secondary:** " + output if output != "" else None
def generate_response(author, build: Build, minified=False, pastebin_key=None, consts=None, web_poe_token=None): """ Build an embed to respond to the user. :param consts: poe constants - skill info :param author: name of the person triggering the action :param build: build to parse an embed from :param minified (bool): whether to get a minified version or the full one :return: Filled embed for discord """ is_support = build_checker.is_support(build) embed = create_embed(author, build.level, build.ascendency_name, build.class_name, build.get_active_skill(), is_support) # add new fields general_str = general_output.get_defense_string(build) if general_str: embed.add_field(name="General", value=general_str, inline=minified) key, offense = offense_output.get_offense(build, consts) if offense: embed.add_field(name=key, value=offense, inline=minified) charges_str = charges_output.get_charges(build) if charges_str: embed.add_field(name="Charges", value=charges_str, inline=minified) # if not minified, add detailed infos. if not minified: skill = skill_output.get_main_skill(build) if skill: embed.add_field(name="Main Skill", value=skill, inline=minified) conf_str = config_output.get_config_string(build.config) if conf_str: embed.add_field(name="Config", value=conf_str, inline=minified) # output embed.add_field(name='Info:', value=generate_info_text(build.tree, pastebin_key, web_poe_token)) return embed
def generate_response(author, build: Build, minified=False, pastebin=None, consts=None): """ Build an embed to respond to the user. :param consts: poe constants - skill info :param author: name of the person triggering the action :param build: build to parse an embed from :param minified (bool): whether to get a minified version or the full one :return: Filled embed for discord """ is_support = build_checker.is_support(build) embed = create_embed(author, build.level, build.ascendency_name, build.class_name, build.get_active_skill(), is_support) # add new fields def_str = defense_output.get_defense_string(build) if def_str: embed.add_field(name="Defense", value=def_str, inline=minified) key, offense = offense_output.get_offense(build, consts) if offense: embed.add_field(name=key, value=offense, inline=minified) charges_str = charges_output.get_charges(build) if charges_str: embed.add_field(name="Charges", value=charges_str, inline=minified) # if not minified, add detailed infos. if not minified: skill = skill_output.get_main_skill(build) if skill: embed.add_field(name="Main Skill", value=skill, inline=minified) conf_str = config_output.get_config_string(build.config) if conf_str: embed.add_field(name="Config", value=conf_str, inline=minified) # output info_text = "" if pastebin: info_text += "[Pastebin](https://pastebin.com/{}) | ".format(pastebin) info_text += "[Web Tree]({}) | [**Web Preview**](https://poe.technology/poebuddy/{}) - created in [Path of Building](https://github.com/Openarl/PathOfBuilding). ".format( build.tree, pastebin) embed.add_field(name='Info:', value=info_text) return embed
def parse_build(xml_root): xml_build = xml_root.find('Build') xml_items = xml_root.find('Items') xml_skills = xml_root.find('Skills') xml_tree = xml_root.find('Tree') selected_tree = get_tree_link(xml_tree) # parse items item_slots = parse_item_slots(xml_items) skills = parse_skills(xml_skills) active_skill = get_attrib_if_exists(xml_build, 'mainSocketGroup') build = Build(xml_build.attrib['level'], xml_build.attrib['targetVersion'], get_attrib_if_exists(xml_build, 'bandit'), xml_build.attrib['className'], xml_build.attrib['ascendClassName'], selected_tree, skills, active_skill, item_slots) for player_stat in xml_build: if 'stat' in player_stat.attrib and 'value' in player_stat.attrib: build.append_stat(player_stat.attrib['stat'], player_stat.attrib['value'], player_stat.tag) else: log.info("Encountered unsupported player stat: k={}, v={}".format( player_stat.tag, player_stat.attrib)) # parse config config = xml_root.find('Config') if not config == None: for input in xml_root.find('Config'): if input.tag == "Input": extracted = [val for (key, val) in input.attrib.items()] if len(extracted) < 1: continue build.append_conf(extracted[0], extracted[1]) # keystones tree = poe_tree_codec.codec.decode_url(selected_tree) build.keystones = tree.get_keystones(poe_tree_codec.codec.keystones) return build
def get_defense_string(build: Build): output = "" life_percent_threshold = min( OutputThresholds.LIFE_PERCENT.value, OutputThresholds.LIFE_PERCENT_PER_LEVEL.value * build.level) life_flat = build.get_stat('Player', 'Life') life_string = get_basic_line( "Life", life_flat, build.get_stat('Player', 'Spec:LifeInc', life_percent_threshold), stat_regen=build.get_stat('Player', 'LifeRegen'), stat_unreserved=build.get_stat('Player', 'LifeUnreserved'), stat_leech_rate=build.get_stat( 'Player', 'LifeLeechGainRate', life_flat * OutputThresholds.LEECH.value if life_flat else 0)) if life_string: output += life_string es_percent_threshold = min( OutputThresholds.ES_PERCENT.value, OutputThresholds.ES_PERCENT_PER_LEVEL.value * build.level) es_flat = build.get_stat('Player', 'EnergyShield') es_string = get_basic_line( "Energy Shield", es_flat, build.get_stat('Player', 'Spec:EnergyShieldInc', es_percent_threshold), stat_regen=build.get_stat('Player', 'EnergyShieldRegen'), stat_leech_rate=build.get_stat( 'Player', 'EnergyShieldLeechGainRate', es_flat * OutputThresholds.LEECH.value if es_flat else 0)) if es_string: output += es_string net_regen = build.get_stat('Player', 'NetLifeRegen') if net_regen: output += "**Net Regen**: {:,.0f}/s\n".format(net_regen) mana_flat = build.get_stat('Player', 'Mana') mana_string = get_basic_line( "Mana", mana_flat, build.get_stat('Player', 'Spec:ManaInc'), stat_regen=build.get_stat('Player', 'ManaRegen'), stat_unreserved=build.get_stat('Player', 'ManaUnreserved'), stat_leech_rate=build.get_stat( 'Player', 'ManaLeechGainRate', mana_flat * OutputThresholds.LEECH.value if mana_flat else 0)) if mana_string: output += mana_string # todo: only pass necessary values to the following options: secondary_def = get_secondary_def(build) if secondary_def: output += secondary_def output += get_resistances(build) if build.keystones: output += get_keystones(build.keystones) return output