Ejemplo n.º 1
0
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
Ejemplo n.º 2
0
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
            })
Ejemplo n.º 4
0
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()))}"