示例#1
0
    def __post_init__(self, asset_manager: "AssetManager"):
        # Quest basic properties
        self.quest_mode = self.quest_data.quest_mode
        self.elements = [
            Element(elem)
            for elem in (self.quest_data.element_1, self.quest_data.element_2)
            if elem.is_valid
        ]
        self.elements_limit = [
            Element(elem) for elem in (self.quest_data.element_1_limit,
                                       self.quest_data.element_2_limit)
            if elem.is_valid
        ]

        self.max_clear_time_sec = self.quest_data.max_time_sec
        self.max_revive_allowed = self.quest_data.max_revive

        # Quest dungeon area
        self.area_1_name = self.quest_data.area_1_name
        dungeon_plan = asset_manager.asset_dungeon_planner.get_data_by_id(
            self.area_1_name)

        # --- ``variation_idx`` is 1-based index

        self.spawn_enemy_param_ids = dungeon_plan.enemy_param_ids[
            self.quest_data.variation_idx - 1]
        if not self.spawn_enemy_param_ids:
            # In Legend Ciella quest, variation type is 4 while the only enemy parameter related is located at 0
            # This will attempt to take the data at variation 0
            self.spawn_enemy_param_ids = dungeon_plan.enemy_param_ids[0]
 def parse_raw(data: dict[str, Union[str, int]]) -> "QuestDataEntry":
     return QuestDataEntry(
         id=data["_Id"],
         quest_mode=QuestMode(data["_QuestPlayModeType"]),
         name_view_label=data["_QuestViewName"],
         element_1=Element(data["_Elemental"]),
         element_1_limit=Element(data["_LimitedElementalType"]),
         element_2=Element(data["_Elemental2"]),
         element_2_limit=Element(data["_LimitedElementalType2"]),
         max_time_sec=data["_FailedTermsTimeElapsed"],
         max_revive=data["_RebornLimit"],
         variation_idx=data["_VariationType"],
         area_1_name=data["_AreaName01"])
 def parse_raw(cls, data: dict[str, Union[str, int]]) -> "DragonDataEntry":
     return DragonDataEntry(
         id=data["_Id"],
         emblem_id=data["_EmblemId"],
         element=Element(data["_ElementalType"]),
         rarity=data["_Rarity"],
         name_label=data["_Name"],
         name_label_2=data["_SecondName"],
         base_id=data["_BaseId"],
         variation_id=data["_VariationId"],
         skill_1_id=data["_Skill1"],
         skill_2_id=data["_Skill2"],
         ability_id_1_lv1=data["_Abilities11"],
         ability_id_1_lv2=data["_Abilities12"],
         ability_id_1_lv3=data["_Abilities13"],
         ability_id_1_lv4=data["_Abilities14"],
         ability_id_1_lv5=data["_Abilities15"],
         ability_id_2_lv1=data["_Abilities21"],
         ability_id_2_lv2=data["_Abilities22"],
         ability_id_2_lv3=data["_Abilities23"],
         ability_id_2_lv4=data["_Abilities24"],
         ability_id_2_lv5=data["_Abilities25"],
         normal_attack_action_id=data["_DefaultSkill"],
         cv_en_label=data["_CvInfoEn"],
         cv_jp_label=data["_CvInfo"],
         release_date=cls.parse_datetime(data["_ReleaseStartDate"]),
         is_playable=bool(data["_IsPlayable"]),
         ss_skill_id=0,
         ss_skill_num=SkillNumber.NA,
         ss_skill_cost=0,
         unique_dragon_id=0,
     )
 def _from_elem_resist_up(
         self, asset_manager: "AssetManager",
         payload: AbilityVariantEffectPayload
 ) -> set[AbilityVariantEffectUnit]:
     return self._direct_buff_unit(
         Element(self.variant.id_a).to_elem_res_up_passive(), asset_manager,
         payload)
 def parse_raw(data: dict[str, Union[str, int]]) -> "EnemyDataEntry":
     return EnemyDataEntry(
         id=data["_Id"],
         initial_element=Element(data["_ElementalType"]),
         od_atk_rate=data["_ObAtkRate"],
         od_def_rate=data["_ObDefRate"],
         bk_duration_sec=data["_BreakDuration"],
         bk_def_rate=data["_BreakDefRate"],
     )
示例#6
0
    def conditions(self) -> list[Condition]:
        """
        Get the conditions for this action condition to be effective.

        If no conditions are required, return an empty list.

        If any of the conditions returned matches, then the action condition is considered effective.
        """
        if not self.target_limited_by_element:
            # Not limited to certain element, no condition
            return []

        return [
            ConditionCategories.target_element.convert_reversed(element)
            for element in Element.from_flag(self.elemental_target)
        ]
