def heal_active_convert(self, act):
        hp = getattr(act, 'hp', 0)
        rcv_mult = getattr(act, 'rcv_multiplier_as_hp', 0)
        php = getattr(act, 'percentage_max_hp', 0)
        trcv_mult = getattr(act, 'team_rcv_multiplier_as_hp', 0)
        unbind = getattr(act, 'card_bind', 0)
        awoken_unbind = getattr(act, 'awoken_bind', 0)

        skill_text = ('Recover ' + '{:,}'.format(hp) + ' HP' if hp != 0 else
                      ('Recover ' + fmt_mult(rcv_mult) +
                       'x RCV as HP' if rcv_mult != 0 else
                       ('Recover all HP' if php == 1 else
                        ('Recover ' + fmt_mult(php * 100) +
                         '% of max HP' if php > 0 else
                         ('Recover HP equal to ' + fmt_mult(trcv_mult) +
                          'x team\'s total RCV' if trcv_mult > 0 else '')))))

        if unbind or awoken_unbind:
            if skill_text:
                skill_text += '; '
            skill_text += (
                'Remove all binds and awoken skill binds' if
                (unbind >= 9999 and awoken_unbind) else
                ('Reduce binds and awoken skill binds by {:s}'.format(
                    noun_count('turn', awoken_unbind)) if
                 (unbind and awoken_unbind) else
                 ('Remove all binds' if unbind >= 9999 else
                  ('Reduce binds by {:s}'.format(noun_count('turn', unbind)
                                                 ) if unbind else
                   ('Remove all awoken skill binds' if awoken_unbind >= 9999
                    else ('Reduce awoken skill binds by {:s}'.
                          format(noun_count('turn', awoken_unbind))))))))
        return skill_text
 def grudge_strike_convert(self, act):
     skill_text = 'Deal ' + self.ATTRIBUTES[
         act.attribute] + ' damage to ' + self.fmt_mass_atk(
             act.mass_attack) + ' depending on HP level (' + fmt_mult(
                 act.low_multiplier) + 'x at 1 HP and ' + fmt_mult(
                     act.high_multiplier) + 'x at 100% HP)'
     return skill_text
예제 #3
0
 def counter_attack_text(self, ls):
     attribute = self.ATTRIBUTES[ls.attributes[0]]
     multiplier = fmt_mult(ls.multiplier)
     if ls.chance == 1:
         return '{}x {} counterattack'.format(multiplier, attribute)
     return '{}% chance to counterattack with {}x {} damage'.format(
         fmt_mult(ls.chance * 100), multiplier, attribute)
    def fmt_multiplier_text(self, hp_mult, atk_mult, rcv_mult, default=1):
        if hp_mult == atk_mult and atk_mult == rcv_mult:
            if hp_mult == default:
                return ''
            return self.all_stats(fmt_mult(hp_mult))

        mults = [(self.hp(), hp_mult), (self.atk(), atk_mult),
                 (self.rcv(), rcv_mult)]
        mults = list(filter(lambda ml: ml[1] != default, mults))
        mults.sort(key=lambda ml: ml[1], reverse=True)

        chunks = []
        x = 0
        while x < len(mults):
            can_check_double = x + 1 < len(mults)
            if can_check_double and mults[x][1] == mults[x + 1][1]:
                chunks.append(('{} & {}'.format(mults[x][0],
                                                mults[x + 1][0]), mults[x][1]))
                x += 2
            else:
                chunks.append((mults[x][0], mults[x][1]))
                x += 1

        output = ''
        for c in chunks:
            if len(output):
                output += ' and '
            output += '{}x {}'.format(fmt_mult(c[1]), c[0])

        return output
예제 #5
0
    def multi_attribute_match_convert(self, ls):
        attributes = multi_getattr(ls, 'match_attributes', 'attributes')
        if not attributes:
            return ''

        min_atk_mult = multi_getattr(ls, 'min_atk', 'atk')
        min_rcv_mult = multi_getattr(ls, 'min_rcv', 'rcv')
        min_match = multi_getattr(ls, 'min_attr', 'min_combo', 'min_match')
        max_mult = multi_getattr(ls, 'max_atk', 'atk')

        intro = self.fmt_stats_type_attr_bonus(ls,
                                               reduce_join_txt=' and ',
                                               skip_attr_all=True,
                                               atk=min_atk_mult,
                                               rcv=min_rcv_mult)

        if all(x == attributes[0] for x in attributes):
            attr_text = self.ATTRIBUTES[attributes[0]]
            max_mult = fmt_mult(
                max_mult) if len(attributes) != min_match else None
            max_match = len(attributes)
            return self.multi_of_one_attribute_match_text(
                intro, min_match, attr_text, max_mult, max_match)
        min_colors = self.attributes_format(attributes[:min_match], sep='+')
        alt_colors = self.attributes_format(
            attributes[1:], sep='+') if len(attributes) > min_match else None
        all_colors = self.attributes_format(attributes, sep='+')
        max_mult = fmt_mult(max_mult) if max_mult > min_atk_mult else None
        return self.multi_of_dif_attribute_match_text(intro, min_colors,
                                                      alt_colors, max_mult,
                                                      all_colors)
