From cdacd947cd81e2128e96b52e890546bd78746d8b Mon Sep 17 00:00:00 2001 From: qwerdvd <2450899274@qq.com> Date: Thu, 5 Oct 2023 14:17:05 +0800 Subject: [PATCH] refactor --- .../damage/AvatarDamage/AvatarDamage.py | 30 +- .../damage/Relic/Relic.py | 2 - .../starrailuid_charinfo/damage/Role.py | 418 ++++++++++-------- .../starrailuid_charinfo/damage/utils.py | 75 +--- 4 files changed, 263 insertions(+), 262 deletions(-) diff --git a/StarRailUID/starrailuid_charinfo/damage/AvatarDamage/AvatarDamage.py b/StarRailUID/starrailuid_charinfo/damage/AvatarDamage/AvatarDamage.py index e287a4d..811d085 100644 --- a/StarRailUID/starrailuid_charinfo/damage/AvatarDamage/AvatarDamage.py +++ b/StarRailUID/starrailuid_charinfo/damage/AvatarDamage/AvatarDamage.py @@ -3,9 +3,9 @@ from typing import Dict, List from gsuid_core.logger import logger -from ..Role import demage_num from ..Base.AvatarBase import BaseAvatar, BaseAvatarBuff -from ..Base.model import DamageInstanceSkill, DamageInstanceAvatar +from ..Base.model import DamageInstanceAvatar, DamageInstanceSkill +from ..Role import calculate_damage class Seele(BaseAvatar): @@ -51,7 +51,7 @@ class Seele(BaseAvatar): skill_info_list = [] # 计算普攻伤害 skill_multiplier = self.Skill_num('Normal', 'Normal') - damagelist1 = await demage_num( + damagelist1 = await calculate_damage( base_attr, attribute_bonus, 'Normal', @@ -64,7 +64,7 @@ class Seele(BaseAvatar): # 计算战技伤害 skill_multiplier = self.Skill_num('BPSkill', 'BPSkill') - damagelist2 = await demage_num( + damagelist2 = await calculate_damage( base_attr, attribute_bonus, 'BPSkill', @@ -77,7 +77,7 @@ class Seele(BaseAvatar): # 计算大招伤害 skill_multiplier = self.Skill_num('Ultra', 'Ultra') - damagelist3 = await demage_num( + damagelist3 = await calculate_damage( base_attr, attribute_bonus, 'Ultra', @@ -94,7 +94,7 @@ class Seele(BaseAvatar): add_attr_bonus['ignore_defence'] = 0.45 + add_attr_bonus.get( 'ignore_defence', 0 ) - damagelist4 = await demage_num( + damagelist4 = await calculate_damage( base_attr, add_attr_bonus, 'Ultra', @@ -147,7 +147,7 @@ class JingYuan(BaseAvatar): skill_info_list = [] # 计算普攻伤害 skill_multiplier = self.Skill_num('Normal', 'Normal') - damagelist1 = await demage_num( + damagelist1 = await calculate_damage( base_attr, attribute_bonus, 'Normal', @@ -160,7 +160,7 @@ class JingYuan(BaseAvatar): # 计算战技伤害 skill_multiplier = self.Skill_num('BPSkill', 'BPSkill') - damagelist2 = await demage_num( + damagelist2 = await calculate_damage( base_attr, attribute_bonus, 'BPSkill', @@ -173,7 +173,7 @@ class JingYuan(BaseAvatar): # 计算大招伤害 skill_multiplier = self.Skill_num('Ultra', 'Ultra') - damagelist3 = await demage_num( + damagelist3 = await calculate_damage( base_attr, attribute_bonus, 'Ultra', @@ -186,7 +186,7 @@ class JingYuan(BaseAvatar): # 神君 skill_multiplier = self.Skill_num('Talent', 'Talent') - damagelist4 = await demage_num( + damagelist4 = await calculate_damage( base_attr, attribute_bonus, 'Talent', @@ -234,7 +234,7 @@ class Welt(BaseAvatar): skill_info_list = [] # 计算普攻伤害 skill_multiplier = self.Skill_num('Normal', 'Normal') - damagelist1 = await demage_num( + damagelist1 = await calculate_damage( base_attr, attribute_bonus, 'Normal', @@ -248,7 +248,7 @@ class Welt(BaseAvatar): # 计算战技伤害 attnum = 3 skill_multiplier = self.Skill_num('BPSkill', 'BPSkill') / attnum - damagelist2 = await demage_num( + damagelist2 = await calculate_damage( base_attr, attribute_bonus, 'BPSkill', @@ -266,7 +266,7 @@ class Welt(BaseAvatar): # 计算大招伤害 skill_multiplier = self.Skill_num('Ultra', 'Ultra') - damagelist3 = await demage_num( + damagelist3 = await calculate_damage( base_attr, attribute_bonus, 'Ultra', @@ -279,7 +279,7 @@ class Welt(BaseAvatar): if self.avatar_rank >= 1: skill_multiplier = self.Skill_num('Normal', 'Normal') * 0.5 - damagelist4 = await demage_num( + damagelist4 = await calculate_damage( base_attr, attribute_bonus, 'Normal', @@ -294,7 +294,7 @@ class Welt(BaseAvatar): skill_info_list.append({'name': '强化普攻', 'damagelist': damagelist4}) skill_multiplier = (self.Skill_num('BPSkill', 'BPSkill') / 3) * 0.8 - damagelist5 = await demage_num( + damagelist5 = await calculate_damage( base_attr, attribute_bonus, 'BPSkill', diff --git a/StarRailUID/starrailuid_charinfo/damage/Relic/Relic.py b/StarRailUID/starrailuid_charinfo/damage/Relic/Relic.py index cf40c97..7e2b21f 100644 --- a/StarRailUID/starrailuid_charinfo/damage/Relic/Relic.py +++ b/StarRailUID/starrailuid_charinfo/damage/Relic/Relic.py @@ -240,7 +240,6 @@ class Relic110(BaseRelicSetSkill): ): if self.pieces4 and await self.check(base_attr, attribute_bonus): logger.info('ModifyActionDelay') - pass return attribute_bonus @@ -263,7 +262,6 @@ class Relic111(BaseRelicSetSkill): ): if self.pieces4 and await self.check(base_attr, attribute_bonus): logger.info('ModifySPNew') - pass return attribute_bonus diff --git a/StarRailUID/starrailuid_charinfo/damage/Role.py b/StarRailUID/starrailuid_charinfo/damage/Role.py index b52c5ff..721106e 100644 --- a/StarRailUID/starrailuid_charinfo/damage/Role.py +++ b/StarRailUID/starrailuid_charinfo/damage/Role.py @@ -1,253 +1,289 @@ -from typing import List, Union +from typing import Dict from gsuid_core.logger import logger from .utils import merge_attribute -async def demage_num( - base_attr, - attribute_bonus, - skill_type, - add_skill_type, - element, - skill_multiplier, - level, +async def calculate_damage( + base_attr: Dict[str, float], + attribute_bonus: Dict[str, float], + skill_type: str, + add_skill_type: str, + element: str, + skill_multiplier: float, + level: int, ): - logger.info(f'技能区: {skill_multiplier}') - logger.info(f'skill_type: {skill_type}') - logger.info(f'level: {level}') - # logger.info(f'base_attr: {base_attr}') - # logger.info(f'attribute_bonus: {attribute_bonus}') - # 检查是否有对某一个技能的属性加成 - logger.info('检查是否有对某一个技能的属性加成') - for attr in attribute_bonus: - # 攻击加成 - if attr.__contains__('AttackAddedRatio'): - attr_name = attr.split('AttackAddedRatio')[0] - if attr_name in (skill_type, add_skill_type): - attack_added_ratio = attribute_bonus.get('AttackAddedRatio', 0) - attribute_bonus['AttackAddedRatio'] = ( - attack_added_ratio + attribute_bonus[attr] - ) - # 效果命中加成 - if attr.__contains__('StatusProbabilityBase'): - attr_name = attr.split('StatusProbabilityBase')[0] - if attr_name in (skill_type, add_skill_type): - status_probability = attribute_bonus.get( - 'StatusProbabilityBase', 0 - ) - attribute_bonus['StatusProbabilityBase'] = ( - status_probability + attribute_bonus[attr] - ) + logger.info(f'Skill Multiplier: {skill_multiplier}') + logger.info(f'Skill Type: {skill_type}') + logger.info(f'Level: {level}') + + 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}') - skill_info_list = [] + attack = merged_attr.get('attack', 0) - logger.info(f'攻击力: {attack}') - damage_add = 0 + logger.info(f'Attack: {attack}') - # 模拟 同属性弱点 同等级 的怪物 - # 韧性条减伤 + damage_reduction = calculate_damage_reduction(level) + resistance_area = calculate_resistance_area(merged_attr, element) + defence_multiplier = calculate_defence_multiplier(level, merged_attr) + injury_area = calculate_injury_area( + merged_attr, skill_type, add_skill_type, element + ) + damage_ratio = calculate_damage_ratio( + merged_attr, skill_type, add_skill_type + ) + critical_damage = calculate_critical_damage( + merged_attr, skill_type, add_skill_type + ) + critical_chance = calculate_critical_chance( + merged_attr, skill_type, add_skill_type + ) + + expected_damage = calculate_expected_damage( + critical_chance, critical_damage + ) + + damage_cd = calculate_damage_cd( + attack, + skill_multiplier, + damage_ratio, + injury_area, + defence_multiplier, + resistance_area, + damage_reduction, + ) + damage_qw = calculate_damage_qw( + attack, + skill_multiplier, + damage_ratio, + injury_area, + defence_multiplier, + resistance_area, + damage_reduction, + expected_damage, + ) + + damage_tz = calculate_damage_tz( + attack, + skill_multiplier, + damage_ratio, + injury_area, + defence_multiplier, + resistance_area, + damage_reduction, + expected_damage, + element, + ) + + skill_info_list = [damage_cd, damage_qw, damage_tz] + + logger.info( + f'Critical Damage: {damage_cd} Expected Damage: {damage_qw} Apocalypse Damage: {damage_tz}' + ) + + return skill_info_list + + +def apply_attribute_bonus( + attribute_bonus: Dict[str, float], + skill_type: str, + add_skill_type: str, +): + # Apply attribute bonuses to attack and status probability + for attr in attribute_bonus: + if 'AttackAddedRatio' in attr and attr.split('AttackAddedRatio')[ + 0 + ] in (skill_type, add_skill_type): + attribute_bonus['AttackAddedRatio'] += attribute_bonus[attr] + if 'StatusProbabilityBase' in attr and attr.split( + 'StatusProbabilityBase' + )[0] in (skill_type, add_skill_type): + attribute_bonus['StatusProbabilityBase'] += attribute_bonus[attr] + return attribute_bonus + + +def calculate_damage_reduction(level: int): enemy_damage_reduction = 0.1 - damage_reduction = 1 - enemy_damage_reduction - logger.info(f'韧性区: {damage_reduction}') - # 抗性区 - enemy_status_resistance = 0.0 - for attr in merged_attr: - if attr.__contains__('ResistancePenetration'): - # 检查是否有某一属性的抗性穿透 - attr_name = attr.split('ResistancePenetration')[0] - if attr_name in (element, 'AllDamage'): - logger.info(f'{attr_name}属性有{merged_attr[attr]}穿透加成') - enemy_status_resistance += merged_attr[attr] - # 检查是否有某一技能属性的抗性穿透 - if attr_name.__contains__('_'): - skill_name = attr_name.split('_')[0] - skillattr_name = attr_name.split('_')[1] - 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]}穿透加成' - ) - resistance_area = 1.0 - (0 - enemy_status_resistance) - logger.info(f'抗性区: {resistance_area}') + return 1 - enemy_damage_reduction - # 防御区 - # 检查是否有 ignore_defence - logger.info('检查是否有 ignore_defence') - ignore_defence = 1.0 - for attr in merged_attr: - if attr == 'ignore_defence': - ignore_defence = 1 - merged_attr[attr] - break - logger.info(f'ignore_defence {ignore_defence}') + +def calculate_resistance_area(merged_attr: Dict[str, float], element: str): + enemy_status_resistance = sum( + merged_attr.get(attr, 0) + for attr in merged_attr + if 'ResistancePenetration' in attr + ) + return 1.0 - max(0, -enemy_status_resistance) + + +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 - defence_multiplier = (level * 10 + 200) / ( - level * 10 + 200 + enemy_defence - ) - logger.info(f'防御区: {defence_multiplier}') + return (level * 10 + 200) / (level * 10 + 200 + enemy_defence) - # 增伤区 - injury_area = 0 - # 检查是否有对某一个技能的伤害加成 - # logger.info('检查是否有对某一个技能的伤害加成') - for attr in merged_attr: - if attr.__contains__('DmgAdd'): - attr_name = attr.split('DmgAdd')[0] - if attr_name in (skill_type, add_skill_type): - logger.info( - f'{attr} 对 {skill_type} 有 {merged_attr[attr]} 伤害加成' - ) - injury_area += merged_attr[attr] - # 检查有无符合属性的伤害加成 - # logger.info('检查球有无符合属性的伤害加成') - element_area = 0 - for attr in merged_attr: - if attr.__contains__('AddedRatio'): - attr_name = attr.split('AddedRatio')[0] - if 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] - injury_area += 1 - logger.info(f'增伤区: {injury_area}') - # 易伤区 - # logger.info('检查是否有易伤加成') +def calculate_injury_area( + merged_attr: Dict[str, float], + skill_type: str, + add_skill_type: str, + element: str, +): + injury_area = 0.0 + for attr in merged_attr: + if 'DmgAdd' in attr and attr.split('DmgAdd')[0] in ( + skill_type, + add_skill_type, + ): + injury_area += merged_attr[attr] + for attr in merged_attr: + if 'AddedRatio' in attr and attr.split('AddedRatio')[0] in ( + element, + 'AllDamage', + ): + injury_area += merged_attr[attr] + return injury_area + 1 + + +def calculate_damage_ratio( + merged_attr: Dict[str, float], + skill_type: str, + add_skill_type: str, +): damage_ratio = merged_attr.get('DmgRatio', 0) - # 检查是否有对特定技能的易伤加成 - # Talent_DmgRatio for attr in merged_attr: - if attr.__contains__('_DmgRatio'): - skill_name = attr.split('_')[0] - if skill_name in (skill_type, add_skill_type): - logger.info( - f'{attr} 对 {skill_type} 有 {merged_attr[attr]} 易伤加成' - ) - damage_ratio += merged_attr[attr] - damage_ratio = damage_ratio + 1 - logger.info(f'易伤: {damage_ratio}') + if '_DmgRatio' in attr and attr.split('_')[0] in ( + skill_type, + add_skill_type, + ): + damage_ratio += merged_attr[attr] + return damage_ratio + 1 - # 爆伤区 + +def calculate_critical_damage( + merged_attr: Dict[str, float], + skill_type: str, + add_skill_type: str, +): if skill_type == 'DOT': - critical_damage_base = 0.0 - else: - # logger.info('检查是否有爆伤加成') - # logger.info(f'{merged_attr}') - critical_damage_base = merged_attr.get('CriticalDamageBase', 0) - # 检查是否有对特定技能的爆伤加成 - # Ultra_CriticalChance - for attr in merged_attr: - if attr.__contains__('_CriticalDamageBase'): - skill_name = attr.split('_')[0] - if skill_name in (skill_type, add_skill_type): - logger.info( - f'{attr} 对 {skill_type} 有 {merged_attr[attr]} 爆伤加成' - ) - critical_damage_base += merged_attr[attr] - critical_damage = critical_damage_base + 1 - logger.info(f'暴伤: {critical_damage}') - - # 暴击区 - logger.info('检查是否有暴击加成') - critical_chance_base = merged_attr['CriticalChanceBase'] - # 检查是否有对特定技能的爆伤加成 - # Ultra_CriticalChance + return 0.0 + critical_damage_base = merged_attr.get('CriticalDamageBase', 0) for attr in merged_attr: - if attr.__contains__('_CriticalChance'): - skill_name = attr.split('_')[0] - if skill_name in (skill_type, add_skill_type): - logger.info( - f'{attr} 对 {skill_type} 有 {merged_attr[attr]} 暴击加成' - ) - critical_chance_base += merged_attr[attr] - critical_chance_base = min(1, critical_chance_base) - logger.info(f'暴击: {critical_chance_base}') + if '_CriticalDamageBase' in attr and attr.split('_')[0] in ( + skill_type, + add_skill_type, + ): + critical_damage_base += merged_attr[attr] + return critical_damage_base + 1 - # 期望伤害 - qiwang_damage = (critical_chance_base * critical_damage_base) + 1 - logger.info(f'暴击期望: {qiwang_damage}') - attack_tz = 0.0 - injury_add = 0.0 - critical_damage_add = 0 +def calculate_critical_chance( + merged_attr: Dict[str, float], + skill_type: str, + add_skill_type: str, +): + critical_chance_base = merged_attr['CriticalChanceBase'] + for attr in merged_attr: + if '_CriticalChance' in attr and attr.split('_')[0] in ( + skill_type, + add_skill_type, + ): + critical_chance_base += merged_attr[attr] + return min(1, critical_chance_base) - damage_cd = ( + +def calculate_expected_damage( + critical_chance: float, + critical_damage: float, +): + return critical_chance * critical_damage + 1 + + +def calculate_damage_cd( + attack: float, + skill_multiplier: float, + damage_ratio: float, + injury_area: float, + defence_multiplier: float, + resistance_area: float, + damage_reduction: float, +): + return ( attack * skill_multiplier * damage_ratio - * (injury_area + injury_add) + * injury_area * defence_multiplier * resistance_area * damage_reduction - * (critical_damage + critical_damage_add) - + damage_add ) - damage_qw = ( + +def calculate_damage_qw( + attack: float, + skill_multiplier: float, + damage_ratio: float, + injury_area: float, + defence_multiplier: float, + resistance_area: float, + damage_reduction: float, + expected_damage: float, +): + return ( attack * skill_multiplier * damage_ratio - * (injury_area + injury_add) + * injury_area * defence_multiplier * resistance_area * damage_reduction - * qiwang_damage - + damage_add + * expected_damage ) - attr_value_tz: float = base_attr.get('attack', 0) - attribute_atk = attribute_bonus.get('AttackDelta', 0) - attack_tz = ( - attr_value_tz - + attr_value_tz - * (1 + attribute_bonus.get('AttackAddedRatio', 0) + 2.144) - + attribute_atk - ) - - injury_add_tz = 0 +def calculate_damage_tz( + attack: float, + skill_multiplier: float, + damage_ratio: float, + injury_area: float, + defence_multiplier: float, + resistance_area: float, + damage_reduction: float, + expected_damage: float, + element: str, +): + injury_add_tz = 0.0 + attack_tz = attack + attack * (1 + 2.144) + 0 if element == 'Imaginary': injury_add_tz = 0.12 - damage_tz = ( attack_tz * skill_multiplier * damage_ratio - * (injury_area + injury_add + injury_add_tz + 2.326) + * (injury_area + injury_add_tz + 2.326) * defence_multiplier * resistance_area * damage_reduction - * (critical_damage + critical_damage_add + 1.594) + * (expected_damage + 1.594) * 10 - + damage_add ) - - if element == 'Thunder': - element_area = 0 + element_area = 0 if element == 'Thunder' else 0 damage_tz_fj = ( attack_tz * 0.44 * damage_ratio - * (injury_area + injury_add + 2.326 + element_area) + * (injury_area + 2.326 + element_area) * defence_multiplier * resistance_area * damage_reduction - * (critical_damage + critical_damage_add + 1.594) + * (expected_damage + 1.594) * 10 ) damage_tz += damage_tz_fj - skill_info_list: List[Union[str, float]] = [] - skill_info_list.append(damage_cd) - skill_info_list.append(damage_qw) - skill_info_list.append(damage_tz) - logger.info(f'暴击: {damage_cd} 期望:{damage_qw} 末日:{damage_tz}') - return skill_info_list + return damage_tz diff --git a/StarRailUID/starrailuid_charinfo/damage/utils.py b/StarRailUID/starrailuid_charinfo/damage/utils.py index 61ac5df..fd7768c 100644 --- a/StarRailUID/starrailuid_charinfo/damage/utils.py +++ b/StarRailUID/starrailuid_charinfo/damage/utils.py @@ -1,65 +1,32 @@ from typing import Dict +from gsuid_core.logger import logger + async def merge_attribute( base_attr: Dict[str, float], attribute_bonus: Dict[str, float] -): - # hp attack defence need base_value and add_value - merged_attr: Dict[str, float] = {} - attr_list = ['attack', 'defence', 'hp', 'speed'] - for attribute in attribute_bonus: - if ( - attribute.__contains__('Attack') - or attribute.__contains__('Defence') - or attribute.__contains__('HP') - or attribute.__contains__('Speed') - ): - if attribute.__contains__('Delta'): - attr = attribute.split('Delta')[0].lower() - if attr in attr_list: - attr_value = merged_attr.get(attr, 0) - merged_attr[attr] = attr_value + attribute_bonus[attribute] - elif attribute.__contains__('AddedRatio'): - attr = attribute.split('AddedRatio')[0].lower() - if attr in attr_list: - attr_value = merged_attr.get(attr, 0) - merged_attr[attr] = attr_value + base_attr[attr] * ( - 1 + attribute_bonus[attribute] - ) - else: - raise Exception(f'attribute error {attribute}') - elif attribute.__contains__('Base'): - attr_value = base_attr.get(attribute, 0) - merged_attr[attribute] = attr_value + attribute_bonus[attribute] - elif attribute.__contains__('AddedRatio'): - attr_value = base_attr.get(attribute, 0) - merged_attr[attribute] = attr_value + attribute_bonus[attribute] - elif attribute.__contains__('DmgAdd'): - attr_value = base_attr.get(attribute, 0) - merged_attr[attribute] = attr_value + attribute_bonus[attribute] - elif attribute.__contains__('DmgRatio'): - attr_value = base_attr.get(attribute, 0) - merged_attr[attribute] = attr_value + attribute_bonus[attribute] - elif attribute == 'ignore_defence': - attr_value = base_attr.get(attribute, 0) - merged_attr[attribute] = attr_value + attribute_bonus[attribute] - elif attribute.__contains__('ResistancePenetration'): - attr_value = base_attr.get(attribute, 0) - merged_attr[attribute] = attr_value + attribute_bonus[attribute] - elif attribute == 'Atk_buff': - attr_value = base_attr.get(attribute, 0) - merged_attr[attribute] = attr_value + attribute_bonus[attribute] - elif attribute == 'Normal_buff': - attr_value = base_attr.get(attribute, 0) - merged_attr[attribute] = attr_value + attribute_bonus[attribute] - elif attribute == 'shield_added_ratio': - attr_value = base_attr.get(attribute, 0) - merged_attr[attribute] = attr_value + attribute_bonus[attribute] +) -> Dict[str, float]: + merged_attr = base_attr.copy() + for attribute, value in attribute_bonus.items(): + if attribute.endswith('Delta'): + attr = attribute.split('Delta')[0].lower() + if attr in merged_attr: + merged_attr[attr] += value + elif attribute.endswith('AddedRatio'): + attr = attribute.split('AddedRatio')[0].lower() + if attr in merged_attr: + merged_attr[attr] += base_attr[attr] * (1 + value) + 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')): + merged_attr[attribute] = base_attr.get(attribute, 0) + value + elif attribute.endswith('Base'): + merged_attr[attribute] = base_attr.get(attribute, 0) + value else: - continue + 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