示例#7
0
 def parse_raw(data: dict[str, Union[str, int]]) -> "AbilityEntry":
     return AbilityEntry(
         id=data["_Id"],
         name_label=data["_Name"],
         description_label=data["_Details"],
         ability_icon_name=data["_AbilityIconName"],
         condition=AbilityConditionEntry(
             unit_type=UnitType(data["_UnitType"]),
             elemental_restriction=Element(data["_ElementalType"]),
             weapon_restriction=Weapon(data["_WeaponType"]),
             condition_code=data["_ConditionType"],
             val_1=data["_ConditionValue"],
             val_2=data["_ConditionValue2"],
             probability=data["_Probability"],
             cooldown_sec=data["_CoolTime"],
             max_occurrences=data["_OccurenceNum"],
             target_action=AbilityTargetAction(data["_TargetAction"]),
         ),
         on_skill=data["_OnSkill"],
         variant_1=AbilityVariantEntry(
             type_id=data["_AbilityType1"],
             id_a=data["_VariousId1a"],
             id_b=data["_VariousId1b"],
             id_c=data["_VariousId1c"],
             id_str=data["_VariousId1str"],
             limited_group_id=data["_AbilityLimitedGroupId1"],
             target_action_id=data["_TargetAction1"],
             up_value=data["_AbilityType1UpValue"]),
         variant_2=AbilityVariantEntry(
             type_id=data["_AbilityType2"],
             id_a=data["_VariousId2a"],
             id_b=data["_VariousId2b"],
             id_c=data["_VariousId2c"],
             id_str=data["_VariousId2str"],
             limited_group_id=data["_AbilityLimitedGroupId2"],
             target_action_id=data["_TargetAction2"],
             up_value=data["_AbilityType2UpValue"]),
         variant_3=AbilityVariantEntry(
             type_id=data["_AbilityType3"],
             id_a=data["_VariousId3a"],
             id_b=data["_VariousId3b"],
             id_c=data["_VariousId3c"],
             id_str=data["_VariousId3str"],
             limited_group_id=data["_AbilityLimitedGroupId3"],
             target_action_id=data["_TargetAction3"],
             up_value=data["_AbilityType3UpValue"]))
    def _init_elemental_buffs(self, action_condition_asset: ActionConditionAsset):
        self.buffs_elemental: list[dict[Element, set[HitActionConditionEffectUnit]]] = []

        for hit_data_lv in self.skill_hit_data.hit_data:
            buff_lv: dict[Element, set[HitActionConditionEffectUnit]] = {
                elem: set() for elem in Element.get_all_valid_elements()
            }

            for hit_data in hit_data_lv:
                if not hit_data.hit_attr.has_action_condition:
                    continue  # No action condition assigned

                action_condition = action_condition_asset.get_data_by_id(hit_data.action_condition_id)

                if not action_condition.target_limited_by_element:
                    continue  # Action condition not limited by element

                for elem in action_condition.elemental_target.elements:
                    buff_lv[elem].update(hit_data.to_buffing_units(action_condition_asset))

            self.buffs_elemental.append(buff_lv)
    def export(self):
        """Export the parsed assets."""
        # Enums
        self._export_enums(
            {
                "afflictions": cond_afflictions,
                "elements": cond_elements
            }, "conditions")
        self._export_enums_ex()
        self._export_enums({"weapon": Weapon.get_all_translatable_members()},
                           "weaponType")
        self._export_enums(
            {"elemental": Element.get_all_translatable_members()}, "elements")
        self._export_enums(
            {"unit": BuffValueUnit.get_all_translatable_members()},
            "buffParam")
        self._export_enums({"status": Status.get_all_translatable_members()},
                           "status")
        self._export_enums(
            {"cancel": SkillCancelAction.get_all_translatable_members()},
            "skill")
        self._export_enums_condition("allCondition")

        # Skill
        self._export_atk_skill()
        self._export_skill_identifiers("identifiers")

        # Abilties
        self._export_ex_abilities()

        # Info
        self._export_unit_info()
        self._export_normal_attack()

        # Story
        self._export_story()

        # Misc
        self._export_elem_bonus()
