mirror of
https://github.com/baiqwerdvd/StarRailUID.git
synced 2025-05-06 11:43:44 +08:00
WIP
This commit is contained in:
parent
bdc103eab4
commit
a36b6d3a0c
@ -38,7 +38,7 @@ class Avatar(Struct):
|
||||
avatarId: int
|
||||
level: int
|
||||
equipment: Equipment | None = None
|
||||
relicList: list[Relic] | None = None
|
||||
relicList: list[Relic] | None = field(default=[])
|
||||
pos: int | None = field(default=0)
|
||||
rank: int | None = field(default=0)
|
||||
promotion: int | None = field(default=0)
|
||||
|
@ -2,7 +2,7 @@ import json
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Union
|
||||
|
||||
from .effect.Role import RoleInstance
|
||||
from .effect.damageCal import DamageCalculator
|
||||
from .mono.Character import Character
|
||||
|
||||
Excel_path = Path(__file__).parent / 'effect'
|
||||
@ -26,8 +26,7 @@ async def cal(char_data: Dict):
|
||||
skill_list = skill_dict[str(char.char_id)]['skillList']
|
||||
skill_list = skill_list.keys()
|
||||
for skill_type in skill_list:
|
||||
role = RoleInstance(char)
|
||||
im_tmp = await role.cal_damage(skill_type)
|
||||
im_tmp = await DamageCalculator(char).cal_damage(skill_type)
|
||||
skill_info_list.append(im_tmp)
|
||||
return skill_info_list
|
||||
return '角色伤害计算未完成'
|
||||
|
@ -4,29 +4,14 @@ import textwrap
|
||||
from pathlib import Path
|
||||
from typing import Dict, Union
|
||||
|
||||
from PIL import Image, ImageDraw
|
||||
from gsuid_core.logger import logger
|
||||
from gsuid_core.utils.image.convert import convert_img
|
||||
from gsuid_core.utils.image.image_tools import draw_text_by_line
|
||||
from PIL import Image, ImageDraw
|
||||
|
||||
from .to_data import api_to_dict
|
||||
from ..utils.error_reply import CHAR_HINT
|
||||
from .cal_damage import cal, cal_char_info
|
||||
from ..utils.fonts.first_world import fw_font_28
|
||||
from ..utils.excel.read_excel import light_cone_ranks
|
||||
from ..utils.map.name_covert import name_to_avatar_id, alias_to_char_name
|
||||
from ..utils.map.SR_MAP_PATH import (
|
||||
RelicId2Rarity,
|
||||
AvatarRelicScore,
|
||||
avatarId2Name,
|
||||
)
|
||||
from ..utils.resource.RESOURCE_PATH import (
|
||||
RELIC_PATH,
|
||||
SKILL_PATH,
|
||||
PLAYER_PATH,
|
||||
WEAPON_PATH,
|
||||
CHAR_PORTRAIT_PATH,
|
||||
)
|
||||
from ..utils.fonts.first_world import fw_font_28
|
||||
from ..utils.fonts.starrail_fonts import (
|
||||
sr_font_18,
|
||||
sr_font_20,
|
||||
@ -37,6 +22,21 @@ from ..utils.fonts.starrail_fonts import (
|
||||
sr_font_34,
|
||||
sr_font_38,
|
||||
)
|
||||
from ..utils.map.name_covert import alias_to_char_name, name_to_avatar_id
|
||||
from ..utils.map.SR_MAP_PATH import (
|
||||
AvatarRelicScore,
|
||||
RelicId2Rarity,
|
||||
avatarId2Name,
|
||||
)
|
||||
from ..utils.resource.RESOURCE_PATH import (
|
||||
CHAR_PORTRAIT_PATH,
|
||||
PLAYER_PATH,
|
||||
RELIC_PATH,
|
||||
SKILL_PATH,
|
||||
WEAPON_PATH,
|
||||
)
|
||||
from .cal_damage import cal, cal_char_info
|
||||
from .to_data import api_to_dict
|
||||
|
||||
Excel_path = Path(__file__).parent / 'effect'
|
||||
with Path.open(Excel_path / 'Excel' / 'SkillData.json', encoding='utf-8') as f:
|
||||
@ -99,7 +99,7 @@ async def draw_char_img(char_data: Dict, sr_uid: str, msg: str):
|
||||
return char_data
|
||||
char = await cal_char_info(char_data)
|
||||
damage_len = 0
|
||||
if str(char.char_id) in skill_dict:
|
||||
if char.char_id in skill_dict:
|
||||
skill_list = skill_dict[str(char.char_id)]['skillList']
|
||||
damage_len = len(skill_list)
|
||||
bg_height = 0
|
||||
|
@ -3,7 +3,7 @@ from typing import Dict, List
|
||||
from gsuid_core.logger import logger
|
||||
|
||||
from ..Base.AvatarBase import BaseAvatar, BaseAvatarBuff
|
||||
from ..Base.model import DamageInstanceSkill, DamageInstanceAvatar
|
||||
from ..Base.model import DamageInstanceAvatar, DamageInstanceSkill
|
||||
|
||||
|
||||
class Seele(BaseAvatar):
|
||||
|
@ -1,14 +1,14 @@
|
||||
import json
|
||||
from pathlib import Path
|
||||
from abc import abstractmethod
|
||||
from typing import List, Union
|
||||
from pathlib import Path
|
||||
from typing import List, Tuple, Union
|
||||
|
||||
import msgspec
|
||||
from msgspec import Struct
|
||||
|
||||
from .SkillBase import BaseSkills
|
||||
from ....utils.excel.model import AvatarPromotionConfig
|
||||
from .model import DamageInstanceSkill, DamageInstanceAvatar
|
||||
from .model import DamageInstanceAvatar, DamageInstanceSkill
|
||||
from .SkillBase import BaseSkills
|
||||
|
||||
path = Path(__file__).parent.parent
|
||||
with Path.open(path / 'Excel' / 'SkillData.json', encoding='utf-8') as f:
|
||||
@ -24,7 +24,7 @@ class BaseAvatarAttribute(Struct):
|
||||
CriticalDamageBase: float
|
||||
BaseAggro: float
|
||||
|
||||
def items(self):
|
||||
def items(self) -> List[Tuple[str, float]]:
|
||||
return [
|
||||
('attack', self.attack),
|
||||
('defence', self.defence),
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -4,16 +4,12 @@ from typing import List, Union
|
||||
|
||||
from gsuid_core.logger import logger
|
||||
|
||||
from .Avatar.Avatar import Avatar
|
||||
from .Weapon.Weapon import Weapon
|
||||
from .utils import merge_attribute
|
||||
from ..mono.Character import Character
|
||||
from .Avatar.Avatar import Avatar
|
||||
from .Base.model import DamageInstance
|
||||
from .Relic.Relic import RelicSet, SingleRelic
|
||||
|
||||
Excel_path = Path(__file__).parent
|
||||
with Path.open(Excel_path / 'Excel' / 'SkillData.json', encoding='utf-8') as f:
|
||||
skill_dict = json.load(f)
|
||||
from .utils import merge_attribute
|
||||
from .Weapon.Weapon import Weapon
|
||||
|
||||
|
||||
class RoleInstance:
|
||||
@ -119,416 +115,3 @@ class RoleInstance:
|
||||
self.attribute_bonus[attribute] = self.weapon.weapon_attribute[
|
||||
attribute
|
||||
]
|
||||
|
||||
async def cal_damage(self, skill_type: str):
|
||||
logger.info('base_attr')
|
||||
logger.info(self.base_attr)
|
||||
logger.info('attribute_bonus')
|
||||
logger.info(self.attribute_bonus)
|
||||
logger.info(skill_type)
|
||||
# 技能区
|
||||
skill_info = self.avatar.Skill_Info(skill_type)
|
||||
skill_multiplier = self.avatar.Skill_num(skill_info[4], skill_type)
|
||||
# 检查是否有对某一个技能的倍率加成
|
||||
for attr in self.attribute_bonus:
|
||||
if attr.__contains__('SkillAdd'):
|
||||
skill_name = attr.split('SkillAdd')[0]
|
||||
if skill_name in (skill_type, skill_info[3]):
|
||||
logger.info(
|
||||
f'{skill_name}对{skill_type}有{self.attribute_bonus[attr]}倍率加成'
|
||||
)
|
||||
skill_multiplier = (
|
||||
skill_multiplier + self.attribute_bonus[attr]
|
||||
)
|
||||
|
||||
logger.info(f'技能区总: {skill_multiplier}')
|
||||
|
||||
# 检查武器战斗生效的buff
|
||||
logger.info('检查武器战斗生效的buff')
|
||||
Ultra_Use = self.avatar.Ultra_Use()
|
||||
logger.info('Ultra_Use')
|
||||
logger.info(Ultra_Use)
|
||||
self.attribute_bonus = await self.weapon.weapon_ability(
|
||||
Ultra_Use, self.base_attr, self.attribute_bonus
|
||||
)
|
||||
logger.info(self.attribute_bonus)
|
||||
logger.info('检查遗器套装战斗生效的buff')
|
||||
for set_skill in self.relic_set.SetSkill:
|
||||
self.attribute_bonus = await set_skill.set_skill_ability(
|
||||
self.base_attr, self.attribute_bonus
|
||||
)
|
||||
if self.attribute_bonus is None:
|
||||
raise Exception('attribute_bonus is None')
|
||||
logger.info(self.attribute_bonus)
|
||||
|
||||
# 检查是否有对某一个技能的属性加成
|
||||
logger.info('检查是否有对某一个技能的属性加成')
|
||||
for attr in self.attribute_bonus:
|
||||
# 攻击加成
|
||||
if attr.__contains__('AttackAddedRatio'):
|
||||
attr_name = attr.split('AttackAddedRatio')[0]
|
||||
if attr_name in (skill_type, skill_info[3]):
|
||||
attack_added_ratio = self.attribute_bonus.get(
|
||||
'AttackAddedRatio', 0
|
||||
)
|
||||
self.attribute_bonus['AttackAddedRatio'] = (
|
||||
attack_added_ratio + self.attribute_bonus[attr]
|
||||
)
|
||||
# 效果命中加成
|
||||
if attr.__contains__('StatusProbabilityBase'):
|
||||
attr_name = attr.split('StatusProbabilityBase')[0]
|
||||
if attr_name in (skill_type, skill_info[3]):
|
||||
status_probability = self.attribute_bonus.get(
|
||||
'StatusProbabilityBase', 0
|
||||
)
|
||||
self.attribute_bonus['StatusProbabilityBase'] = (
|
||||
status_probability + self.attribute_bonus[attr]
|
||||
)
|
||||
|
||||
merged_attr = await merge_attribute(
|
||||
self.base_attr, self.attribute_bonus
|
||||
)
|
||||
logger.info(f'{merged_attr}')
|
||||
skill_info_list = []
|
||||
# 技能类型为攻击
|
||||
if skill_info[0] == 'attack':
|
||||
if isinstance(skill_info[2], str):
|
||||
raise Exception('skill_info[2] is str')
|
||||
skill_multiplier = skill_multiplier / skill_info[2]
|
||||
logger.info(f'技能区单段: {skill_multiplier}')
|
||||
if self.raw_data.avatar.id_ == 1004:
|
||||
if self.raw_data.avatar.rank >= 6 and skill_type == 'BPSkill':
|
||||
skill_info[2] = skill_info[2] + 1
|
||||
multiplier_add = self.avatar.Talent()
|
||||
skill_multiplier = skill_multiplier + multiplier_add
|
||||
|
||||
if (
|
||||
self.raw_data.avatar.id_ == 1201
|
||||
and self.raw_data.avatar.rank >= 4
|
||||
and skill_type == 'Normal'
|
||||
):
|
||||
skill_info[2] = skill_info[2] + 1
|
||||
|
||||
attack = merged_attr.get('attack', 0)
|
||||
if self.raw_data.avatar.id_ == 1104:
|
||||
# 杰帕德天赋加攻
|
||||
defence = merged_attr['defence']
|
||||
attack = attack + (defence * 0.35)
|
||||
logger.info(f'攻击力: {attack}')
|
||||
damage_add = 0
|
||||
hp_multiplier = 0
|
||||
hp_num = 0
|
||||
if self.raw_data.avatar.id_ in [1205, 1208]:
|
||||
hp_num = merged_attr['hp']
|
||||
skill_type_hp = skill_type + '_HP'
|
||||
if skill_type_hp in skill_dict[str(self.raw_data.avatar.id_)]:
|
||||
hp_multiplier = self.avatar.Skill_num(
|
||||
skill_info[4], skill_type_hp
|
||||
)
|
||||
else:
|
||||
hp_multiplier = 0
|
||||
for attr in self.attribute_bonus:
|
||||
if attr.__contains__('HpSkillAdd'):
|
||||
skill_name = attr.split('HpSkillAdd')[0]
|
||||
if skill_name in (skill_type, skill_info[3]):
|
||||
logger.info(
|
||||
f'{skill_name}对{skill_type}有{self.attribute_bonus[attr]}倍率加成'
|
||||
)
|
||||
hp_multiplier = (
|
||||
hp_multiplier + self.attribute_bonus[attr]
|
||||
)
|
||||
|
||||
if skill_type == 'Talent':
|
||||
if (
|
||||
self.raw_data.avatar.rank >= 6
|
||||
and self.raw_data.avatar.id_ == 1205
|
||||
):
|
||||
damage_add = hp_num * 0.5
|
||||
attack = (skill_multiplier * attack) + (hp_multiplier * hp_num)
|
||||
skill_multiplier = 1
|
||||
logger.info(f'混伤区: {attack}')
|
||||
|
||||
logger.info(f'额外伤害: {damage_add}')
|
||||
# 模拟 同属性弱点 同等级 的怪物
|
||||
# 韧性条减伤
|
||||
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 (self.avatar.avatar_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,
|
||||
skill_info[3],
|
||||
) and skillattr_name in (
|
||||
self.avatar.avatar_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}')
|
||||
|
||||
# 防御区
|
||||
# 检查是否有 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}')
|
||||
enemy_defence = (
|
||||
self.avatar.avatar_level * 10 + 200
|
||||
) * ignore_defence
|
||||
defence_multiplier = (self.avatar.avatar_level * 10 + 200) / (
|
||||
self.avatar.avatar_level * 10 + 200 + enemy_defence
|
||||
)
|
||||
logger.info(f'防御区: {defence_multiplier}')
|
||||
|
||||
# 增伤区
|
||||
# TODO: 这里计算只考虑了希儿,需要重写 injury_area = self.avatar.Talent_add()
|
||||
injury_area = self.avatar.Talent_add()
|
||||
# 检查是否有对某一个技能的伤害加成
|
||||
logger.info('检查是否有对某一个技能的伤害加成')
|
||||
for attr in merged_attr:
|
||||
if attr.__contains__('DmgAdd'):
|
||||
attr_name = attr.split('DmgAdd')[0]
|
||||
if attr_name in (skill_type, skill_info[3]):
|
||||
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 (self.avatar.avatar_element, 'AllDamage'):
|
||||
logger.info(
|
||||
f'{attr} 对 {self.avatar.avatar_element} '
|
||||
f'有 {merged_attr[attr]} 伤害加成'
|
||||
)
|
||||
if attr_name == self.avatar.avatar_element:
|
||||
element_area += merged_attr[attr]
|
||||
injury_area += merged_attr[attr]
|
||||
injury_area += 1
|
||||
logger.info(f'增伤区: {injury_area}')
|
||||
|
||||
# 易伤区
|
||||
logger.info('检查是否有易伤加成')
|
||||
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, skill_info[3]):
|
||||
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 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, skill_info[3]):
|
||||
logger.info(
|
||||
f'{attr} 对 {skill_type} 有 '
|
||||
f'{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
|
||||
for attr in merged_attr:
|
||||
if attr.__contains__('_CriticalChance'):
|
||||
skill_name = attr.split('_')[0]
|
||||
if skill_name in (skill_type, skill_info[3]):
|
||||
logger.info(
|
||||
f'{attr} 对 {skill_type} 有 '
|
||||
f'{merged_attr[attr]} 暴击加成'
|
||||
)
|
||||
critical_chance_base += merged_attr[attr]
|
||||
critical_chance_base = min(1, critical_chance_base)
|
||||
logger.info(f'暴击: {critical_chance_base}')
|
||||
|
||||
# 期望伤害
|
||||
qiwang_damage = (critical_chance_base * critical_damage_base) + 1
|
||||
logger.info(f'暴击期望: {qiwang_damage}')
|
||||
damage_cd_z = 0.0
|
||||
damage_qw_z = 0.0
|
||||
damage_tz_z = 0.0
|
||||
attack_tz = 0.0
|
||||
injury_add = 0.0
|
||||
critical_damage_add = 0
|
||||
for i in range(1, skill_info[2] + 1):
|
||||
injury_add = 0
|
||||
critical_damage_add = 0
|
||||
if self.raw_data.avatar.id_ == 1213:
|
||||
injury_add = self.avatar.Talent()
|
||||
critical_damage_add = self.avatar.BPSkill()
|
||||
normal_buff = merged_attr.get('Normal_buff', 0)
|
||||
if i >= 4:
|
||||
normal_buff = min(4, int(normal_buff + (i - 3)))
|
||||
if normal_buff >= 1:
|
||||
critical_damage_add = normal_buff * critical_damage_add
|
||||
atk_buff = merged_attr.get('Atk_buff', 0)
|
||||
atk_buff = min(10, int((i - 1) * (atk_buff + 1)))
|
||||
injury_add = atk_buff * injury_add
|
||||
qiwang_damage = (
|
||||
critical_chance_base
|
||||
* (critical_damage_base + critical_damage_add)
|
||||
) + 1
|
||||
|
||||
damage_cd = (
|
||||
attack
|
||||
* skill_multiplier
|
||||
* damage_ratio
|
||||
* (injury_area + injury_add)
|
||||
* defence_multiplier
|
||||
* resistance_area
|
||||
* damage_reduction
|
||||
* (critical_damage + critical_damage_add)
|
||||
+ damage_add
|
||||
)
|
||||
damage_cd_z += damage_cd
|
||||
damage_qw = (
|
||||
attack
|
||||
* skill_multiplier
|
||||
* damage_ratio
|
||||
* (injury_area + injury_add)
|
||||
* defence_multiplier
|
||||
* resistance_area
|
||||
* damage_reduction
|
||||
* qiwang_damage
|
||||
+ damage_add
|
||||
)
|
||||
damage_qw_z += damage_qw
|
||||
|
||||
attr_value_tz: float = self.base_attr.get('attack', 0)
|
||||
attribute_atk = self.attribute_bonus.get('AttackDelta', 0)
|
||||
attack_tz = (
|
||||
attr_value_tz
|
||||
+ attr_value_tz
|
||||
* (
|
||||
1
|
||||
+ self.attribute_bonus.get('AttackAddedRatio', 0)
|
||||
+ 2.144
|
||||
)
|
||||
+ attribute_atk
|
||||
)
|
||||
if self.raw_data.avatar.id_ in [1205, 1208]:
|
||||
attack_tz = (skill_multiplier * attack_tz) + (
|
||||
hp_multiplier * hp_num
|
||||
)
|
||||
injury_add_tz = 0
|
||||
if self.avatar.avatar_element == 'Imaginary':
|
||||
injury_add_tz = 0.12
|
||||
damage_tz = (
|
||||
attack_tz
|
||||
* skill_multiplier
|
||||
* damage_ratio
|
||||
* (injury_area + injury_add + injury_add_tz + 2.326)
|
||||
* defence_multiplier
|
||||
* resistance_area
|
||||
* damage_reduction
|
||||
* (critical_damage + critical_damage_add + 1.594)
|
||||
* 10
|
||||
+ damage_add
|
||||
)
|
||||
|
||||
damage_tz_z += damage_tz
|
||||
|
||||
if (
|
||||
self.raw_data.avatar.id_ == 1003
|
||||
and self.raw_data.avatar.rank >= 6
|
||||
):
|
||||
damage_cd_z = damage_cd_z * 1.8
|
||||
damage_qw_z = damage_qw_z * 1.8
|
||||
damage_tz_z = damage_tz_z * 1.8
|
||||
|
||||
if self.avatar.avatar_element == 'Thunder':
|
||||
element_area = 0
|
||||
damage_tz_fj = (
|
||||
attack_tz
|
||||
* 0.44
|
||||
* damage_ratio
|
||||
* (injury_area + injury_add + 2.326 + element_area)
|
||||
* defence_multiplier
|
||||
* resistance_area
|
||||
* damage_reduction
|
||||
* (critical_damage + critical_damage_add + 1.594)
|
||||
* 10
|
||||
)
|
||||
damage_tz_z += damage_tz_fj
|
||||
skill_info_list: List[Union[str, float]] = []
|
||||
skill_info_list.append(skill_info[1])
|
||||
skill_info_list.append(damage_cd_z)
|
||||
skill_info_list.append(damage_qw_z)
|
||||
skill_info_list.append(damage_tz_z)
|
||||
logger.info(
|
||||
f'{skill_info[1]} 暴击伤害: {damage_cd_z} 期望伤害{damage_qw_z}'
|
||||
)
|
||||
|
||||
# 技能类型为防御
|
||||
if skill_info[0] == 'defence':
|
||||
defence = merged_attr['defence']
|
||||
logger.info(f'防御力: {defence}')
|
||||
defence_multiplier = 0
|
||||
|
||||
# 获取技能提供的固定护盾值
|
||||
if skill_type == 'Normal':
|
||||
defence_multiplier = self.avatar.Normalnum('Normal_G')
|
||||
elif skill_type == 'BPSkill':
|
||||
defence_multiplier = self.avatar.BPSkill_num('BPSkill_G')
|
||||
elif skill_type == 'Ultra':
|
||||
defence_multiplier = self.avatar.Ultra_num('Ultra_G')
|
||||
elif skill_type == 'Talent':
|
||||
defence_multiplier = self.avatar.Talent_num('Talent_G')
|
||||
|
||||
# 检查是否有护盾加成
|
||||
shield_added_ratio = merged_attr.get('shield_added_ratio', 0)
|
||||
shield_added = shield_added_ratio + 1
|
||||
logger.info(f'护盾加成: {shield_added}')
|
||||
|
||||
defence_num = (
|
||||
defence * skill_multiplier + defence_multiplier
|
||||
) * shield_added
|
||||
|
||||
skill_info_list: List[Union[str, float]] = []
|
||||
skill_info_list.append(skill_info[1])
|
||||
skill_info_list.append(defence_num)
|
||||
skill_info_list.append(defence_num)
|
||||
skill_info_list.append(defence_num)
|
||||
|
||||
return skill_info_list
|
||||
|
460
StarRailUID/starrailuid_charinfo/effect/damageCal.py
Normal file
460
StarRailUID/starrailuid_charinfo/effect/damageCal.py
Normal file
@ -0,0 +1,460 @@
|
||||
import json
|
||||
from copy import deepcopy
|
||||
from pathlib import Path
|
||||
from typing import List, Union
|
||||
|
||||
from gsuid_core.logger import logger
|
||||
|
||||
from ..mono.Character import Character
|
||||
from .Role import RoleInstance
|
||||
from .utils import merge_attribute
|
||||
|
||||
Excel_path = Path(__file__).parent
|
||||
with Path.open(Excel_path / 'Excel' / 'SkillData.json', encoding='utf-8') as f:
|
||||
skill_dict = json.load(f)
|
||||
|
||||
|
||||
class DamageCalculator:
|
||||
def __init__(self, char_data: Character):
|
||||
self.char_data = deepcopy(char_data)
|
||||
self.role = RoleInstance(self.char_data)
|
||||
|
||||
def clear(self):
|
||||
self.role = RoleInstance(self.char_data)
|
||||
self.merged_attr = None
|
||||
|
||||
def get_skill_info(self, skill_type: str):
|
||||
return self.role.avatar.Skill_Info(skill_type)
|
||||
|
||||
async def skill_calculation(self, skill_type: str):
|
||||
skill_info = self.role.avatar.Skill_Info(skill_type)
|
||||
skill_multiplier = self.role.avatar.Skill_num(skill_info[4], skill_type)
|
||||
for attr in self.role.attribute_bonus:
|
||||
if attr.__contains__('SkillAdd'):
|
||||
skill_name = attr.split('SkillAdd')[0]
|
||||
if skill_name in (skill_type, skill_info[3]):
|
||||
logger.info(
|
||||
f'{skill_name}对{skill_type}有{self.role.attribute_bonus[attr]}倍率加成'
|
||||
)
|
||||
skill_multiplier = (
|
||||
skill_multiplier + self.role.attribute_bonus[attr]
|
||||
)
|
||||
|
||||
logger.info(f'技能区总: {skill_multiplier}')
|
||||
|
||||
async def weapon_calculation(self):
|
||||
logger.info('检查武器战斗生效的buff')
|
||||
Ultra_Use = self.role.avatar.Ultra_Use()
|
||||
logger.info('Ultra_Use')
|
||||
logger.info(Ultra_Use)
|
||||
self.role.attribute_bonus = await self.role.weapon.weapon_ability(
|
||||
Ultra_Use, self.role.base_attr, self.role.attribute_bonus
|
||||
)
|
||||
logger.info(self.role.attribute_bonus)
|
||||
logger.info('检查遗器套装战斗生效的buff')
|
||||
for set_skill in self.role.relic_set.SetSkill:
|
||||
self.role.attribute_bonus = await set_skill.set_skill_ability(
|
||||
self.role.base_attr, self.role.attribute_bonus
|
||||
)
|
||||
if self.role.attribute_bonus is None:
|
||||
raise Exception('attribute_bonus is None')
|
||||
logger.info(self.role.attribute_bonus)
|
||||
|
||||
async def attribute_calculation(self, skill_type: str):
|
||||
# 检查是否有对某一个技能的属性加成
|
||||
logger.info('检查是否有对某一个技能的属性加成')
|
||||
for attr in self.role.attribute_bonus:
|
||||
# 攻击加成
|
||||
if attr.__contains__('AttackAddedRatio'):
|
||||
attr_name = attr.split('AttackAddedRatio')[0]
|
||||
if attr_name in (skill_type, self.get_skill_info(skill_type)[3]):
|
||||
attack_added_ratio = self.role.attribute_bonus.get(
|
||||
'AttackAddedRatio', 0
|
||||
)
|
||||
self.role.attribute_bonus['AttackAddedRatio'] = (
|
||||
attack_added_ratio + self.role.attribute_bonus[attr]
|
||||
)
|
||||
# 效果命中加成
|
||||
if attr.__contains__('StatusProbabilityBase'):
|
||||
attr_name = attr.split('StatusProbabilityBase')[0]
|
||||
if attr_name in (skill_type, self.get_skill_info(skill_type)[3]):
|
||||
status_probability = self.role.attribute_bonus.get(
|
||||
'StatusProbabilityBase', 0
|
||||
)
|
||||
self.role.attribute_bonus['StatusProbabilityBase'] = (
|
||||
status_probability + self.role.attribute_bonus[attr]
|
||||
)
|
||||
|
||||
self.merged_attr = await merge_attribute(
|
||||
self.role.base_attr, self.role.attribute_bonus
|
||||
)
|
||||
logger.info(f'{self.merged_attr}')
|
||||
|
||||
async def cal_attack_base_damage(self, skill_type: str):
|
||||
if isinstance(self.get_skill_info(skill_type)[2], str):
|
||||
raise TypeError('skill_info[2] is str')
|
||||
skill_multiplier = self.role.avatar.Skill_num(
|
||||
self.get_skill_info(skill_type)[4],
|
||||
skill_type
|
||||
)
|
||||
skill_multiplier = skill_multiplier / int(self.get_skill_info(skill_type)[2])
|
||||
logger.info(f'技能区单段: {skill_multiplier}')
|
||||
if self.role.raw_data.avatar.id_ == 1004:
|
||||
if self.role.raw_data.avatar.rank >= 6 and skill_type == 'BPSkill':
|
||||
self.get_skill_info(skill_type)[2] = int(self.get_skill_info(skill_type)[2]) + 1
|
||||
multiplier_add = self.role.avatar.Talent()
|
||||
skill_multiplier = skill_multiplier + multiplier_add
|
||||
|
||||
if (
|
||||
self.role.raw_data.avatar.id_ == 1201
|
||||
and self.role.raw_data.avatar.rank >= 4
|
||||
and skill_type == 'Normal'
|
||||
):
|
||||
self.get_skill_info(skill_type)[2] = int(self.get_skill_info(skill_type)[2]) + 1
|
||||
|
||||
assert(self.merged_attr is not None)
|
||||
attack = self.merged_attr.get('attack', 0)
|
||||
if self.role.raw_data.avatar.id_ == 1104:
|
||||
# 杰帕德天赋加攻
|
||||
defence = self.merged_attr['defence']
|
||||
attack = attack + (defence * 0.35)
|
||||
logger.info(f'攻击力: {attack}')
|
||||
damage_add = 0
|
||||
hp_multiplier = 0
|
||||
hp_num = 0
|
||||
if self.role.raw_data.avatar.id_ in [1205, 1208]:
|
||||
hp_num = self.merged_attr['hp']
|
||||
skill_type_hp = skill_type + '_HP'
|
||||
if skill_type_hp in skill_dict[str(self.role.raw_data.avatar.id_)]:
|
||||
hp_multiplier = self.role.avatar.Skill_num(
|
||||
self.get_skill_info(skill_type)[4], skill_type_hp
|
||||
)
|
||||
else:
|
||||
hp_multiplier = 0
|
||||
for attr in self.role.attribute_bonus:
|
||||
if attr.__contains__('HpSkillAdd'):
|
||||
skill_name = attr.split('HpSkillAdd')[0]
|
||||
if skill_name in (skill_type, self.get_skill_info(skill_type)[3]):
|
||||
logger.info(
|
||||
f'{skill_name}对{skill_type}有{self.role.attribute_bonus[attr]}倍率加成'
|
||||
)
|
||||
hp_multiplier = (
|
||||
hp_multiplier + self.role.attribute_bonus[attr]
|
||||
)
|
||||
|
||||
if skill_type == 'Talent':
|
||||
if (
|
||||
self.role.raw_data.avatar.rank >= 6
|
||||
and self.role.raw_data.avatar.id_ == 1205
|
||||
):
|
||||
damage_add = hp_num * 0.5
|
||||
attack = (skill_multiplier * attack) + (hp_multiplier * hp_num)
|
||||
skill_multiplier = 1
|
||||
logger.info(f'混伤区: {attack}')
|
||||
|
||||
logger.info(f'额外伤害: {damage_add}')
|
||||
# 模拟 同属性弱点 同等级 的怪物
|
||||
# 韧性条减伤
|
||||
enemy_damage_reduction = 0.1
|
||||
damage_reduction = 1 - enemy_damage_reduction
|
||||
logger.info(f'韧性区: {damage_reduction}')
|
||||
# 抗性区
|
||||
enemy_status_resistance = 0.0
|
||||
for attr in self.merged_attr:
|
||||
if attr.__contains__('ResistancePenetration'):
|
||||
# 检查是否有某一属性的抗性穿透
|
||||
attr_name = attr.split('ResistancePenetration')[0]
|
||||
if attr_name in (self.role.avatar.avatar_element, 'AllDamage'):
|
||||
logger.info(f'{attr_name}属性有{self.merged_attr[attr]}穿透加成')
|
||||
enemy_status_resistance += self.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,
|
||||
self.get_skill_info(skill_type)[3],
|
||||
) and skillattr_name in (
|
||||
self.role.avatar.avatar_element,
|
||||
'AllDamage',
|
||||
):
|
||||
enemy_status_resistance += self.merged_attr[attr]
|
||||
logger.info(
|
||||
f'{skill_name}对{skillattr_name}属性有{self.merged_attr[attr]}穿透加成'
|
||||
)
|
||||
resistance_area = 1.0 - (0 - enemy_status_resistance)
|
||||
logger.info(f'抗性区: {resistance_area}')
|
||||
|
||||
# 防御区
|
||||
# 检查是否有 ignore_defence
|
||||
logger.info('检查是否有 ignore_defence')
|
||||
ignore_defence = 1.0
|
||||
for attr in self.merged_attr:
|
||||
if attr == 'ignore_defence':
|
||||
ignore_defence = 1 - self.merged_attr[attr]
|
||||
break
|
||||
logger.info(f'ignore_defence {ignore_defence}')
|
||||
enemy_defence = (
|
||||
self.role.avatar.avatar_level * 10 + 200
|
||||
) * ignore_defence
|
||||
defence_multiplier = (self.role.avatar.avatar_level * 10 + 200) / (
|
||||
self.role.avatar.avatar_level * 10 + 200 + enemy_defence
|
||||
)
|
||||
logger.info(f'防御区: {defence_multiplier}')
|
||||
|
||||
# 增伤区
|
||||
# TODO: 这里计算只考虑了希儿,需要重写 injury_area = role.avatar.Talent_add()
|
||||
injury_area = self.role.avatar.Talent_add()
|
||||
# 检查是否有对某一个技能的伤害加成
|
||||
logger.info('检查是否有对某一个技能的伤害加成')
|
||||
for attr in self.merged_attr:
|
||||
if attr.__contains__('DmgAdd'):
|
||||
attr_name = attr.split('DmgAdd')[0]
|
||||
if attr_name in (skill_type, self.get_skill_info(skill_type)[3]):
|
||||
logger.info(
|
||||
f'{attr} 对 {skill_type} 有 {self.merged_attr[attr]} 伤害加成'
|
||||
)
|
||||
injury_area += self.merged_attr[attr]
|
||||
# 检查有无符合属性的伤害加成
|
||||
logger.info('检查球有无符合属性的伤害加成')
|
||||
element_area = 0
|
||||
for attr in self.merged_attr:
|
||||
if attr.__contains__('AddedRatio'):
|
||||
attr_name = attr.split('AddedRatio')[0]
|
||||
if attr_name in (self.role.avatar.avatar_element, 'AllDamage'):
|
||||
logger.info(
|
||||
f'{attr} 对 {self.role.avatar.avatar_element} '
|
||||
f'有 {self.merged_attr[attr]} 伤害加成'
|
||||
)
|
||||
if attr_name == self.role.avatar.avatar_element:
|
||||
element_area += self.merged_attr[attr]
|
||||
injury_area += self.merged_attr[attr]
|
||||
injury_area += 1
|
||||
logger.info(f'增伤区: {injury_area}')
|
||||
|
||||
# 易伤区
|
||||
logger.info('检查是否有易伤加成')
|
||||
damage_ratio = self.merged_attr.get('DmgRatio', 0)
|
||||
# 检查是否有对特定技能的易伤加成
|
||||
# Talent_DmgRatio
|
||||
for attr in self.merged_attr:
|
||||
if attr.__contains__('_DmgRatio'):
|
||||
skill_name = attr.split('_')[0]
|
||||
if skill_name in (skill_type, self.get_skill_info(skill_type)[3]):
|
||||
logger.info(
|
||||
f'{attr} 对 {skill_type} 有 {self.merged_attr[attr]} 易伤加成'
|
||||
)
|
||||
damage_ratio += self.merged_attr[attr]
|
||||
damage_ratio = damage_ratio + 1
|
||||
logger.info(f'易伤: {damage_ratio}')
|
||||
|
||||
# 爆伤区
|
||||
if skill_type == 'DOT':
|
||||
critical_damage_base = 0.0
|
||||
else:
|
||||
logger.info('检查是否有爆伤加成')
|
||||
logger.info(f'{self.merged_attr}')
|
||||
critical_damage_base = self.merged_attr.get('CriticalDamageBase', 0)
|
||||
# 检查是否有对特定技能的爆伤加成
|
||||
# Ultra_CriticalChance
|
||||
for attr in self.merged_attr:
|
||||
if attr.__contains__('_CriticalDamageBase'):
|
||||
skill_name = attr.split('_')[0]
|
||||
if skill_name in (skill_type, self.get_skill_info(skill_type)[3]):
|
||||
logger.info(
|
||||
f'{attr} 对 {skill_type} 有 '
|
||||
f'{self.merged_attr[attr]} 爆伤加成'
|
||||
)
|
||||
critical_damage_base += self.merged_attr[attr]
|
||||
critical_damage = critical_damage_base + 1
|
||||
logger.info(f'暴伤: {critical_damage}')
|
||||
|
||||
# 暴击区
|
||||
logger.info('检查是否有暴击加成')
|
||||
critical_chance_base = self.merged_attr['CriticalChanceBase']
|
||||
# 检查是否有对特定技能的爆伤加成
|
||||
# Ultra_CriticalChance
|
||||
for attr in self.merged_attr:
|
||||
if attr.__contains__('_CriticalChance'):
|
||||
skill_name = attr.split('_')[0]
|
||||
if skill_name in (skill_type, self.get_skill_info(skill_type)[3]):
|
||||
logger.info(
|
||||
f'{attr} 对 {skill_type} 有 '
|
||||
f'{self.merged_attr[attr]} 暴击加成'
|
||||
)
|
||||
critical_chance_base += self.merged_attr[attr]
|
||||
critical_chance_base = min(1, critical_chance_base)
|
||||
logger.info(f'暴击: {critical_chance_base}')
|
||||
|
||||
# 期望伤害
|
||||
qiwang_damage = (critical_chance_base * critical_damage_base) + 1
|
||||
logger.info(f'暴击期望: {qiwang_damage}')
|
||||
damage_cd_z = 0.0
|
||||
damage_qw_z = 0.0
|
||||
damage_tz_z = 0.0
|
||||
attack_tz = 0.0
|
||||
injury_add = 0.0
|
||||
critical_damage_add = 0
|
||||
for i in range(1, int(self.get_skill_info(skill_type)[2]) + 1):
|
||||
injury_add = 0
|
||||
critical_damage_add = 0
|
||||
if self.role.raw_data.avatar.id_ == 1213:
|
||||
injury_add = self.role.avatar.Talent()
|
||||
critical_damage_add = self.role.avatar.BPSkill()
|
||||
normal_buff = self.merged_attr.get('Normal_buff', 0)
|
||||
if i >= 4:
|
||||
normal_buff = min(4, int(normal_buff + (i - 3)))
|
||||
if normal_buff >= 1:
|
||||
critical_damage_add = normal_buff * critical_damage_add
|
||||
atk_buff = self.merged_attr.get('Atk_buff', 0)
|
||||
atk_buff = min(10, int((i - 1) * (atk_buff + 1)))
|
||||
injury_add = atk_buff * injury_add
|
||||
qiwang_damage = (
|
||||
critical_chance_base
|
||||
* (critical_damage_base + critical_damage_add)
|
||||
) + 1
|
||||
|
||||
damage_cd = (
|
||||
attack
|
||||
* skill_multiplier
|
||||
* damage_ratio
|
||||
* (injury_area + injury_add)
|
||||
* defence_multiplier
|
||||
* resistance_area
|
||||
* damage_reduction
|
||||
* (critical_damage + critical_damage_add)
|
||||
+ damage_add
|
||||
)
|
||||
damage_cd_z += damage_cd
|
||||
damage_qw = (
|
||||
attack
|
||||
* skill_multiplier
|
||||
* damage_ratio
|
||||
* (injury_area + injury_add)
|
||||
* defence_multiplier
|
||||
* resistance_area
|
||||
* damage_reduction
|
||||
* qiwang_damage
|
||||
+ damage_add
|
||||
)
|
||||
damage_qw_z += damage_qw
|
||||
|
||||
attr_value_tz: float = self.role.base_attr.get('attack', 0)
|
||||
attribute_atk = self.role.attribute_bonus.get('AttackDelta', 0)
|
||||
attack_tz = (
|
||||
attr_value_tz
|
||||
+ attr_value_tz
|
||||
* (
|
||||
1
|
||||
+ self.role.attribute_bonus.get('AttackAddedRatio', 0)
|
||||
+ 2.144
|
||||
)
|
||||
+ attribute_atk
|
||||
)
|
||||
if self.role.raw_data.avatar.id_ in [1205, 1208]:
|
||||
attack_tz = (skill_multiplier * attack_tz) + (
|
||||
hp_multiplier * hp_num
|
||||
)
|
||||
injury_add_tz = 0
|
||||
if self.role.avatar.avatar_element == 'Imaginary':
|
||||
injury_add_tz = 0.12
|
||||
damage_tz = (
|
||||
attack_tz
|
||||
* skill_multiplier
|
||||
* damage_ratio
|
||||
* (injury_area + injury_add + injury_add_tz + 2.326)
|
||||
* defence_multiplier
|
||||
* resistance_area
|
||||
* damage_reduction
|
||||
* (critical_damage + critical_damage_add + 1.594)
|
||||
* 10
|
||||
+ damage_add
|
||||
)
|
||||
|
||||
damage_tz_z += damage_tz
|
||||
|
||||
if (
|
||||
self.role.raw_data.avatar.id_ == 1003
|
||||
and self.role.raw_data.avatar.rank >= 6
|
||||
):
|
||||
damage_cd_z = damage_cd_z * 1.8
|
||||
damage_qw_z = damage_qw_z * 1.8
|
||||
damage_tz_z = damage_tz_z * 1.8
|
||||
|
||||
if self.role.avatar.avatar_element == 'Thunder':
|
||||
element_area = 0
|
||||
damage_tz_fj = (
|
||||
attack_tz
|
||||
* 0.44
|
||||
* damage_ratio
|
||||
* (injury_area + injury_add + 2.326 + element_area)
|
||||
* defence_multiplier
|
||||
* resistance_area
|
||||
* damage_reduction
|
||||
* (critical_damage + critical_damage_add + 1.594)
|
||||
* 10
|
||||
)
|
||||
damage_tz_z += damage_tz_fj
|
||||
skill_info_list: List[Union[str, float]] = []
|
||||
skill_info_list.append(self.get_skill_info(skill_type)[1])
|
||||
skill_info_list.append(damage_cd_z)
|
||||
skill_info_list.append(damage_qw_z)
|
||||
skill_info_list.append(damage_tz_z)
|
||||
logger.info(
|
||||
f'{self.get_skill_info(skill_type)[1]} 暴击伤害: {damage_cd_z} 期望伤害{damage_qw_z}'
|
||||
)
|
||||
return skill_info_list
|
||||
|
||||
async def cal_defense_base_damage(self, skill_type: str):
|
||||
###########################################
|
||||
###########################################
|
||||
# 这里我直接cv的, 记得改 #
|
||||
###########################################
|
||||
###########################################
|
||||
assert(self.merged_attr is not None)
|
||||
defence = self.merged_attr['defence']
|
||||
logger.info(f'防御力: {defence}')
|
||||
defence_multiplier = 0
|
||||
|
||||
# 获取技能提供的固定护盾值
|
||||
if skill_type == 'Normal':
|
||||
defence_multiplier = self.role.avatar.Normalnum('Normal_G')
|
||||
elif skill_type == 'BPSkill':
|
||||
defence_multiplier = self.role.avatar.BPSkill_num('BPSkill_G')
|
||||
elif skill_type == 'Ultra':
|
||||
defence_multiplier = self.role.avatar.Ultra_num('Ultra_G')
|
||||
elif skill_type == 'Talent':
|
||||
defence_multiplier = self.role.avatar.Talent_num('Talent_G')
|
||||
|
||||
# 检查是否有护盾加成
|
||||
shield_added_ratio = self.merged_attr.get('shield_added_ratio', 0)
|
||||
shield_added = shield_added_ratio + 1
|
||||
logger.info(f'护盾加成: {shield_added}')
|
||||
|
||||
skill_multiplier = self.role.avatar.Skill_num(
|
||||
self.get_skill_info(skill_type)[4],
|
||||
skill_type
|
||||
)
|
||||
skill_multiplier = skill_multiplier / int(self.get_skill_info(skill_type)[2])
|
||||
|
||||
defence_num = (
|
||||
defence * skill_multiplier + defence_multiplier
|
||||
) * shield_added
|
||||
|
||||
skill_info_list: List[Union[str, float]] = []
|
||||
skill_info_list.append(self.get_skill_info(skill_type)[1])
|
||||
skill_info_list.append(defence_num)
|
||||
skill_info_list.append(defence_num)
|
||||
skill_info_list.append(defence_num)
|
||||
|
||||
async def cal_heal_base_damage(self):
|
||||
pass
|
||||
|
||||
async def cal_damage(self, skill_type: str):
|
||||
await self.skill_calculation(skill_type)
|
||||
await self.weapon_calculation()
|
||||
await self.attribute_calculation(skill_type)
|
||||
skill_info_list = await self.cal_attack_base_damage(skill_type)
|
||||
self.clear()
|
||||
|
||||
return skill_info_list
|
Loading…
x
Reference in New Issue
Block a user