def test_s1_masked_no_affliction(transformer_skill: SkillTransformer): # Yukata Curran S1 - Masked # https://dragalialost.wiki/w/Yukata_Curran skill_data_base = transformer_skill.transform_attacking(103504043) level_1_base_expected = 1.44 level_2_base_expected = 1.62 level_3_base_expected = 1.82 hits_expected = 5 # Base data - (1 hit for each bullets) skill_data = skill_data_base.with_conditions() assert skill_data.hit_count == [hits_expected, hits_expected, hits_expected] assert skill_data.hit_count_at_max == hits_expected assert skill_data.total_mod == pytest.approx([ level_1_base_expected * hits_expected, level_2_base_expected * hits_expected, level_3_base_expected * hits_expected ]) assert skill_data.total_mod_at_max == pytest.approx(level_3_base_expected * hits_expected) assert skill_data.mods == approx_matrix([ [level_1_base_expected] * hits_expected, [level_2_base_expected] * hits_expected, [level_3_base_expected] * hits_expected ]) assert skill_data.mods_at_max == pytest.approx([level_3_base_expected] * hits_expected) assert skill_data.max_level == 3 # Different bullet hit count dmg_up_rate = { Condition.BULLET_HIT_1: sum(0.55 ** deterioration_count for deterioration_count in range(1)), Condition.BULLET_HIT_2: sum(0.55 ** deterioration_count for deterioration_count in range(2)), Condition.BULLET_HIT_3: sum(0.55 ** deterioration_count for deterioration_count in range(3)), Condition.BULLET_HIT_4: sum(0.55 ** deterioration_count for deterioration_count in range(4)), Condition.BULLET_HIT_5: sum(0.55 ** deterioration_count for deterioration_count in range(5)), Condition.BULLET_HIT_6: sum(0.55 ** deterioration_count for deterioration_count in range(6)), } for condition, up_rate in dmg_up_rate.items(): skill_data = skill_data_base.with_conditions(ConditionComposite(condition)) bullet_hit_count = ConditionCategories.skill_bullet_hit.convert(condition) hits_conditioned = hits_expected * bullet_hit_count assert skill_data.hit_count == [hits_conditioned, hits_conditioned, hits_conditioned] assert skill_data.hit_count_at_max == hits_conditioned assert skill_data.total_mod == pytest.approx([ level_1_base_expected * hits_expected * up_rate, level_2_base_expected * hits_expected * up_rate, level_3_base_expected * hits_expected * up_rate ]) assert skill_data.total_mod_at_max == pytest.approx(level_3_base_expected * hits_expected * up_rate) assert skill_data.mods == approx_matrix([ [ level_1_base_expected * 0.55 ** deterioration for deterioration in range(bullet_hit_count) for _ in range(hits_expected) ], [ level_2_base_expected * 0.55 ** deterioration for deterioration in range(bullet_hit_count) for _ in range(hits_expected) ], [ level_3_base_expected * 0.55 ** deterioration for deterioration in range(bullet_hit_count) for _ in range(hits_expected) ], ]) assert skill_data.mods_at_max == pytest.approx([ level_3_base_expected * 0.55 ** deterioration for deterioration in range(bullet_hit_count) for _ in range(hits_expected) ]) assert skill_data.max_level == 3
def test_multi_effect_to_nearby_2(transformer_skill: SkillTransformer): # Summer Cleo S2 # https://dragalialost.wiki/w/Summer_Cleo skill_data_base = transformer_skill.transform_supportive(106504012) expected_base_buffs_lv_1 = { BuffEffectInfo("BOW_108_04_ATK_LV01", HitTargetSimple.SELF_SURROUNDING, BuffParameter.ATK_BUFF, 0.03, 10, 0), BuffEffectInfo("BOW_108_04_CRT_LV01", HitTargetSimple.SELF_SURROUNDING, BuffParameter.CRT_RATE_BUFF, 0.02, 10, 0), BuffEffectInfo("BOW_108_04_SKILL_LV01", HitTargetSimple.SELF_SURROUNDING, BuffParameter.SKILL_DAMAGE_BUFF, 0.1, 10, 0), BuffEffectInfo("BOW_108_04_SPB_LV01", HitTargetSimple.SELF_SURROUNDING, BuffParameter.SP_RATE, 0.1, 10, 0), } expected_base_buffs_lv_2 = { BuffEffectInfo("BOW_108_04_ATK_LV02", HitTargetSimple.SELF_SURROUNDING, BuffParameter.ATK_BUFF, 0.05, 10, 0), BuffEffectInfo("BOW_108_04_CRT_LV02", HitTargetSimple.SELF_SURROUNDING, BuffParameter.CRT_RATE_BUFF, 0.03, 10, 0), BuffEffectInfo("BOW_108_04_SKILL_LV02", HitTargetSimple.SELF_SURROUNDING, BuffParameter.SKILL_DAMAGE_BUFF, 0.1, 10, 0), BuffEffectInfo("BOW_108_04_SPB_LV02", HitTargetSimple.SELF_SURROUNDING, BuffParameter.SP_RATE, 0.1, 10, 0), } expected_base_buffs_lv_3 = { BuffEffectInfo("BOW_108_04_ATK_LV03", HitTargetSimple.SELF_SURROUNDING, BuffParameter.ATK_BUFF, 0.05, 10, 0), BuffEffectInfo("BOW_108_04_CRT_LV03", HitTargetSimple.SELF_SURROUNDING, BuffParameter.CRT_RATE_BUFF, 0.03, 10, 0), BuffEffectInfo("BOW_108_04_SKILL_LV03", HitTargetSimple.SELF_SURROUNDING, BuffParameter.SKILL_DAMAGE_BUFF, 0.1, 10, 0), BuffEffectInfo("BOW_108_04_SPB_LV03", HitTargetSimple.SELF_SURROUNDING, BuffParameter.SP_RATE, 0.1, 10, 0), } on_0_plus_buffs = { BuffEffectInfo("BOW_108_04_DEF_LV03", HitTargetSimple.SELF, BuffParameter.DEF_BUFF, 0.1, 10, 0), } on_1_plus_buffs = on_0_plus_buffs | { BuffEffectInfo("BOW_108_04_CRTDMG_LV03", HitTargetSimple.SELF, BuffParameter.CRT_DAMAGE_BUFF, 0.1, 10, 0), } on_2_plus_buffs = on_1_plus_buffs | { BuffEffectInfo("BOW_108_04_SP_LV03", HitTargetSimple.SELF, BuffParameter.SP_CHARGE_PCT_S1, 1, 0, 0), } expected_base_buffs = [ expected_base_buffs_lv_1, expected_base_buffs_lv_2, expected_base_buffs_lv_3 ] # arr[i][j] is the additional buffs granted, i = skill level / j = count of teammates covered expected_additional_buffs = [[set(), set(), set(), set()], [set(), set(), set(), set()], [ on_0_plus_buffs, on_1_plus_buffs, on_2_plus_buffs, on_2_plus_buffs ]] assert skill_data_base.max_level == 3 for cond_enum, teammate_count in ConditionCategories.skill_teammates_covered.conversion_dict.items( ): skill_data = skill_data_base.with_conditions( ConditionComposite(cond_enum)) check_buff_unit_match( skill_data.max_lv_buffs, expected_base_buffs_lv_3 | expected_additional_buffs[-1][teammate_count]) for skill_lv in range(skill_data_base.max_level): actual_buffs = skill_data.buffs[skill_lv] expected_buffs = expected_base_buffs[ skill_lv] | expected_additional_buffs[skill_lv][teammate_count] check_buff_unit_match(actual_buffs, expected_buffs)
if not hit_attr and do_nothing_on_not_found: return if not hit_attr.is_effective_to_enemy(True): return # Dummy hit attribute might be inserted for...animation? (Nino `SWD_NIN_BLT_01_H00`) if action_component.skill_pre_condition in PRE_CONDITIONS_TO_OMIT: return # Specific pre-conditions to omit # Get pre-conditions to fill combo info # --------------- # This is different from `pre_conditions` because `pre_conditions` lists all possible pre-conditions, # while this only contains the pre-condition coming from `action_component` if it exists. target_conditions: set[ConditionComposite] = ({ ConditionComposite(action_component.skill_pre_condition) } if action_component.skill_pre_condition else pre_conditions) # Add punisher conditions if any punisher_conditions = { ConditionCategories.target_status.convert_reversed(affliction) for affliction in hit_attr.punisher_states } if punisher_conditions: target_conditions.update({ ConditionComposite(composite.conditions_sorted + (punisher_condition, )) for punisher_condition in punisher_conditions for composite in pre_conditions })
def test_iter_entries_s2(transformer_skill: SkillTransformer): # Lapis S2 # https://dragalialost.wiki/w/Lapis skill_data = transformer_skill.transform_attacking(109502012, is_exporting=True) possible_entries = skill_data.get_all_possible_entries() expected_addl_conds = [ Condition.SELF_LAPIS_CARD_0, Condition.SELF_LAPIS_CARD_1, Condition.SELF_LAPIS_CARD_2, Condition.SELF_LAPIS_CARD_3, ] expected_conds_up_rate = { ConditionComposite(addl_cond): min(ConditionCategories.self_lapis_card.convert(addl_cond) * 0.2, 0.8) for addl_cond in expected_addl_conds } expected = set(expected_conds_up_rate.keys()) actual = {entry.condition_comp for entry in possible_entries} assert expected == actual, actual.symmetric_difference(expected) for entry in possible_entries: expected_rate = 15.05 * 2 * (1 + expected_conds_up_rate[entry.condition_comp]) assert entry.total_mod_at_max == pytest.approx(expected_rate), entry.condition_comp del expected_conds_up_rate[entry.condition_comp] assert len(expected_conds_up_rate) == 0, f"Conditions not tested: {list(sorted(expected_conds_up_rate.keys()))}" # Not exporting skill_data = transformer_skill.transform_attacking(109502012, is_exporting=False) possible_entries = skill_data.get_all_possible_entries() expected_buff_count_conds = [ Condition.SELF_BUFF_0, Condition.SELF_BUFF_1, Condition.SELF_BUFF_2, Condition.SELF_BUFF_3, Condition.SELF_BUFF_4, Condition.SELF_BUFF_5, Condition.SELF_BUFF_6, Condition.SELF_BUFF_7, Condition.SELF_BUFF_8, Condition.SELF_BUFF_9, Condition.SELF_BUFF_10, Condition.SELF_BUFF_15, Condition.SELF_BUFF_20, Condition.SELF_BUFF_25, Condition.SELF_BUFF_30, Condition.SELF_BUFF_35, Condition.SELF_BUFF_40, Condition.SELF_BUFF_45, Condition.SELF_BUFF_50, ] expected_addl_conds = [ Condition.SELF_LAPIS_CARD_0, Condition.SELF_LAPIS_CARD_1, Condition.SELF_LAPIS_CARD_2, Condition.SELF_LAPIS_CARD_3, ] expected_conds_up_rate = { ConditionComposite([buff_count_cond, addl_cond]): min( ConditionCategories.self_buff_count.convert(buff_count_cond) * 0.05 + ConditionCategories.self_lapis_card.convert(addl_cond) * 0.2, 0.8 ) for buff_count_cond, addl_cond in product(expected_buff_count_conds, expected_addl_conds) } expected = set(expected_conds_up_rate.keys()) actual = {entry.condition_comp for entry in possible_entries} assert expected == actual, actual.symmetric_difference(expected) for entry in possible_entries: expected_rate = 15.05 * 2 * (1 + expected_conds_up_rate[entry.condition_comp]) assert entry.total_mod_at_max == pytest.approx(expected_rate), entry.condition_comp del expected_conds_up_rate[entry.condition_comp] assert len(expected_conds_up_rate) == 0, f"Conditions not tested: {list(sorted(expected_conds_up_rate.keys()))}"