diff --git a/StarRailUID/starrailuid_charinfo/damage/Avatar.py b/StarRailUID/starrailuid_charinfo/damage/Avatar.py index f10e14e..0323c85 100644 --- a/StarRailUID/starrailuid_charinfo/damage/Avatar.py +++ b/StarRailUID/starrailuid_charinfo/damage/Avatar.py @@ -94,10 +94,10 @@ class AvatarInstance: self.merge_attribute_bonus(self.weapon.weapon_attribute) async def gat_damage(self): - logger.info('base_attr') - logger.info(self.base_attr) - logger.info('attribute_bonus') - logger.info(self.attribute_bonus) + # logger.info('base_attr') + # logger.info(self.base_attr) + # logger.info('attribute_bonus') + # logger.info(self.attribute_bonus) logger.info('检查武器战斗生效的buff') Ultra_Use = self.avatar.Ultra_Use() diff --git a/StarRailUID/starrailuid_charinfo/damage/AvatarDamage/AvatarDamage.py b/StarRailUID/starrailuid_charinfo/damage/AvatarDamage/AvatarDamage.py index 811d085..a48e0c4 100644 --- a/StarRailUID/starrailuid_charinfo/damage/AvatarDamage/AvatarDamage.py +++ b/StarRailUID/starrailuid_charinfo/damage/AvatarDamage/AvatarDamage.py @@ -47,7 +47,17 @@ class Seele(BaseAvatar): attribute_bonus['AllDamageAddedRatio'] = self.Skill_num( 'Talent', 'Talent' ) + attribute_bonus.get('AllDamageAddedRatio', 0) - + + damage1, damage2, damage3 = await calculate_damage( + base_attr, + attribute_bonus, + 'fujia', + 'fujia', + 'Thunder', + 0.44, + self.avatar_level, + ) + skill_info_list = [] # 计算普攻伤害 skill_multiplier = self.Skill_num('Normal', 'Normal') @@ -60,6 +70,7 @@ class Seele(BaseAvatar): skill_multiplier, self.avatar_level, ) + damagelist1[2] += damage3 skill_info_list.append({'name': '普攻', 'damagelist': damagelist1}) # 计算战技伤害 @@ -73,6 +84,7 @@ class Seele(BaseAvatar): skill_multiplier, self.avatar_level, ) + damagelist2[2] += damage3 skill_info_list.append({'name': '战技', 'damagelist': damagelist2}) # 计算大招伤害 @@ -86,6 +98,7 @@ class Seele(BaseAvatar): skill_multiplier, self.avatar_level, ) + damagelist3[2] += damage3 skill_info_list.append({'name': '终结技', 'damagelist': damagelist3}) # 银狼降防终结技伤害 @@ -103,6 +116,7 @@ class Seele(BaseAvatar): skill_multiplier, self.avatar_level, ) + damagelist4[2] += damage3 skill_info_list.append({'name': '银狼降防终结技', 'damagelist': damagelist4}) logger.info(skill_info_list) @@ -144,6 +158,16 @@ class JingYuan(BaseAvatar): base_attr: Dict[str, float], attribute_bonus: Dict[str, float], ): + damage1, damage2, damage3 = await calculate_damage( + base_attr, + attribute_bonus, + 'fujia', + 'fujia', + 'Thunder', + 0.44, + self.avatar_level, + ) + skill_info_list = [] # 计算普攻伤害 skill_multiplier = self.Skill_num('Normal', 'Normal') @@ -156,6 +180,7 @@ class JingYuan(BaseAvatar): skill_multiplier, self.avatar_level, ) + damagelist1[2] += damage3 skill_info_list.append({'name': '普攻', 'damagelist': damagelist1}) # 计算战技伤害 @@ -169,6 +194,7 @@ class JingYuan(BaseAvatar): skill_multiplier, self.avatar_level, ) + damagelist2[2] += damage3 skill_info_list.append({'name': '战技', 'damagelist': damagelist2}) # 计算大招伤害 @@ -182,6 +208,7 @@ class JingYuan(BaseAvatar): skill_multiplier, self.avatar_level, ) + damagelist3[2] += damage3 skill_info_list.append({'name': '终结技', 'damagelist': damagelist3}) # 神君 @@ -195,6 +222,7 @@ class JingYuan(BaseAvatar): skill_multiplier, self.avatar_level, ) + damagelist4[2] += damage3 skill_info_list.append({'name': '10层神君伤害', 'damagelist': damagelist4}) logger.info(skill_info_list) @@ -231,6 +259,16 @@ class Welt(BaseAvatar): base_attr: Dict[str, float], attribute_bonus: Dict[str, float], ): + damage1, damage2, damage3 = await calculate_damage( + base_attr, + attribute_bonus, + 'fujia', + 'fujia', + 'Thunder', + 0.44, + self.avatar_level, + ) + skill_info_list = [] # 计算普攻伤害 skill_multiplier = self.Skill_num('Normal', 'Normal') @@ -243,6 +281,7 @@ class Welt(BaseAvatar): skill_multiplier, self.avatar_level, ) + damagelist1[2] += damage3 skill_info_list.append({'name': '普攻', 'damagelist': damagelist1}) # 计算战技伤害 @@ -262,6 +301,7 @@ class Welt(BaseAvatar): damagelist2[0] = damagelist2[0] * attnum damagelist2[1] = damagelist2[1] * attnum damagelist2[2] = damagelist2[2] * attnum + damagelist2[2] += damage3 skill_info_list.append({'name': '战技', 'damagelist': damagelist2}) # 计算大招伤害 @@ -275,6 +315,7 @@ class Welt(BaseAvatar): skill_multiplier, self.avatar_level, ) + damagelist3[2] += damage3 skill_info_list.append({'name': '终结技', 'damagelist': damagelist3}) if self.avatar_rank >= 1: @@ -291,6 +332,7 @@ class Welt(BaseAvatar): damagelist4[0] = damagelist1[0] + damagelist4[0] damagelist4[1] = damagelist1[1] + damagelist4[1] damagelist4[2] = damagelist1[2] + damagelist4[2] + damagelist4[2] += damage3 skill_info_list.append({'name': '强化普攻', 'damagelist': damagelist4}) skill_multiplier = (self.Skill_num('BPSkill', 'BPSkill') / 3) * 0.8 @@ -306,11 +348,266 @@ class Welt(BaseAvatar): damagelist5[0] = damagelist2[0] + damagelist5[0] damagelist5[1] = damagelist2[1] + damagelist5[1] damagelist5[2] = damagelist2[2] + damagelist5[2] + damagelist5[2] += damage3 skill_info_list.append({'name': '强化战技', 'damagelist': damagelist5}) logger.info(skill_info_list) return skill_info_list +class Danhengil(BaseAvatar): + Buff: BaseAvatarBuff + + def __init__( + self, char: DamageInstanceAvatar, skills: List[DamageInstanceSkill] + ): + super().__init__(char=char, skills=skills) + self.eidolon_attribute: Dict[str, float] = {} + self.extra_ability_attribute: Dict[str, float] = {} + self.eidolons() + self.extra_ability() + + def Technique(self): + pass + + def eidolons(self): + if self.avatar_rank >= 6: + self.extra_ability_attribute[ + 'Normal3_ImaginaryResistancePenetration' + ] = 0.6 + + def extra_ability(self): + logger.info('额外能力') + logger.info('对拥有虚数属性弱点的敌方目标造成伤害时, 暴击伤害提高24%。') + self.extra_ability_attribute['CriticalDamageBase'] = 0.24 + + async def getdamage( + self, + base_attr: Dict[str, float], + attribute_bonus: Dict[str, float], + ): + start_buff = 3 + add_buff = 1 + max_buff = 6 + if self.avatar_rank >= 1: + start_buff = 6 + add_buff = 2 + max_buff = 10 + + injury_add = self.Skill_num('Talent', 'Talent') + critical_damage_add = self.Skill_num('BPSkill', 'BPSkill') + critical_buff = 0 + if self.avatar_rank >= 4: + critical_buff = critical_damage_add * 4 + + skill_info_list = [] + # 计算普攻1伤害 + skill_multiplier = self.Skill_num('Normal', 'Normal') / 2 + damage_c = 0 + damage_e = 0 + damage_a = 0 + for i in range(1, 3): + add_attr_bonus = copy.deepcopy(attribute_bonus) + damage_buff = min(max_buff, start_buff + (i - 1) * add_buff) + add_attr_bonus['AllDamageAddedRatio'] = damage_buff * injury_add + add_attr_bonus.get( + 'AllDamageAddedRatio', 0 + ) + if self.avatar_rank >= 4: + add_attr_bonus['CriticalDamageBase'] = critical_buff + add_attr_bonus.get( + 'CriticalDamageBase', 0 + ) + damage1, damage2, damage3 = await calculate_damage( + base_attr, + add_attr_bonus, + 'Normal', + 'Normal', + self.avatar_element, + skill_multiplier, + self.avatar_level, + ) + damage_c += damage1 + damage_e += damage2 + damage_a += damage3 + damage1, damage2, damage3 = await calculate_damage( + base_attr, + add_attr_bonus, + 'Normal', + 'Normal', + 'Thunder', + 0.44, + self.avatar_level, + ) + damage_a += damage3 + skill_info_list.append({'name': '普攻', 'damagelist': [damage_c, damage_e, damage_a]}) + + # 计算瞬华伤害 + skill_multiplier = self.Skill_num('Normal', 'Normal1') / 3 + damage_c = 0 + damage_e = 0 + damage_a = 0 + for i in range(1, 4): + add_attr_bonus = copy.deepcopy(attribute_bonus) + damage_buff = min(max_buff, start_buff + (i - 1) * add_buff) + add_attr_bonus['AllDamageAddedRatio'] = damage_buff * injury_add + add_attr_bonus.get( + 'AllDamageAddedRatio', 0 + ) + if self.avatar_rank >= 4: + add_attr_bonus['CriticalDamageBase'] = critical_buff + add_attr_bonus.get( + 'CriticalDamageBase', 0 + ) + damage1, damage2, damage3 = await calculate_damage( + base_attr, + add_attr_bonus, + 'Normal', + 'Normal1', + self.avatar_element, + skill_multiplier, + self.avatar_level, + ) + damage_c += damage1 + damage_e += damage2 + damage_a += damage3 + damage1, damage2, damage3 = await calculate_damage( + base_attr, + add_attr_bonus, + 'Normal', + 'Normal', + 'Thunder', + 0.44, + self.avatar_level, + ) + damage_a += damage3 + skill_info_list.append({'name': '瞬华', 'damagelist': [damage_c, damage_e, damage_a]}) + + # 计算天矢阴伤害 + skill_multiplier = self.Skill_num('Normal', 'Normal2') / 5 + damage_c = 0 + damage_e = 0 + damage_a = 0 + for i in range(1, 6): + add_attr_bonus = copy.deepcopy(attribute_bonus) + damage_buff = min(max_buff, start_buff + (i - 1) * add_buff) + add_attr_bonus['AllDamageAddedRatio'] = damage_buff * injury_add + add_attr_bonus.get( + 'AllDamageAddedRatio', 0 + ) + if self.avatar_rank >= 4: + add_attr_bonus['CriticalDamageBase'] = critical_buff + add_attr_bonus.get( + 'CriticalDamageBase', 0 + ) + else: + if i >= 4: + critical_buff = (i - 3) * critical_damage_add + add_attr_bonus['CriticalDamageBase'] = critical_buff + add_attr_bonus.get( + 'CriticalDamageBase', 0 + ) + damage1, damage2, damage3 = await calculate_damage( + base_attr, + add_attr_bonus, + 'Normal', + 'Normal2', + self.avatar_element, + skill_multiplier, + self.avatar_level, + ) + damage_c += damage1 + damage_e += damage2 + damage_a += damage3 + damage1, damage2, damage3 = await calculate_damage( + base_attr, + add_attr_bonus, + 'Normal', + 'Normal', + 'Thunder', + 0.44, + self.avatar_level, + ) + damage_a += damage3 + skill_info_list.append({'name': '天矢阴', 'damagelist': [damage_c, damage_e, damage_a]}) + + # 计算盘拏耀跃伤害 + skill_multiplier = self.Skill_num('Normal', 'Normal3') / 7 + damage_c = 0 + damage_e = 0 + damage_a = 0 + for i in range(1, 8): + add_attr_bonus = copy.deepcopy(attribute_bonus) + damage_buff = min(max_buff, start_buff + (i - 1) * add_buff) + add_attr_bonus['AllDamageAddedRatio'] = damage_buff * injury_add + add_attr_bonus.get( + 'AllDamageAddedRatio', 0 + ) + if self.avatar_rank >= 4: + add_attr_bonus['CriticalDamageBase'] = critical_buff + add_attr_bonus.get( + 'CriticalDamageBase', 0 + ) + else: + if i >= 4: + critical_buff = (i - 3) * critical_damage_add + add_attr_bonus['CriticalDamageBase'] = critical_buff + add_attr_bonus.get( + 'CriticalDamageBase', 0 + ) + damage1, damage2, damage3 = await calculate_damage( + base_attr, + add_attr_bonus, + 'Normal', + 'Normal3', + self.avatar_element, + skill_multiplier, + self.avatar_level, + ) + damage_c += damage1 + damage_e += damage2 + damage_a += damage3 + damage1, damage2, damage3 = await calculate_damage( + base_attr, + add_attr_bonus, + 'Normal', + 'Normal', + 'Thunder', + 0.44, + self.avatar_level, + ) + damage_a += damage3 + skill_info_list.append({'name': '盘拏耀跃', 'damagelist': [damage_c, damage_e, damage_a]}) + + # 计算大招伤害 + skill_multiplier = self.Skill_num('Ultra', 'Ultra') / 3 + damage_c = 0 + damage_e = 0 + damage_a = 0 + for i in range(1, 4): + add_attr_bonus = copy.deepcopy(attribute_bonus) + damage_buff = min(max_buff, 10) + add_attr_bonus['AllDamageAddedRatio'] = damage_buff * injury_add + add_attr_bonus.get( + 'AllDamageAddedRatio', 0 + ) + critical_buff = 4 * critical_damage_add + add_attr_bonus['CriticalDamageBase'] = critical_buff + add_attr_bonus.get( + 'CriticalDamageBase', 0 + ) + damage1, damage2, damage3 = await calculate_damage( + base_attr, + add_attr_bonus, + 'Ultra', + 'Ultra', + self.avatar_element, + skill_multiplier, + self.avatar_level, + ) + damage_c += damage1 + damage_e += damage2 + damage_a += damage3 + damage1, damage2, damage3 = await calculate_damage( + base_attr, + add_attr_bonus, + 'Normal', + 'Normal', + 'Thunder', + 0.44, + self.avatar_level, + ) + damage_a += damage3 + skill_info_list.append({'name': '终结技', 'damagelist': [damage_c, damage_e, damage_a]}) + logger.info(skill_info_list) + return skill_info_list class AvatarDamage: @classmethod @@ -323,4 +620,6 @@ class AvatarDamage: return JingYuan(char, skills) if char.id_ == 1004: return Welt(char, skills) + if char.id_ == 1213: + return Danhengil(char, skills) raise Exception('不支持的角色') diff --git a/StarRailUID/starrailuid_charinfo/damage/Role.py b/StarRailUID/starrailuid_charinfo/damage/Role.py index 1dba89b..8d9c448 100644 --- a/StarRailUID/starrailuid_charinfo/damage/Role.py +++ b/StarRailUID/starrailuid_charinfo/damage/Role.py @@ -17,37 +17,53 @@ async def calculate_damage( logger.info(f'Skill Multiplier: {skill_multiplier}') logger.info(f'Skill Type: {skill_type}') logger.info(f'Level: {level}') + # logger.info(f'attribute_bonus: {attribute_bonus}') attribute_bonus = apply_attribute_bonus( attribute_bonus, skill_type, add_skill_type ) merged_attr = await merge_attribute(base_attr, attribute_bonus) + # logger.info(f'merged_attr: {merged_attr}') attack = merged_attr.get('attack', 0) logger.info(f'Attack: {attack}') damage_reduction = calculate_damage_reduction(level) + logger.info(f'韧性区: {damage_reduction}') + resistance_area = calculate_resistance_area( merged_attr, skill_type, add_skill_type, element ) + logger.info(f'抗性区: {resistance_area}') + defence_multiplier = calculate_defence_multiplier(level, merged_attr) + logger.info(f'防御区: {defence_multiplier}') + injury_area, element_area = calculate_injury_area( merged_attr, skill_type, add_skill_type, element ) + logger.info(f'增伤区: {injury_area}') + damage_ratio = calculate_damage_ratio( merged_attr, skill_type, add_skill_type ) + logger.info(f'易伤区: {damage_ratio}') + critical_damage = calculate_critical_damage( merged_attr, skill_type, add_skill_type ) + logger.info(f'爆伤区: {critical_damage}') + critical_chance = calculate_critical_chance( merged_attr, skill_type, add_skill_type ) + logger.info(f'暴击区: {critical_chance}') expected_damage = calculate_expected_damage( critical_chance, critical_damage ) + logger.info(f'暴击期望: {expected_damage}') damage_cd = calculate_damage_cd( attack, @@ -57,6 +73,7 @@ async def calculate_damage( defence_multiplier, resistance_area, damage_reduction, + critical_damage, ) damage_qw = calculate_damage_qw( attack, @@ -77,9 +94,10 @@ async def calculate_damage( defence_multiplier, resistance_area, damage_reduction, - expected_damage, + critical_damage, element, - element_area + element_area, + base_attr, ) skill_info_list = [damage_cd, damage_qw, damage_tz] @@ -126,20 +144,17 @@ def calculate_resistance_area( # 检查是否有某一属性的抗性穿透 attr_name = attr.split('ResistancePenetration')[0] if attr_name in (element, 'AllDamage'): - logger.info(f'{attr_name}属性有{merged_attr[attr]}穿透加成') + # logger.info(f'{attr_name}属性有{merged_attr[attr]}穿透加成') enemy_status_resistance += merged_attr[attr] # 检查是否有某一技能属性的抗性穿透 - skill_name, skillattr_name = ( - attr_name.split('_', 1) if '_' in attr_name else (None, None) - ) - if skill_name in ( - skill_type, - add_skill_type, - ) and skillattr_name in (element, 'AllDamage'): - enemy_status_resistance += merged_attr[attr] - logger.info( - f'{skill_name}对{skillattr_name}属性有{merged_attr[attr]}穿透加成' - ) + if '_' in attr_name: + skill_name = attr_name.split('_')[0] + skillattr_name = attr_name.split('_')[1] + if skill_name == add_skill_type and skillattr_name in (element, 'AllDamage'): + enemy_status_resistance += merged_attr[attr] + # logger.info( + # f'{skill_name}对{skillattr_name}属性有{merged_attr[attr]}穿透加成' + # ) return 1.0 - (0 - enemy_status_resistance) @@ -147,8 +162,8 @@ def calculate_defence_multiplier( level: int, merged_attr: Dict[str, float], ): - ignore_defence = merged_attr.get('ignore_defence', 1.0) - enemy_defence = (level * 10 + 200) * ignore_defence + ignore_defence = merged_attr.get('ignore_defence', 0.0) + enemy_defence = (level * 10 + 200) * (1 - ignore_defence) return (level * 10 + 200) / (level * 10 + 200 + enemy_defence) @@ -161,17 +176,24 @@ def calculate_injury_area( injury_area = 0.0 element_area = 0.0 for attr in merged_attr: - if 'DmgAdd' in attr and attr.split('DmgAdd')[0] in ( + attr_name = attr.split('AddedRatio')[0] + skill_name = attr.split('DmgAdd')[0] + if 'DmgAdd' in attr and skill_name in ( skill_type, add_skill_type, ): + # logger.info( + # f'{attr} 对 {skill_type} 有 {merged_attr[attr]} 伤害加成' + # ) injury_area += merged_attr[attr] - for attr in merged_attr: - attr_name = attr.split('DmgAdd')[0] + if 'AddedRatio' in attr and attr_name in ( element, 'AllDamage', ): + # logger.info( + # f'{attr} 对 {element} 属性有 {merged_attr[attr]} 伤害加成' + # ) if attr_name == element: element_area += merged_attr[attr] injury_area += merged_attr[attr] @@ -199,7 +221,7 @@ def calculate_critical_damage( add_skill_type: str, ): if skill_type == 'DOT': - return 0.0 + return 1.0 critical_damage_base = merged_attr.get('CriticalDamageBase', 0) for attr in merged_attr: if '_CriticalDamageBase' in attr and attr.split('_')[0] in ( @@ -229,7 +251,7 @@ def calculate_expected_damage( critical_chance_base: float, critical_damage_base: float, ): - return critical_chance_base * critical_damage_base + 1 + return critical_chance_base * (critical_damage_base - 1) + 1 def calculate_damage_cd( @@ -240,6 +262,7 @@ def calculate_damage_cd( defence_multiplier: float, resistance_area: float, damage_reduction: float, + critical_damage: float, ): return ( attack @@ -249,6 +272,7 @@ def calculate_damage_cd( * defence_multiplier * resistance_area * damage_reduction + * critical_damage ) @@ -282,36 +306,27 @@ def calculate_damage_tz( defence_multiplier: float, resistance_area: float, damage_reduction: float, - expected_damage: float, + critical_damage: float, element: str, - element_area: float + element_area: float, + base_attr: Dict[str, float], ): injury_add_tz = 0.0 - attack_tz = attack + attack * (1 + 2.144) + 0 + + attack_tz = attack + 355 + base_attr['attack'] * 2.334 + # logger.info(f'attack_tz: {attack_tz}') if element == 'Imaginary': injury_add_tz = 0.12 damage_tz = ( attack_tz * skill_multiplier * damage_ratio - * (injury_area + injury_add_tz + 2.326) + * (injury_area + injury_add_tz + 2.626) * defence_multiplier * resistance_area * damage_reduction - * (expected_damage + 1.594) + * (critical_damage + 1.794) * 10 ) - element_area = 0 if element == 'Thunder' else 0 - damage_tz_fj = ( - attack_tz - * 0.44 - * damage_ratio - * (injury_area + 2.326 + element_area) - * defence_multiplier - * resistance_area - * damage_reduction - * (expected_damage + 1.594) - * 10 - ) - damage_tz += damage_tz_fj + damage_tz return damage_tz diff --git a/StarRailUID/starrailuid_charinfo/damage/utils.py b/StarRailUID/starrailuid_charinfo/damage/utils.py index fd7768c..45aea74 100644 --- a/StarRailUID/starrailuid_charinfo/damage/utils.py +++ b/StarRailUID/starrailuid_charinfo/damage/utils.py @@ -12,10 +12,14 @@ async def merge_attribute( attr = attribute.split('Delta')[0].lower() if attr in merged_attr: merged_attr[attr] += value + else: + merged_attr[attribute] = attribute_bonus[attribute] elif attribute.endswith('AddedRatio'): attr = attribute.split('AddedRatio')[0].lower() if attr in merged_attr: - merged_attr[attr] += base_attr[attr] * (1 + value) + merged_attr[attr] += base_attr[attr] * value + else: + merged_attr[attribute] = attribute_bonus[attribute] elif attribute in ['ignore_defence', 'Atk_buff', 'Normal_buff', 'shield_added_ratio']: merged_attr[attribute] = base_attr.get(attribute, 0) + value elif attribute.endswith(('ResistancePenetration', 'DmgAdd', 'DmgRatio')): @@ -25,8 +29,4 @@ async def merge_attribute( else: logger.info(f'未知的属性加成: {attribute}, 采用覆盖模式') merged_attr[attribute] = attribute_bonus[attribute] - for attr in base_attr: - merged_value = merged_attr.get(attr, 0) - if merged_value == 0: - merged_attr[attr] = base_attr[attr] return merged_attr