示例#10
0
class SkillDataBase(Generic[HT, ET], ABC):
    """Base class for a single skill data."""

    asset_manager: "AssetManager"

    skill_hit_data: "SkillHitData"

    skill_data: SkillDataEntry = field(init=False)
    skill_id: int = field(init=False)
    hit_data_mtx: list[list[HT]] = field(init=False)
    sp_gradual_fill_pct: list[float] = field(init=False)

    possible_conditions: set[ConditionComposite] = field(
        init=False, default_factory=ConditionComposite)

    max_level: int = field(init=False)

    @final
    def _init_possible_conditions_pre_conditions(
            self) -> Optional[set[tuple[Condition, ...]]]:
        pre_conditions: set[tuple[Condition, ...]] = {
            tuple(hit_data.pre_condition_comp)
            for hit_data_lv in self.hit_data_mtx for hit_data in hit_data_lv
            if hit_data.pre_condition_comp
        }
        if pre_conditions:
            if any(
                    any(pre_condition in ConditionCategories.skill_addl_inputs
                        for pre_condition in pre_condition_tuple)
                    for pre_condition_tuple in pre_conditions):
                # Pre-condition has additional inputs condition,
                # no-additional-input (additional input = 0) condition is possible
                # Appears in Lathna S1 (`105505021`), Ramona S1 (`104501011`)
                pre_conditions.add((Condition.ADDL_INPUT_0, ))

            if any(
                    any(pre_condition in
                        ConditionCategories.skill_action_cancel
                        for pre_condition in pre_condition_tuple)
                    for pre_condition_tuple in pre_conditions):
                # Pre-condition has action cancelling condition,
                # no cancelling (no condition) is possible
                # Appears in handle Formal Joachim S1 (`109503011`)
                pre_conditions.add(())

            if any(
                    any(pre_condition in ConditionCategories.trigger
                        for pre_condition in pre_condition_tuple)
                    for pre_condition_tuple in pre_conditions):
                # Pre-condition has trigger,
                # Triggering conditions are not always happening
                pre_conditions.add(())

            if any(
                    any(pre_condition in
                        ConditionCategories.skill_action_misc_var
                        for pre_condition in pre_condition_tuple)
                    for pre_condition_tuple in pre_conditions):
                # Skill has some variants. However, the skill can be used without triggering the variants.
                # Appears in Nobunaga S1 (`102501031`), Yoshitsune S1 (`109502021`)
                pre_conditions.add(())

            if any(Condition.SELF_PASSIVE_ENHANCED in pre_condition_tuple
                   for pre_condition_tuple in pre_conditions):
                # Pre-condition has passive enhancement, this is not always happening
                pre_conditions.add(())

            return pre_conditions

        return None

    @final
    def _init_possible_conditions_base_elems(self):
        cond_elems: list[set[tuple[Condition, ...]]] = []

        # Get all possible pre-conditions as a condition element
        if pre_conditions := self._init_possible_conditions_pre_conditions():
            cond_elems.append(pre_conditions)

        # Get the elemental restriction from the action conditions if any
        action_conds_elem_flag: set[ElementFlag] = set()
        for hit_data_lv in self.hit_data_mtx:
            for hit_data in hit_data_lv:
                if not hit_data.action_condition_id:
                    continue  # No action condition

                action_conds_elem_flag.add(
                    self.asset_manager.asset_action_cond.get_data_by_id(
                        hit_data.action_condition_id).elemental_target)
        if action_conds_elem_flag:
            # Elemental action condition available

            # Convert discovered elemental flags to elements
            action_conds_elem: set[Element] = set()
            for elem_flag in action_conds_elem_flag:
                action_conds_elem.update(Element.from_flag(elem_flag))

            # Convert elements to conditions and add it
            # - Dummy condition tuple for pre-condition of none, meaning other elements
            cond_elems.append({(
                ConditionCategories.target_element.convert_reversed(elem), )
                               for elem in action_conds_elem}
                              | {()})

        return cond_elems
def test_export_element_enums(asset_manager: AssetManager):
    export_enum(asset_manager, "element", Element.get_all_valid_elements())
    export_enum(asset_manager, "element",
                Element.get_all_translatable_members())
