def max_hp_change(self, turns, max_hp, percent): if percent: return 'Change player HP to {:,}% for {:s}'.format( max_hp, noun_count('turn', turns)) else: return 'Change player HP to {:,} for {:s}'.format( max_hp, noun_count('turn', turns))
def spinners(self, turns, speed, random_num=None): if random_num is None: return 'Specific orbs change every {:.1f}s for {:s}' \ .format(speed / 100, noun_count('turn', turns)) else: return 'Random {:d} orbs change every {:.1f}s for {:s}' \ .format(random_num, speed / 100, noun_count('turn', turns))
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 debuff_atk_target(self, turns, targets, count, mult): if targets == 3: target_text = "both leaders" elif targets == 4: target_text = noun_count('random sub', count) elif targets == 7: target_text = noun_count('random card', count) else: target_text = '???' return f"{target_text} {emoji_dict['atk_debuff']} {100-mult}% for {turns}"
def debuff_atk_target(self, turns, targets, count, mult): if targets == 3: target_text = "both leaders" elif targets == 4: target_text = noun_count('random sub', count) elif targets == 7: target_text = noun_count('random card', count) else: human_fix_logger.warning( f"Unknown DebuffATKTarget target {targets}") target_text = '???' return f"For {noun_count('turn', turns)}, {mult}% ATK for {target_text}"
def absorb(self, abs_type: Absorb, condition, min_turns, max_turns=None): if abs_type == Absorb.attr: source = self.attributes_to_str(condition) return 'Absorb {:s} damage for {:s}' \ .format(source, noun_count("turn", min_turns, max_turns)) elif abs_type == Absorb.combo: source = 'combos <= {:d}'.format(condition) elif abs_type == Absorb.damage: source = 'damage >= {:,d}'.format(condition) else: raise ValueError("unknown absorb type: {}".format(abs_type)) return 'Absorb damage when {:s} for {:s}' \ .format(source, noun_count("turn", min_turns, max_turns))
def bind(self, min_turns, max_turns, target_count=None, target_types=TargetType.card, source: Source = None): if isinstance(target_types, TargetType): target_types = [target_types] elif source is not None: target_types = SOURCE_FUNCS[source]([target_types]) + ' cards' targets = targets_to_str(target_types) output = 'Bind {:s} '.format(noun_count(targets, target_count)) output += 'for ' + noun_count('turn', minmax(min_turns, max_turns)) return output
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()
def damage_reduction(self, source_type: Source, source=None, percent=None, turns=None): source = (SOURCE_FUNCS[source_type])(source) if source_type != Source.all_sources: source += ' ' + source_type.name if percent is None: return 'Immune to damage from {:s} for {:s}' \ .format(source, noun_count('turn', turns)) else: if turns: return 'Reduce damage from {:s} by {:d}% for {:s}' \ .format(source, percent, noun_count('turn', turns)) else: return 'Reduce damage from {:s} by {:d}%' \ .format(source, percent)
def attack(self, mult, min_hit=1, max_hit=1): if mult is None: return None output = 'Deal {:s}% damage'. \ format(minmax(int(min_hit) * int(mult), int(max_hit) * int(mult))) if min_hit and max_hit != 1: output += ' ({:s}, {:,}% each)'. \ format(noun_count("hit", minmax(min_hit, max_hit)), mult) return output
def debuff(self, d_type, amount, unit, turns): amount = amount or 0 if amount % 1 != 0: human_fix_logger.error( 'Amount {} will be truncated. Change debuff'.format(amount)) unit = UNITS[unit] turns = turns or 0 type_text = capitalize_first(STATUSES[d_type] or '') turn_text = noun_count('turn', turns) return '{:s} {:.0f}{:s} for {:s}'.format(type_text, amount, unit, turn_text)
def skyfall(self, attributes, chance, min_turns, max_turns=None, locked=False): lock = 'Locked ' if locked else '' orbs = self.attributes_to_str(attributes) # TODO: tieout if lock and orbs == 'Random': orbs = orbs.lower() return '{:s}{:s} skyfall +{:d}% for {:s}' \ .format(lock, orbs, chance, noun_count('turn', min_turns, max_turns))
def auto_heal_convert(self, act): skill_text = '' unbind = act.card_bind awoken_unbind = act.awoken_bind if act.duration: skill_text += self.fmt_duration(act.duration) + 'recover ' + \ fmt_mult(act.percentage_max_hp * 100) + '% of max HP' 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 bind(self, min_turns, max_turns, target_count=None, target_types=TargetType.card, source: Source = None): if isinstance(target_types, TargetType): target_types = [target_types] elif source is not None: target_types = SOURCE_FUNCS[source]([target_types]) + ' cards' targets = targets_to_str(target_types) output = '({} {} '.format(emoji_dict['bind'], noun_count(targets, target_count)) output += 'for ' + minmax(min_turns, max_turns) + ')' return output
def cloud(self, turns, width, height, x, y): if width == 6 and height == 1: shape = 'row' elif width == 1 and height == 5: shape = 'column' else: shape = '{:d}×{:d}'.format(width, height) shape += ' square' if width == height else ' rectangle' pos = [] if x is not None and shape != 'Row of': pos.append('{:s} row'.format(ordinal(x))) if y is not None and shape != 'Column of': pos.append('{:s} column'.format(ordinal(y))) if len(pos) == 0: pos.append('a random location') return 'A {:s} of clouds appears for {:s} at {:s}' \ .format(shape, noun_count('turn', turns), ', '.join(pos))
def ctw_convert(self, act): return 'Freely move orbs for {:s}'.format( noun_count('second', act.duration))
def delay_convert(self, act): return 'Delay enemies\' next attack by {:s}'.format( noun_count('turn', act.turns))
def ally_active_disable(self, turns: int): return 'Disable team active skills for {:s}'.format( noun_count('turn', turns))
def ally_active_delay(self, turns: int): return 'Self-delay active skills by {:s}'.format( noun_count('turn', turns))
def match_disable_convert(self, act): return 'Reduce unable to match orbs effect by {:s}'.format( noun_count('turn', act.duration))
def spawn_spinner(self, turns: int, speed: float, count: int): return 'Create {:s} that {:s} every {:.1f}s for {:s}' \ .format(noun_count('spinner', count), pluralize("change", count, verb=True), speed, noun_count('turn', turns))
def no_skyfall(self, turns): return 'No skyfall for {:s}'.format(noun_count('turn', turns))
def fmt_duration(self, duration, max_duration=None): if max_duration and duration != max_duration: return 'For {}~{:s}, '.format(duration, noun_count('turn', max_duration)) else: return 'For {:s}, '.format(noun_count('turn', duration))
def haste_convert(self, act): return 'Charge all allies\' skills by {:s}'.format( noun_count('turn', act.turns, act.max_turns))
def fmt_repeated(self, text, amount): return '{} {:s}'.format(text, noun_count('time', amount))
def combo_skyfall(self, turns, chance): return 'For {:s}, {}% chance for combo orb skyfall.'.format( noun_count('turn', turns), chance)
def force_board_size(self, turns: int, size_param: int): size = {1: '7x6', 2: '5x4', 3: '6x5'}.get(size_param, 'unknown') return 'Change board size to {} for {:s}'.format( size, noun_count('turn', turns))
def debuff_atk(self, turns, amount): return 'ATK -{}% for {:s}'.format(amount, noun_count('turn', turns))
def disable_assists(self, turns): return '{} for {}'.format(emoji_dict['disable_assists'], noun_count('turn', turns))
def disable_assists(self, turns): return 'Disable active skills for {:s}'.format( noun_count('turn', turns))