예제 #6
0
    def attribute_match_text(self, ls):
        skill_text = self.fmt_stats_type_attr_bonus(ls,
                                                    reduce_join_txt=' and ',
                                                    skip_attr_all=True,
                                                    atk=ls.min_atk,
                                                    rcv=ls.min_rcv)
        skill_text += self.matching_n_or_more_attr(
            ls.match_attributes,
            ls.min_attr,
            is_range=ls.max_attr > ls.min_attr)

        if ls.atk > ls.min_atk:
            if ls.match_attributes == [0, 1, 2, 3, 4, 5]:
                skill_text += ' up to {}x at 5 colors+heal'.format(
                    fmt_mult(ls.atk))
            elif ls.max_attr < 5 and (len(ls.match_attributes) < 5
                                      or 5 in ls.match_attributes):
                skill_text += ' up to {}x when matching {}'.format(
                    fmt_mult(ls.atk), ls.max_attr)
            else:
                skill_text += ' up to {}x at '.format(fmt_mult(ls.atk))
                if ls.match_attributes == [0, 1, 2, 3, 4]:
                    skill_text += '{} colors'.format(ls.max_attr)
                elif ls.match_attributes == [0, 1, 2, 3, 4, 5]:
                    skill_text += '{} colors ({}+heal)'.format(
                        ls.max_attr, ls.max_attr - 1)
                elif len(ls.match_attributes) > ls.max_attr:
                    skill_text += '{}+ of {} at once'.format(
                        str(ls.max_attr),
                        self.attributes_to_str(ls.match_attributes,
                                               concat='or'))
                else:
                    skill_text += '{} at once'.format(
                        self.attributes_to_str(ls.match_attributes))
        return skill_text
 def move_time_buff_convert(self, act):
     if act.static == 0:
         return self.fmt_duration(act.duration) + \
                fmt_mult(act.percentage) + 'x orb move time'
     elif act.percentage == 0:
         return self.fmt_duration(act.duration) + \
                'increase orb move time by {:s}'.format(noun_count('second', fmt_mult(act.static)))
     raise ValueError()
예제 #8
0
 def orb_remain_convert(self, ls):
     intro = self.fmt_stats_type_attr_bonus(ls, atk=ls.min_atk)
     if ls.base_atk in [0, 1]:
         return intro
     base_atk = fmt_mult(ls.base_atk)
     orb_count = str(ls.orb_count)
     max_atk = fmt_mult(ls.atk) if ls.bonus_atk != 0 else None
     return self.orb_remain_text(intro, base_atk, orb_count, max_atk)
예제 #9
0
 def passive_stats_type_atk_all_hp_convert(self, ls):
     hp_pct = fmt_mult((1 - ls.hp) * 100)
     atk_mult = fmt_mult(ls.atk)
     type_text = ''
     for i in ls.types[:-1]:
         type_text += self.TYPES[i] + ', '
     type_text += self.TYPES[int(ls.types[-1])]
     return self.passive_stats_type_atk_all_hp_text(hp_pct, atk_mult, type_text)
 def drain_attack_convert(self, act):
     skill_text = 'Deal ' + \
                  fmt_mult(act.atk_multiplier) + 'x ATK damage to ' + self.fmt_mass_atk(act.mass_attack)
     if act.recover_multiplier == 1:
         skill_text += ' and recover the same amount as HP'
     else:
         skill_text += ' and recover ' + \
                       fmt_mult(act.recover_multiplier * 100) + '% of the damage as HP'
     return skill_text