示例#12
0
 def parse_raw(cls, data: dict[str, Union[str, int,
                                          float]]) -> "CharaDataEntry":
     return CharaDataEntry(
         id=data["_Id"],
         name_label=data["_Name"],
         name_label_2=data["_SecondName"],
         emblem_id=data["_EmblemId"],
         weapon=Weapon(data["_WeaponType"]),
         rarity=data["_Rarity"],
         max_limit_break_count=data["_MaxLimitBreakCount"],
         element=Element(data["_ElementalType"]),
         chara_type_id=data["_CharaType"],
         base_id=data["_BaseId"],
         variation_id=data["_VariationId"],
         max_hp=data["_MaxHp"],
         max_hp_1=data["_AddMaxHp1"],
         plus_hp_0=data["_PlusHp0"],
         plus_hp_1=data["_PlusHp1"],
         plus_hp_2=data["_PlusHp2"],
         plus_hp_3=data["_PlusHp3"],
         plus_hp_4=data["_PlusHp4"],
         plus_hp_5=data["_PlusHp5"],
         mc_full_bonus_hp=data["_McFullBonusHp5"],
         max_atk=data["_MaxAtk"],
         max_atk_1=data["_AddMaxAtk1"],
         plus_atk_0=data["_PlusAtk0"],
         plus_atk_1=data["_PlusAtk1"],
         plus_atk_2=data["_PlusAtk2"],
         plus_atk_3=data["_PlusAtk3"],
         plus_atk_4=data["_PlusAtk4"],
         plus_atk_5=data["_PlusAtk5"],
         mc_full_bonus_atk=data["_McFullBonusAtk5"],
         def_coef=data["_DefCoef"],
         mode_change_type=ModeChangeType(data["_ModeChangeType"]),
         mode_1_id=data["_ModeId1"],
         mode_2_id=data["_ModeId2"],
         mode_3_id=data["_ModeId3"],
         mode_4_id=data["_ModeId4"],
         keep_mode_on_revive=bool(data["_KeepModeOnRevive"]),
         combo_original_id=data["_OriginCombo"],
         combo_mode_1_id=data["_Mode1Combo"],
         combo_mode_2_id=data["_Mode2Combo"],
         skill_1_id=data["_Skill1"],
         skill_2_id=data["_Skill2"],
         ability_1_lv_1_id=data["_Abilities11"],
         ability_1_lv_2_id=data["_Abilities12"],
         ability_1_lv_3_id=data["_Abilities13"],
         ability_1_lv_4_id=data["_Abilities14"],
         ability_2_lv_1_id=data["_Abilities21"],
         ability_2_lv_2_id=data["_Abilities22"],
         ability_2_lv_3_id=data["_Abilities23"],
         ability_2_lv_4_id=data["_Abilities24"],
         ability_3_lv_1_id=data["_Abilities31"],
         ability_3_lv_2_id=data["_Abilities32"],
         ability_3_lv_3_id=data["_Abilities33"],
         ability_3_lv_4_id=data["_Abilities34"],
         ex_1_id=data["_ExAbilityData1"],
         ex_2_id=data["_ExAbilityData2"],
         ex_3_id=data["_ExAbilityData3"],
         ex_4_id=data["_ExAbilityData4"],
         ex_5_id=data["_ExAbilityData5"],
         cex_1_id=data["_ExAbility2Data1"],
         cex_2_id=data["_ExAbility2Data2"],
         cex_3_id=data["_ExAbility2Data3"],
         cex_4_id=data["_ExAbility2Data4"],
         cex_5_id=data["_ExAbility2Data5"],
         fs_type_id=data["_ChargeType"],
         fs_count_max=data["_MaxChargeLv"],
         ss_cost_max_self=data["_HoldEditSkillCost"],
         ss_skill_id=data["_EditSkillId"],
         ss_skill_num=SkillNumber.s1_s2_only(data["_EditSkillLevelNum"]),
         ss_skill_cost=data["_EditSkillCost"],
         ss_skill_relation_id=data["_EditSkillRelationId"],
         ss_release_item_id=data["_EditReleaseEntityId1"],
         ss_release_item_quantity=data["_EditReleaseEntityQuantity1"],
         win_face_eye_id=data["_WinFaceEyeMotion"],
         win_face_mouth_id=data["_WinFaceEyeMotion"],
         unique_weapon_id=data["_UniqueWeaponId"],
         unique_dragon_id=data["_UniqueDragonId"],
         unique_dragon_inherit_skill_lv=bool(
             data["_IsConvertDragonSkillLevel"]),
         is_dragon_drive=bool(data["_WinFaceMouthMotion"]),  # ?????
         is_playable=bool(data["_IsPlayable"]),
         max_friendship_point=data["_MaxFriendshipPoint"],
         grow_material_start=cls.parse_datetime(
             data["_GrowMaterialOnlyStartDate"]),
         grow_material_end=cls.parse_datetime(
             data["_GrowMaterialOnlyEndDate"]),
         grow_material_id=data["_GrowMaterialId"],
         cv_en_label=data["_CvInfoEn"],
         cv_jp_label=data["_CvInfo"],
         release_date=cls.parse_datetime(data["_ReleaseStartDate"]))