From 8de5dd1ad116d7511e73a534198ebfad3ff187fd Mon Sep 17 00:00:00 2001 From: RaenonX Date: Tue, 26 Jan 2021 02:46:19 -0600 Subject: [PATCH] ADD - parse and export healing CCA (closes #5) Signed-off-by: RaenonX --- dlparse/export/entry/base/effect.py | 2 +- dlparse/model/ability_var_common.py | 14 ++++----- dlparse/model/action_cond_conv.py | 17 ++++++++++- dlparse/model/base/effect.py | 2 +- dlparse/model/hit_conv.py | 14 ++++----- dlparse/mono/asset/master/action_condition.py | 9 ++++-- .../test_chained_ex/test_main.py | 30 +++++++++++++++++++ tests/utils/unit_ability.py | 3 ++ tests/utils/unit_affliction.py | 6 ++-- 9 files changed, 76 insertions(+), 21 deletions(-) diff --git a/dlparse/export/entry/base/effect.py b/dlparse/export/entry/base/effect.py index 90d9c710..29f6063c 100644 --- a/dlparse/export/entry/base/effect.py +++ b/dlparse/export/entry/base/effect.py @@ -62,7 +62,7 @@ def to_json_entry(self) -> dict[str, Any]: }, "probabilityPct": self.effect_unit.probability_pct, "rate": self.effect_unit.rate, - "slipInterval": self.effect_unit.slip_interval, + "slipInterval": self.effect_unit.slip_interval_sec, "slipDamageMod": self.effect_unit.slip_damage_mod, "durationSec": self.effect_unit.duration_sec, "durationCount": self.effect_unit.duration_count, diff --git a/dlparse/model/ability_var_common.py b/dlparse/model/ability_var_common.py index e98afe37..0aee056c 100644 --- a/dlparse/model/ability_var_common.py +++ b/dlparse/model/ability_var_common.py @@ -140,7 +140,7 @@ def _action_cond_unit( max_stack_count=max_stack_count, duration_sec=action_cond.duration_sec, duration_count=0 if param_enum.is_duration_count_meaningless else action_cond.duration_count, - slip_interval=action_cond.slip_interval, + slip_interval_sec=action_cond.slip_interval_sec, slip_damage_mod=action_cond.slip_damage_mod, ) @@ -173,7 +173,7 @@ def _direct_buff_unit( duration_count=0, max_stack_count=payload.source_ability.condition.max_stack_count, slip_damage_mod=0, - slip_interval=0, + slip_interval_sec=0, ) } @@ -314,7 +314,7 @@ def _from_change_state_dragons_claws( is_chained_ex=payload.is_chained_ex, ) - ret.update(self.to_buff_units( + ret.update(self.to_effect_units( asset_manager.asset_action_cond.get_data_by_id(action_cond_id), payload_new )) @@ -342,7 +342,7 @@ def _from_change_state( # Get units from action condition IDs ret: set[AbilityVariantEffectUnit] = set() for action_cond_id in action_cond_ids: - ret.update(self.to_buff_units( + ret.update(self.to_effect_units( asset_manager.asset_action_cond.get_data_by_id(action_cond_id), payload )) return ret @@ -375,7 +375,7 @@ def _from_action_grant( payload.target_action = action_grant_data.target_action - units: set[AbilityVariantEffectUnit] = set(self.to_buff_units(action_cond_data, payload)) + units: set[AbilityVariantEffectUnit] = set(self.to_effect_units(action_cond_data, payload)) units.update(self.to_dispel_units(action_cond_data, payload)) return units @@ -396,7 +396,7 @@ def _from_addl_heal_on_revive( addl_cond_comp=ConditionComposite(Condition.ON_REVIVED) ) - def to_effect_units( + def get_effect_units( self, asset_manager: "AssetManager", payload: AbilityVariantEffectPayload ) -> set[AbilityVariantEffectUnit]: """ @@ -451,6 +451,6 @@ def ability_to_effect_units( if variant.type_enum == AbilityVariantType.OTHER_ABILITY: continue # Refer to the other ability, no variant effect - effect_units.update(AbilityVariantData(variant).to_effect_units(asset_manager, payload)) + effect_units.update(AbilityVariantData(variant).get_effect_units(asset_manager, payload)) return effect_units diff --git a/dlparse/model/action_cond_conv.py b/dlparse/model/action_cond_conv.py index 7ba63091..68ca56fb 100644 --- a/dlparse/model/action_cond_conv.py +++ b/dlparse/model/action_cond_conv.py @@ -93,6 +93,20 @@ def _units_defensive_buffs( self.to_param_up(BuffParameter.RESISTANCE_SHADOW_BUFF, action_cond.resistance_shadow, action_cond, payload) ] + def _units_recovery_buffs( + self, action_cond: "ActionConditionEntry", payload: Optional[PT] = None + ) -> list[Optional[UT]]: + return [ + # Over time HP heal + self.to_param_up( + BuffParameter.HEAL_OVER_TIME_HP, -action_cond.slip_damage_hp_rate, action_cond, payload + ), + # Over time RP heal + self.to_param_up( + BuffParameter.HEAL_OVER_TIME_RP, action_cond.regen_rp / 100, action_cond, payload + ), + ] + def _units_special_buffs( self, action_cond: "ActionConditionEntry", payload: Optional[PT] = None ) -> list[Optional[UT]]: @@ -103,7 +117,7 @@ def _units_special_buffs( self.to_param_up(BuffParameter.INSPIRE_LEVEL, action_cond.inspire_lv, action_cond, payload), ] - def to_buff_units( + def to_effect_units( self, action_cond: "ActionConditionEntry", payload: Optional[PT] = None ) -> list[UT]: """Convert ``action_cond`` to a list of effect units.""" @@ -111,6 +125,7 @@ def to_buff_units( unit for unit in self._units_common_buffs(action_cond, payload) + self._units_defensive_buffs(action_cond, payload) + + self._units_recovery_buffs(action_cond, payload) + self._units_special_buffs(action_cond, payload) if unit # Skipping empty unit ] diff --git a/dlparse/model/base/effect.py b/dlparse/model/base/effect.py index a5a74b78..1da89d86 100644 --- a/dlparse/model/base/effect.py +++ b/dlparse/model/base/effect.py @@ -18,7 +18,7 @@ class EffectUnitBase(ABC): probability_pct: float # 90 = 90% rate: float - slip_interval: float + slip_interval_sec: float slip_damage_mod: float duration_sec: float diff --git a/dlparse/model/hit_conv.py b/dlparse/model/hit_conv.py index 714c2224..29f6746a 100644 --- a/dlparse/model/hit_conv.py +++ b/dlparse/model/hit_conv.py @@ -40,7 +40,7 @@ def to_param_up( parameter=param_enum, probability_pct=action_cond.probability_pct, rate=param_rate, - slip_interval=action_cond.slip_interval, + slip_interval_sec=action_cond.slip_interval_sec, slip_damage_mod=action_cond.slip_damage_mod, duration_sec=self.get_duration(action_cond), duration_count=action_cond.duration_count, @@ -71,7 +71,7 @@ def to_affliction_unit( probability_pct=action_cond.probability_pct, parameter=BuffParameter.AFFLICTION, duration_sec=action_cond.duration_sec, - slip_interval=action_cond.slip_interval, + slip_interval_sec=action_cond.slip_interval_sec, slip_damage_mod=action_cond.slip_damage_mod, max_stack_count=action_cond.max_stack_count, hit_attr_label=self.hit_attr.id, @@ -88,7 +88,7 @@ def to_dispel_unit( probability_pct=action_cond.probability_pct, parameter=BuffParameter.DISPEL, duration_sec=action_cond.duration_sec, - slip_interval=action_cond.slip_interval, + slip_interval_sec=action_cond.slip_interval_sec, slip_damage_mod=action_cond.slip_damage_mod, max_stack_count=action_cond.max_stack_count, hit_attr_label=self.hit_attr.id, @@ -115,7 +115,7 @@ def to_damage_self(starting_time: float, hit_attr: HitAttrEntry) -> Optional[Hit target=HitTargetSimple.SELF, parameter=BuffParameter.HP_FIX_BY_MAX, rate=hit_attr.hp_fix_rate, - slip_interval=0, + slip_interval_sec=0, slip_damage_mod=0, duration_sec=0, duration_count=0, @@ -132,7 +132,7 @@ def to_damage_self(starting_time: float, hit_attr: HitAttrEntry) -> Optional[Hit target=HitTargetSimple.SELF, parameter=BuffParameter.HP_DECREASE_BY_MAX, rate=hit_attr.hp_consumption_rate, - slip_interval=0, + slip_interval_sec=0, slip_damage_mod=0, duration_sec=0, duration_count=0, @@ -159,7 +159,7 @@ def to_marker_unit(self, asset_action_condition: ActionConditionAsset) -> list[H target=HitTargetSimple.ENEMY, parameter=BuffParameter.MARK, rate=0, - slip_interval=action_cond.slip_interval, + slip_interval_sec=action_cond.slip_interval_sec, slip_damage_mod=action_cond.slip_damage_mod, duration_sec=action_cond.duration_sec, duration_count=action_cond.duration_count, @@ -206,7 +206,7 @@ def to_buffing_units( # --- General buffs if action_cond: - units.extend(self.to_buff_units(action_cond)) + units.extend(self.to_effect_units(action_cond)) # --- Instant gauge refill diff --git a/dlparse/mono/asset/master/action_condition.py b/dlparse/mono/asset/master/action_condition.py index 54299803..3a9d4428 100644 --- a/dlparse/mono/asset/master/action_condition.py +++ b/dlparse/mono/asset/master/action_condition.py @@ -36,8 +36,11 @@ class ActionConditionEntry(MasterEntryBase): efficacy_type: EfficacyType - slip_interval: float + slip_interval_sec: float slip_damage_mod: float + slip_damage_hp_rate: float + + regen_rp: float buff_atk: float buff_def: float @@ -87,8 +90,10 @@ def parse_raw(data: dict[str, Union[str, int]]) -> "ActionConditionEntry": duration_count_max=duration_count_max, probability_pct=data["_Rate"], efficacy_type=EfficacyType(data["_EfficacyType"]), - slip_interval=data["_SlipDamageIntervalSec"], + slip_interval_sec=data["_SlipDamageIntervalSec"], slip_damage_mod=data["_SlipDamagePower"], + slip_damage_hp_rate=data["_SlipDamageRatio"], + regen_rp=data["_RegenePower"], buff_atk=data["_RateAttack"], buff_def=data["_RateDefense"], buff_def_b=data["_RateDefenseB"], diff --git a/tests/test_transformer/test_chained_ex/test_main.py b/tests/test_transformer/test_chained_ex/test_main.py index a9a1447f..0ebb6274 100644 --- a/tests/test_transformer/test_chained_ex/test_main.py +++ b/tests/test_transformer/test_chained_ex/test_main.py @@ -297,3 +297,33 @@ def test_combo_time_extend(transformer_ability: AbilityTransformer): } check_ability_effect_unit_match(ex_ability_data.effect_units, expected_info) + + +def test_regen_on_hp_below(transformer_ability: AbilityTransformer): + # Lea - 10150103 + # https://dragalialost.gamepedia.com/Nobunaga + ex_ability_data = transformer_ability.transform_chained_ex_ability(400000710) + + expected_info = { + AbilityEffectInfo( + 400000710, ConditionComposite([Condition.TARGET_FLAME, Condition.ON_HP_LT_60]), + BuffParameter.HEAL_OVER_TIME_HP, 0.04, duration_sec=20, slip_interval_sec=3.9 + ), + } + + check_ability_effect_unit_match(ex_ability_data.effect_units, expected_info) + + +def test_regen_on_combo_above(transformer_ability: AbilityTransformer): + # Summer Norwin - 10350302 + # https://dragalialost.gamepedia.com/Summer_Norwin + ex_ability_data = transformer_ability.transform_chained_ex_ability(400000770) + + expected_info = { + AbilityEffectInfo( + 400000770, ConditionComposite([Condition.TARGET_WIND, Condition.ON_COMBO_GTE_10]), + BuffParameter.HEAL_OVER_TIME_RP, 0.07200000000000001, slip_interval_sec=2.9 + ), + } + + check_ability_effect_unit_match(ex_ability_data.effect_units, expected_info) diff --git a/tests/utils/unit_ability.py b/tests/utils/unit_ability.py index 4e0b48da..1327e5b9 100644 --- a/tests/utils/unit_ability.py +++ b/tests/utils/unit_ability.py @@ -29,6 +29,7 @@ class AbilityEffectInfo(AbilityInfoBase): target_action: Optional[AbilityTargetAction] = None duration_sec: Optional[float] = None duration_count: Optional[float] = None + slip_interval_sec: Optional[float] = None def __hash__(self): # x 1E5 for error tolerance @@ -69,6 +70,7 @@ def check_ability_effect_unit_match( has_target_action = any(info.target_action is not None for info in expected_info) has_duration_sec = any(info.duration_sec is not None for info in expected_info) has_duration_count = any(info.duration_count is not None for info in expected_info) + has_slip_interval = any(info.slip_interval_sec is not None for info in expected_info) actual_info = [ AbilityEffectInfo( @@ -83,6 +85,7 @@ def check_ability_effect_unit_match( target_action=unit.target_action if has_target_action else None, duration_sec=unit.duration_sec if has_duration_sec else None, duration_count=unit.duration_count if has_duration_count else None, + slip_interval_sec=unit.slip_interval_sec if has_slip_interval else None, ) for unit in actual_units ] diff --git a/tests/utils/unit_affliction.py b/tests/utils/unit_affliction.py index 776ffaa3..a7d2f1c0 100644 --- a/tests/utils/unit_affliction.py +++ b/tests/utils/unit_affliction.py @@ -33,8 +33,10 @@ def check_affliction_unit_match( ): """Check if the info of the affliction units match.""" actual_info = [ - AfflictionInfo(unit.hit_attr_label, unit.status, unit.probability_pct, unit.duration_sec, unit.slip_interval, - unit.slip_damage_mod, unit.stackable) + AfflictionInfo( + unit.hit_attr_label, unit.status, unit.probability_pct, unit.duration_sec, + unit.slip_interval_sec, unit.slip_damage_mod, unit.stackable + ) for unit in actual_units ]