예제 #11
0
    def scaling_attribute_match_text(self, ls):
        min_atk = ls.min_atk
        min_attr = ls.min_attr

        if max(ls.steps, default=-1) + 1 != len(ls.steps):
            human_fix_logger.warning(
                f"Unknown behavior for rainbow skill {ls.skill_id}")

        if min_atk < ls.atk:
            if ls.min_atk == 1:
                min_atk = 1 + (ls.atk - ls.min_atk) / (ls.max_attr -
                                                       ls.min_attr)
                min_attr += 1
        else:
            return self.attribute_match_text(ls)

        skill_text = self.fmt_stats_type_attr_bonus(ls,
                                                    reduce_join_txt=' and ',
                                                    skip_attr_all=True,
                                                    atk=1,
                                                    rcv=1)
        skill_text += self.matching_n_or_more_attr(ls.match_attributes,
                                                   ls.min_attr) + '; '

        skill_text += self.fmt_stats_type_attr_bonus(ls,
                                                     reduce_join_txt=' and ',
                                                     skip_attr_all=True,
                                                     atk=min_atk,
                                                     shield=0)
        skill_text += self.matching_n_or_more_attr(
            ls.match_attributes, min_attr, is_range=ls.max_attr > min_attr)

        if ls.atk > min_atk:
            if ls.match_attributes == [0, 1, 2, 3, 4, 5]:
                skill_text += ' up to {}x at 5 colors+heal'.format(
                    fmt_mult(ls.atk))
            elif ls.max_attr < 5 and (len(ls.match_attributes) < 5
                                      or 5 in ls.match_attributes):
                skill_text += ' up to {}x when matching {}'.format(
                    fmt_mult(ls.atk), ls.max_attr)
            else:
                skill_text += ' up to {}x at '.format(fmt_mult(ls.atk))
                if ls.match_attributes == [0, 1, 2, 3, 4]:
                    skill_text += '{} colors'.format(ls.max_attr)
                elif ls.match_attributes == [0, 1, 2, 3, 4, 5]:
                    skill_text += '{} colors ({}+heal)'.format(
                        ls.max_attr, ls.max_attr - 1)
                elif len(ls.match_attributes) > ls.max_attr:
                    skill_text += '{}+ of {} at once'.format(
                        str(ls.max_attr),
                        self.attributes_to_str(ls.match_attributes,
                                               concat='or'))
                else:
                    skill_text += '{} at once'.format(
                        self.attributes_to_str(ls.match_attributes))
        return skill_text
 def random_nuke_convert(self, act):
     if act.minimum_multiplier != act.maximum_multiplier:
         return 'Randomized ' + self.ATTRIBUTES[
             act.attribute] + ' damage to ' + self.fmt_mass_atk(
                 act.mass_attack) + '(' + fmt_mult(
                     act.minimum_multiplier) + '~' + fmt_mult(
                         act.maximum_multiplier) + 'x)'
     else:
         return 'Deal ' + fmt_mult(act.maximum_multiplier) + 'x ' + \
                self.ATTRIBUTES[act.attribute] + ' damage to ' + self.fmt_mass_atk(act.mass_attack)
예제 #13
0
 def orb_remain_text(self, ls):
     skill_text = self.fmt_stats_type_attr_bonus(ls, atk=ls.min_atk)
     if ls.base_atk in [0, 1]:
         return skill_text
     if skill_text:
         skill_text += '; '
     skill_text += '{}x ATK when there are {} or fewer orbs remaining'.format(
         fmt_mult(ls.base_atk), ls.orb_count)
     if ls.bonus_atk != 0:
         skill_text += ' up to {}x ATK when 0 orbs left'.format(
             fmt_mult(ls.max_bonus_atk))
     return skill_text
예제 #14
0
    def multi_attribute_match_text(self, ls):
        if not ls.match_attributes:
            return ''

        skill_text = ''
        min_atk = ls.min_atk
        min_rcv = ls.min_rcv
        shield = ls.shield
        min_match = ls.min_match
        if (min_atk == 1 and ls.atk != 1) or (min_rcv == 1 and ls.rcv != 1):
            skill_text = self.fmt_stats_type_attr_bonus(
                ls, reduce_join_txt=' and ', atk=min_atk, rcv=min_rcv)
            skill_text += f' when matching {min_match} {self.ATTRIBUTES[ls.match_attributes[0]]} combos; '
            min_match += 1
            min_atk += ls.atk_step
            min_rcv += ls.rcv_step
            shield = 0

        skill_text += self.fmt_stats_type_attr_bonus(ls,
                                                     reduce_join_txt=' and ',
                                                     skip_attr_all=True,
                                                     atk=min_atk,
                                                     rcv=min_rcv,
                                                     shield=shield)

        if len(set(ls.match_attributes)) == 1:
            skill_text += ' when matching {}'.format(min_match)
            if not len(ls.match_attributes) != min_match:
                skill_text += '+'
            skill_text += ' {} combos'.format(
                self.ATTRIBUTES[ls.match_attributes[0]])
            if len(ls.match_attributes) != min_match:
                skill_text += ', up to {}x at {} {} combos'.format(
                    fmt_mult(ls.atk), len(ls.match_attributes),
                    self.ATTRIBUTES[ls.match_attributes[0]])
        else:
            skill_text += ' when matching {}'.format(
                self.attributes_to_str(ls.match_attributes[:min_match]))
            if len(ls.match_attributes) > min_match:
                if min_match == 1:
                    skill_text += ' or {}'.format(
                        self.attributes_to_str(ls.match_attributes[1:]))
                else:
                    skill_text += ' (or {})'.format(
                        self.attributes_to_str(ls.match_attributes[1:]))
            if ls.atk > min_atk:
                skill_text += ' up to {}x when matching {}'.format(
                    fmt_mult(ls.atk),
                    self.attributes_to_str(ls.match_attributes))
        return skill_text
예제 #15
0
 def color_cross_convert(self, ls):
     atk = fmt_mult(ls.crosses[0].atk)
     attr_list = [
         self.ATTRIBUTES[ls.crosses[i].attribute]
         for i in range(0, len(ls.crosses))
     ]
     return self.color_cross_text(atk, attr_list)
예제 #16
0
 def bonus_time_text(self, ls):
     skill_text = [self.fmt_stats_type_attr_bonus(ls)]
     if ls.time:
         skill_text.append(
             'Increase orb movement time by {} seconds'.format(
                 fmt_mult(ls.time)))
     return self.concat_list_semicolons(skill_text)
예제 #17
0
 def threshold_stats_convert(self, ls):
     intro = self.fmt_stats_type_attr_bonus(ls,
                                            reduce_join_txt=' and ',
                                            skip_attr_all=True)
     above = ls.threshold_type == ThresholdType.ABOVE
     threshold = fmt_mult(ls.threshold * 100)
     return self.threshold_stats_text(intro, above, threshold)
 def type_attack_boost_convert(self, act):
     skill_text = self.fmt_duration(act.duration) + fmt_mult(
         act.multiplier) + 'x ATK for '
     skill_text += self.concat_list_and([self.TYPES[t]
                                         for t in act.types]) + ' '
     skill_text += pluralize('type', len(act.types))
     return skill_text
예제 #19
0
    def combo_match_text(self, ls):
        if ls.min_combos == 0:
            return ''

        skill_text = ''
        min_atk = ls.min_atk
        min_rcv = ls.min_rcv
        shield = ls.shield
        min_combos = ls.min_combos
        if (min_atk == 1 and ls.atk != 1) or (min_rcv == 1 and ls.rcv != 1):
            skill_text = self.fmt_stats_type_attr_bonus(
                ls, reduce_join_txt=' and ', atk=min_atk, rcv=min_rcv)
            skill_text += ' when {} or more combos'.format(min_combos) + '; '
            min_combos += 1
            min_atk += ls.atk_step
            min_rcv += ls.rcv_step
            shield = 0

        skill_text += self.fmt_stats_type_attr_bonus(ls,
                                                     reduce_join_txt=' and ',
                                                     atk=min_atk,
                                                     rcv=min_rcv,
                                                     shield=shield)
        skill_text += ' when {} or more combos'.format(min_combos)
        if min_combos != ls.max_combos and ls.max_combos:
            skill_text += ' up to {}x at {} combos'.format(
                fmt_mult(ls.atk), ls.max_combos)
        return skill_text
 def attack_attr_x_team_atk_convert(self, act):
     skill_text = 'Deal ' + self.ATTRIBUTES[act.attack_attribute] + \
                  ' damage equal to ' + fmt_mult(act.multiplier) + 'x of team\'s total '
     skill_text += self.concat_list_and(
         [self.ATTRIBUTES[a] for a in act.team_attributes]) + ' ATK to '
     skill_text += self.fmt_mass_atk(act.mass_attack)
     return skill_text
예제 #21
0
 def random_shield_threshold_text(self, ls):
     threshold_text = self.passive_stats_text(ls, skip_attr_all=True)
     threshold_text += self.threshold_hp(ls.threshold, ls.above)
     if ls.chance == 1:
         return threshold_text
     else:
         chance = fmt_mult(ls.chance * 100)
         return '{}% chance to {}'.format(chance, threshold_text).lower()
예제 #22
0
 def random_shield_threshold_stats(self, ls):
     threshold_text = self.threshold_stats_convert(ls)
     is_guaranteed = ls.chance == 1
     if is_guaranteed:
         return threshold_text
     else:
         chance = fmt_mult(ls.chance * 100)
         return self.chance_to_text(chance, threshold_text)
 def fmt_reduct_text(self, shield, reduct_att=None):
     if shield == 0:
         return ''
     shield_text = fmt_mult(shield * 100)
     if reduct_att in [None, [], [0, 1, 2, 3, 4]]:
         return self.reduce_all_pct(shield_text)
     else:
         color_text = self.attributes_to_str(reduct_att)
         return self.reduce_attr_pct(color_text, shield_text)
예제 #24
0
 def dual_threshold_stats_part_convert(self, c):
     intro = self.fmt_stats_type_attr_bonus(c,
                                            reduce_join_txt=' and ',
                                            skip_attr_all=True)
     if c.threshold == 1:
         return self.dual_threshold_stats_part_full_hp_text(intro, c.above)
     threshold = fmt_mult(c.threshold * 100)
     return self.dual_threshold_stats_part_threshold_text(
         intro, c.above, threshold)
 def awakening_attack_boost_convert(self, act):
     skill_text = self.fmt_duration(act.duration) + 'increase ATK by ' + \
                  fmt_mult(act.amount_per * 100) + '% for each '
     awakens = [
         f"{{{{ awoskills.id{a}|default('???') }}}}" for a in act.awakenings
         if a
     ]
     skill_text += self.concat_list_and(awakens)
     skill_text += ' awakening on the team'
     return skill_text
 def awakening_shield_convert(self, act):
     skill_text = self.fmt_duration(act.duration) + 'reduce damage taken by ' + \
                  fmt_mult(act.amount_per * 100) + '% for each '
     awakens = [
         f"{{{{ awoskills.id{a}|default('???') }}}}" for a in act.awakenings
         if a
     ]
     skill_text += self.concat_list_and(awakens)
     skill_text += ' awakening on the team'
     return skill_text
 def elemental_shield_convert(self, act):
     skill_text = self.fmt_duration(act.duration)
     if act.shield == 1:
         skill_text += 'void all ' + self.ATTRIBUTES[int(
             act.attribute)] + ' damage'
     else:
         skill_text += 'reduce ' + \
                       self.ATTRIBUTES[int(act.attribute)] + ' damage by ' + \
                       fmt_mult(act.shield * 100) + '%'
     return skill_text
예제 #28
0
    def dual_threshold_stats_text(self, ls):
        skill_parts = []
        if str(ls.atk_1) != '1' or ls.rcv_1 != 1 or ls.shield_1 != 0:
            skill_text = self.fmt_stats_type_attr_bonus(
                None,
                reduce_join_txt=' and ',
                skip_attr_all=True,
                atk=ls.atk_1,
                rcv=ls.rcv_1,
                types=ls.types,
                attributes=ls.attributes,
                hp=ls.hp,
                shield=ls.shield_1)
            if ls.threshold_1 == 1:
                skill_text += ' when HP {} full'.format(
                    'is' if ls.above_1 else 'is not')
            else:
                skill_text += ' when {} '.format(
                    'above' if ls.above_1 else 'below')
                skill_text += '{}% HP'.format(fmt_mult(ls.threshold_1 * 100))
            skill_parts.append(skill_text)

        if ls.threshold_2 != 0:
            skill_text = self.fmt_stats_type_attr_bonus(
                None,
                reduce_join_txt=' and ',
                skip_attr_all=True,
                atk=ls.atk_2,
                rcv=ls.rcv_2,
                types=ls.types,
                attributes=ls.attributes,
                hp=ls.hp,
                shield=ls.shield_2)
            if ls.threshold_2 == 1:
                skill_text += ' when HP {} full'.format(
                    'is' if ls.above_2 else 'is not')
            else:
                skill_text += ' when {} '.format(
                    'above' if ls.above_2 else 'below')
                skill_text += '{}% HP'.format(fmt_mult(ls.threshold_2 * 100))
            skill_parts.append(skill_text)
        return self.concat_list_semicolons(skill_parts)
 def attribute_attack_boost_convert(self, act):
     skill_text = ''
     if act.rcv_boost:
         skill_text += self.fmt_duration(act.duration) + fmt_mult(
             act.multiplier) + 'x RCV'
     if skill_text:
         skill_text += '; '
     skill_text += self.fmt_duration(
         act.duration) + self.fmt_stats_type_attr_bonus(act,
                                                        atk=act.multiplier)
     return skill_text
    def change_skyfall_convert(self, act):
        skill_text = self.fmt_duration(act.duration, act.max_duration)
        rate = fmt_mult(act.percentage * 100)

        if rate == '100':
            skill_text += 'only {} orbs will appear'.format(
                self.concat_list_and(self.ATTRIBUTES[i] for i in act.orbs))
        else:
            skill_text += '{} orbs are more likely to appear by {}%'.format(
                self.concat_list_and(self.ATTRIBUTES[i] for i in act.orbs),
                rate)
        return skill_text