ysd新增查看钟离、胡桃、雷电将军伤害计算

This commit is contained in:
CMHopeSunshine 2022-06-30 19:35:07 +08:00
parent addb044064
commit 4a89541387
14 changed files with 22099 additions and 25 deletions

View File

@ -37,7 +37,7 @@ __plugin_meta__ = PluginMetadata(
sim_gacha = on_regex(r'^抽((?P<num>\d+)|(?:.*))十连(?P<pool>.*?)$', priority=5, block=True)
sim_gacha.__paimon_help__ = {
"usage": "抽[数量]十连[卡池]",
"introduce": "模拟抽卡池有角色1|角色2|武器|常驻|菜单",
"introduce": "模拟抽卡池有角色1|角色2|武器|常驻|彩蛋",
"priority": 1
}

View File

@ -0,0 +1,304 @@
from utils.enka_util import get_artifact_suit
def attribute(base_attribute: float, increase_attribute: float = 0, fixed_attribute: float = 0):
"""
计算属性
:param base_attribute: 基础属性
:param increase_attribute: 百分比增加系数
:param fixed_attribute: 固定增加系数
:return: 最终属性
"""
return base_attribute * (1 + increase_attribute) + fixed_attribute
def resistance_coefficient(base_resistance: float = 0.1, reduction_rate: float = 0):
"""
计算抗性系数
:param base_resistance: 怪物基础抗性
:param reduction_rate: 减抗系数
:return: 抗性系数
"""
resistance = base_resistance - reduction_rate
if resistance > 0.75:
return 1 / (1 + 4 * resistance)
elif 0 <= resistance < 0.75:
return 1 - resistance
else:
return 1 - (resistance / 2)
def defense_coefficient(self_level: int, enemy_level: int = 90, reduction_rate: float = 0, ignore: float = 0):
"""
计算防御力系数
:param self_level: 角色自身等级
:param enemy_level: 怪物等级
:param reduction_rate: 减防系数
:param ignore: 无视防御系数
:return: 防御力系数
"""
return (self_level + 100) / ((self_level + 100) + (enemy_level + 100) * (1 - reduction_rate) * (1 - ignore))
def growth_reaction(mastery: int = 0, base_coefficient: float = 1.5, extra_coefficient: float = 0):
"""
计算增幅反应的系数
:param mastery: 元素精通
:param base_coefficient: 基础系数如蒸发为1.5 融化为2
:param extra_coefficient: 反应系数提高如魔女4件套效果
:return: 增幅系数
"""
mastery_increase = (2.78 * mastery) / (mastery + 1400)
return base_coefficient * (1 + mastery_increase + extra_coefficient)
def upheaval_reaction(level: int, type: str, mastery: int = 0, extra_coefficient: float = 0, resistance: float = 0.9):
"""
计算剧变反应的伤害
:param level: 等级
:param type: 反应类型
:param mastery: 元素精通
:param extra_coefficient: 反应系数提高如如雷4件套效果
:param resistance: 怪物抗性系数
:return: 剧变伤害
"""
if type == '超导':
base_ratio = 1
elif type == '扩散':
base_ratio = 1.2
elif type == '碎冰':
base_ratio = 3
elif type == '超载':
base_ratio = 4
else:
base_ratio = 4.8
base_coefficient = 723 # 暂缺全等级剧变反应的系数先写90级的
mastery_increase = (16 * mastery) / (mastery + 2000)
return base_coefficient * base_ratio * (1 + mastery_increase + extra_coefficient) * resistance
def polearm_common_fix(data: dict):
"""
对长柄武器角色的通用面板属性修正
:param data: 角色数据
:return: 角色数据
"""
attr = data['属性']
weapon = data['武器']
if weapon['名称'] == '护摩之杖':
attr['额外攻击'] += (attr['基础生命'] + attr['额外生命']) * (0.008 + 0.002 * weapon['精炼等级'])
if '半血以下' not in data['伤害描述']:
data['伤害描述'].append('半血以下')
elif weapon['名称'] == '和璞鸢':
attr['额外攻击'] += attr['基础攻击'] * 7 * (0.025 + 0.007 * weapon['精炼等级'])
for i, k in enumerate(attr['伤害加成']):
attr['伤害加成'][i] = k + (0.09 + 0.03 * weapon['精炼等级'])
data['伤害描述'].append('和璞鸢满层')
elif weapon['名称'] == '贯虹之槊':
attr['额外攻击'] += attr['基础攻击'] * 2 * 5 * (0.003 + 0.001 * weapon['精炼等级'])
attr['护盾强效'] += 0.15 + 0.05 * weapon['精炼等级']
data['伤害描述'].append('贯虹带盾满层')
elif weapon['名称'] == '决斗之枪':
attr['额外攻击'] += attr['基础攻击'] * 0.18 + 0.06 * weapon['精炼等级']
data['伤害描述'].append('决斗单怪')
elif weapon['名称'] == '息灾':
for i, k in enumerate(attr['伤害加成']):
attr['伤害加成'][i] = k + (0.09 + 0.03 * weapon['精炼等级'])
attr['额外攻击'] += attr['基础攻击'] * 6 * (0.024 + 0.006 * weapon['精炼等级'])
data['伤害描述'].append('息灾前台满层')
elif weapon['名称'] == '薙草之稻光':
attr['额外攻击'] += attr['基础攻击'] * (attr['元素充能效率'] - 1) * (0.21 + 0.07 * weapon['精炼等级'])
attr['元素充能效率'] += 0.25 + 0.05 * weapon['精炼等级']
elif weapon['名称'] == '天空之脊':
attr['暴击率'] += (0.06 + 0.02 * weapon['精炼等级'])
elif weapon['名称'] == '千岩长枪':
attr['暴击率'] += (0.02 + 0.01 * weapon['精炼等级'])
attr['额外攻击'] += attr['基础攻击'] * (0.06 + 0.01 * weapon['精炼等级'])
data['伤害描述'].append('璃月人1层')
elif weapon['名称'] == '匣里灭辰':
for i, k in enumerate(attr['伤害加成']):
attr['伤害加成'][i] = k + (0.16 + 0.04 * weapon['精炼等级'])
data['伤害描述'].append('灭辰触发')
elif weapon['名称'] == '黑岩刺枪':
attr['额外攻击'] += attr['基础攻击'] * (0.09 + 0.03 * weapon['精炼等级'])
data['伤害描述'].append('黑岩1层')
data['属性'] = attr
return data
def attr_common_fix(data: dict):
"""
对武器圣遗物的通用面板属性修正
:param data: 角色数据
:return: 角色数据
"""
if '伤害描述' not in data:
data['伤害描述'] = []
if '护盾强效' not in data['属性']:
data['属性']['护盾强效'] = 0
if data['武器']['类型'] == '长柄武器':
data = polearm_common_fix(data)
artifacts = data['圣遗物']
attr = data['属性']
suit = get_artifact_suit(artifacts)
# 两件套的情况
if '逆飞的流星' in suit:
attr['护盾强效'] += 0.35
if len(suit) == 2:
# 四件套的情况
if suit[0][0] == suit[1][0]:
if suit[0][0] == '苍白之火':
attr['额外攻击'] += attr['基础攻击'] * 0.18
attr['伤害加成'][0] += 0.25
data['伤害描述'].append('苍白满层')
elif suit[0][0] == '华馆梦醒形骸记':
attr['伤害加成'][6] += 0.24
attr['额外防御'] += attr['基础防御'] * 0.24
data['伤害描述'].append('华馆满层')
elif suit[0][0] == '千岩牢固':
attr['护盾强效'] += 0.3
attr['额外攻击'] += attr['基础攻击'] * 0.2
data['伤害描述'].append('千岩触发')
elif suit[0][0] == '昔日宗室之仪':
attr['额外攻击'] += attr['基础攻击'] * 0.2
data['伤害描述'].append('宗室触发')
elif suit[0][0] == '冰风迷途的勇士':
attr['暴击率'] += 0.4
data['伤害描述'].append('冰套暴击40%')
elif suit[0][0] == '勇士之心':
for i, k in enumerate(attr['伤害加成']):
attr['伤害加成'][i] = k + 0.3
data['伤害描述'].append('勇士触发')
elif suit[0][0] == '教官':
attr['元素精通'] += 120
data['伤害描述'].append('教官触发')
elif suit[0][0] == '炽烈的炎之魔女':
if data['名称'] in ['胡桃', '宵宫']:
attr['伤害加成'][1] += 0.075
data['伤害描述'].append('魔女1层')
else:
attr['伤害加成'][1] += 0.225
data['伤害描述'].append('魔女满层')
attr['蒸发系数'] = 0.15
elif suit[0][0] == '渡过烈火的贤人':
for i, k in enumerate(attr['伤害加成']):
attr['伤害加成'][i] = k + 0.5
data['伤害描述'].append('渡火触发')
elif suit[0][0] == '平息鸣雷的尊者':
for i, k in enumerate(attr['伤害加成']):
attr['伤害加成'][i] = k + 0.5
data['伤害描述'].append('平雷触发')
elif suit[0][0] == '战狂':
attr['暴击率'] += 0.24
data['伤害描述'].append('战狂触发')
elif suit[0][0] == '辰砂往生录':
attr['额外攻击'] += attr['基础攻击'] * 0.48
data['伤害描述'].append('辰砂满层')
elif suit[0][0] == '被怜爱的少女':
attr['受治疗加成'] += 0.2
data['属性'] = attr
return data
def q_fix(data: dict):
# 武器
attr = data['属性']
extra_value = {
'暴击率': 0,
'增伤': 0
}
weapon = data['武器']
if weapon['名称'] == '「渔获」':
extra_value['增伤'] += 0.12 + 0.04 * weapon['精炼等级']
extra_value['暴击率'] += 0.045 + 0.015 * weapon['精炼等级']
if weapon['名称'] == '断浪长鳍':
extra_value['增伤'] += (0.0009 + 0.0003 * weapon['精炼等级']) * 240
data['伤害描述'].append('断浪算240能量')
# 圣遗物
artifacts = data['圣遗物']
suit = get_artifact_suit(artifacts)
# 两件套的情况
if '昔日宗室之仪' in suit:
extra_value['增伤'] += 0.2
if len(suit) == 2:
# 四件套的情况
if suit[0][0] == suit[1][0]:
if suit[0][0] == '绝缘之旗印':
extra_value['增伤'] += 0.25 * attr['元素充能效率']
return data, extra_value
def e_fix(data: dict):
# 武器
attr = data['属性']
extra_value = {
'暴击率': 0,
'增伤': 0
}
# 圣遗物
artifacts = data['圣遗物']
suit = get_artifact_suit(artifacts)
# 两件套的情况
if '赌徒' in suit:
extra_value['增伤'] += 0.2
return data, extra_value
def a_fix(data: dict):
# 武器
attr = data['属性']
extra_value = {
'普攻暴击率': 0,
'普攻增伤': 0,
'重击暴击率': 0,
'重击增伤': 0,
'下落攻击暴击率': 0,
'下落攻击增伤': 0
}
weapon = data['武器']
if weapon['名称'] == '白缨枪':
extra_value['普攻增伤'] += 0.18 + 0.06 * weapon['精炼等级']
# 圣遗物
artifacts = data['圣遗物']
suit = get_artifact_suit(artifacts)
# # 两件套的情况
if '武人' in suit:
extra_value['普攻增伤'] += 0.15
extra_value['重击增伤'] += 0.15
if len(suit) == 2:
# 四件套的情况
if suit[0][0] == suit[1][0]:
if suit[0][0] == '追忆之注连':
extra_value['普攻增伤'] += 0.5
extra_value['重击增伤'] += 0.5
extra_value['下落攻击增伤'] += 0.5
data['伤害描述'].append('追忆触发')
elif suit[0][0] == '流浪大地的乐团':
if weapon['类型'] in ['法器', '弓箭']:
extra_value['重击增伤'] += 0.35
elif suit[0][0] == '角斗士的终幕礼':
if weapon['类型'] in ['单手剑', '双手剑', '长柄武器']:
extra_value['普攻增伤'] += 0.35
elif suit[0][0] == '染血的骑士道':
extra_value['重击增伤'] += 0.5
data['伤害描述'].append('染血触发')
elif suit[0][0] == '沉沦之心':
extra_value['普攻增伤'] += 0.3
extra_value['重击增伤'] += 0.3
data['伤害描述'].append('沉沦触发')
elif suit[0][0] == '逆飞的流星':
extra_value['普攻增伤'] += 0.4
extra_value['重击增伤'] += 0.4
data['伤害描述'].append('流星触发')
elif suit[0][0] == '武人':
extra_value['普攻增伤'] += 0.25
extra_value['重击增伤'] += 0.25
data['伤害描述'].append('武人触发')
elif suit[0][0] == '行者之心':
extra_value['重击暴击率'] += 0.3
return data, extra_value

View File

@ -0,0 +1,17 @@
from .zhongli import draw_zhongli_dmg
from .hutao import draw_hutao_dmg
from .leishen import draw_leishen_dmg
# 支持的角色列表
roles_list = {
'钟离': draw_zhongli_dmg,
'胡桃': draw_hutao_dmg,
'雷电将军': draw_leishen_dmg
}
def get_role_dmg(role_name: str, data: dict):
if role_name in roles_list:
return roles_list[role_name](data)
else:
return None

View File

@ -0,0 +1,145 @@
from copy import deepcopy
from pathlib import Path
from typing import Tuple
from PIL import Image, ImageDraw
from utils.PIL_util import get_font, draw_center_text
from utils.file_handler import load_json, load_image
from .common import resistance_coefficient as rc, defense_coefficient as dc, attr_common_fix, q_fix, e_fix, a_fix, \
growth_reaction
mask_top = load_image(path=Path(__file__).parent.parent.parent / 'res' / 'player_card2' / '遮罩top.png')
mask_body = load_image(path=Path(__file__).parent.parent.parent / 'res' / 'player_card2' / '遮罩body.png')
mask_bottom = load_image(path=Path(__file__).parent.parent.parent / 'res' / 'player_card2' / '遮罩bottom.png')
skill_data = load_json(path=Path(__file__).parent.parent.parent / 'utils' / 'json' / 'roles_data.json')['胡桃']['skill']
def cal_e_attack(data: dict):
"""
计算胡桃开E后的攻击力和半血后的增伤
:param data: 角色数据
:return: 角色数据
"""
health = data['属性']['基础生命'] + data['属性']['额外生命']
skill_level = data['天赋'][1]['等级'] - 1
percent_value = float(skill_data['蝶引来生']['数值']['攻击力提高'][skill_level].replace('%生命值上限', '')) / 100.0
data['属性']['额外攻击'] += health * percent_value
if data['等级'] >= 70:
data['属性']['伤害加成'][1] += 0.33
return data
def cal_single_attack_dmg(data: dict, extra: dict) -> Tuple[float, float]:
"""
计算胡桃裸重击的伤害
:param data: 角色数据
:param extra: 针对重击的额外数值
:return: 期望伤害和暴击后伤害
"""
role_level = data['等级']
skill_level = data['天赋'][0]['等级'] - 1
attack = data['属性']['基础攻击'] + data['属性']['额外攻击']
cr = data['属性']['暴击率'] + extra['重击暴击率']
cd = data['属性']['暴击伤害']
dmg_bonus = 1 + data['属性']['伤害加成'][1] + extra['重击增伤']
percent_value = float(skill_data['普通攻击·往生秘传枪法']['数值']['重击伤害'][skill_level].replace('%', '')) / 100.0
damage = (attack * percent_value) * (1 + cr * cd) * dmg_bonus * rc() * dc(role_level)
return damage, damage / (1 + cr * cd) * (1 + cd)
def cal_e_dmg(data: dict, extra: dict) -> Tuple[float, float]:
"""
计算胡桃裸雪梅香的伤害
:param data: 角色数据
:param extra: 针对元素战技的额外数值
:return: 期望伤害和暴击后伤害
"""
role_level = data['等级']
skill_level = data['天赋'][1]['等级'] - 1
attack = data['属性']['基础攻击'] + data['属性']['额外攻击']
cr = data['属性']['暴击率'] + extra['暴击率']
cd = data['属性']['暴击伤害']
dmg_bonus = 1 + data['属性']['伤害加成'][1] + extra['增伤']
hp_dmg = 0.1 * (data['属性']['基础生命'] + data['属性']['额外生命']) if len(data['命座']) >= 2 else 0
percent_value = float(skill_data['蝶引来生']['数值']['血梅香伤害'][skill_level].replace('%', '')) / 100.0
damage = (attack * percent_value + hp_dmg) * (1 + cr * cd) * dmg_bonus * rc() * dc(role_level)
return damage, damage / (1 + cr * cd) * (1 + cd)
def cal_q_dmg(data: dict, extra: dict) -> Tuple[float, float]:
"""
计算胡桃裸大招的伤害
:param data: 角色数据
:param extra: 针对大招的额外数值
:return: 期望伤害和暴击后伤害
"""
role_level = data['等级']
skill_level = data['天赋'][2]['等级'] - 1
attack = data['属性']['基础攻击'] + data['属性']['额外攻击']
cr = data['属性']['暴击率'] + extra['暴击率']
cd = data['属性']['暴击伤害']
dmg_bonus = 1 + data['属性']['伤害加成'][1] + extra['增伤']
percent_value = float(skill_data['安神秘法']['数值']['低血量时技能伤害'][skill_level].replace('%', '')) / 100.0
damage = (attack * percent_value) * (1 + cr * cd) * dmg_bonus * rc() * dc(role_level)
return damage, damage / (1 + cr * cd) * (1 + cd)
def draw_hutao_dmg(data: dict):
data = deepcopy(data)
height = 5 * 60 - 20
data['伤害描述'] = ['半血以下']
data = attr_common_fix(data)
data = cal_e_attack(data)
data, q_value = q_fix(data)
data, e_value = e_fix(data)
data, a_value = a_fix(data)
# 蒸发系数
if '蒸发系数' in data['属性']:
zf = growth_reaction(data['属性']['元素精通'], 1.5, 0.15)
else:
zf = growth_reaction(data['属性']['元素精通'], 1.5)
bg = Image.new('RGBA', (948, height + 80), (0, 0, 0, 0))
bg.alpha_composite(mask_top, (0, 0))
bg.alpha_composite(mask_body.resize((948, height)), (0, 60))
bg.alpha_composite(mask_bottom, (0, height + 60))
bg_draw = ImageDraw.Draw(bg)
# 画线
bg_draw.line((250, 0, 250, 948), (255, 255, 255, 75), 2)
bg_draw.line((599, 0, 599, 300), (255, 255, 255, 75), 2)
bg_draw.line((0, 60, 948, 60), (255, 255, 255, 75), 2)
bg_draw.line((0, 120, 948, 120), (255, 255, 255, 75), 2)
bg_draw.line((0, 180, 948, 180), (255, 255, 255, 75), 2)
bg_draw.line((0, 240, 948, 240), (255, 255, 255, 75), 2)
bg_draw.line((0, 300, 948, 300), (255, 255, 255, 75), 2)
# 顶栏
draw_center_text(bg_draw, '伤害计算', 0, 250, 11, 'white', get_font(30))
draw_center_text(bg_draw, '期望伤害', 250, 599, 11, 'white', get_font(30))
draw_center_text(bg_draw, '暴击伤害', 599, 948, 11, 'white', get_font(30))
# 裸重击
draw_center_text(bg_draw, '裸重击', 0, 250, 73, 'white', get_font(30))
expect_dmg, crit_dmg = cal_single_attack_dmg(data, a_value)
draw_center_text(bg_draw, str(int(expect_dmg)), 250, 599, 76, 'white', get_font(30, 'number.ttf'))
draw_center_text(bg_draw, str(int(crit_dmg)), 599, 948, 76, 'white', get_font(30, 'number.ttf'))
# 重击蒸发
draw_center_text(bg_draw, '重击蒸发', 0, 250, 133, 'white', get_font(30))
draw_center_text(bg_draw, str(int(expect_dmg * zf)), 250, 599, 136, 'white', get_font(30, 'number.ttf'))
draw_center_text(bg_draw, str(int(crit_dmg * zf)), 599, 948, 136, 'white', get_font(30, 'number.ttf'))
# 大招蒸发
draw_center_text(bg_draw, '大招蒸发', 0, 250, 193, 'white', get_font(30))
expect_dmg, crit_dmg = cal_q_dmg(data, q_value)
draw_center_text(bg_draw, str(int(expect_dmg * zf)), 250, 599, 196, 'white', get_font(30, 'number.ttf'))
draw_center_text(bg_draw, str(int(crit_dmg * zf)), 599, 948, 196, 'white', get_font(30, 'number.ttf'))
# 雪梅香蒸发
draw_center_text(bg_draw, '雪梅香蒸发', 0, 250, 253, 'white', get_font(30))
expect_dmg, crit_dmg = cal_e_dmg(data, e_value)
draw_center_text(bg_draw, str(int(expect_dmg * zf)), 250, 599, 256, 'white', get_font(30, 'number.ttf'))
draw_center_text(bg_draw, str(int(crit_dmg * zf)), 599, 948, 256, 'white', get_font(30, 'number.ttf'))
# 额外说明
draw_center_text(bg_draw, '额外说明', 0, 250, 313, 'white', get_font(30))
draw_center_text(bg_draw, ''.join(data['伤害描述']), 250, 948, 313, 'white', get_font(30))
return bg

View File

@ -0,0 +1,164 @@
from copy import deepcopy
from pathlib import Path
from typing import Tuple
from PIL import Image, ImageDraw
from utils.PIL_util import get_font, draw_center_text
from utils.file_handler import load_json, load_image
from .common import resistance_coefficient as rc, defense_coefficient as dc, attr_common_fix, q_fix, e_fix, a_fix
mask_top = load_image(path=Path(__file__).parent.parent.parent / 'res' / 'player_card2' / '遮罩top.png')
mask_body = load_image(path=Path(__file__).parent.parent.parent / 'res' / 'player_card2' / '遮罩body.png')
mask_bottom = load_image(path=Path(__file__).parent.parent.parent / 'res' / 'player_card2' / '遮罩bottom.png')
skill_data = load_json(path=Path(__file__).parent.parent.parent / 'utils' / 'json' / 'roles_data.json')['雷电将军']['skill']
def cal_e_dmg(data: dict, extra: dict) -> Tuple[float, float]:
"""
计算雷神单次E的伤害
:param data: 角色数据
:param extra: 针对元素战技的额外数值
:return: 期望伤害和暴击后伤害
"""
role_level = data['等级']
skill_level = data['天赋'][1]['等级'] - 1
attack = data['属性']['基础攻击'] + data['属性']['额外攻击']
cr = data['属性']['暴击率'] + extra['暴击率']
cd = data['属性']['暴击伤害']
if len(data['命座']) < 2:
defense = dc(role_level)
else:
defense = dc(role_level, ignore=0.6)
dmg_bonus = 1 + data['属性']['伤害加成'][2] + extra['增伤']
percent_value = float(skill_data['神变·恶曜开眼']['数值']['协同攻击伤害'][skill_level].replace('%', '')) / 100.0
damage = (attack * percent_value) * (1 + cr * cd) * dmg_bonus * rc() * defense
return damage, damage / (1 + cr * cd) * (1 + cd)
def cal_q_dmg(data: dict, extra: dict, num: int) -> Tuple[float, float]:
"""
计算雷神梦想一刀的伤害
:param data: 角色数据
:param extra: 针对大招的额外数值
:param num: 愿力层数
:return: 期望伤害和暴击后伤害
"""
role_level = data['等级']
skill_level = data['天赋'][2]['等级'] - 1
e_skill_level = data['天赋'][1]['等级'] - 1
e_bonus = float(
skill_data['神变·恶曜开眼']['数值']['元素爆发伤害提高'][e_skill_level].replace('每点元素能量', '').replace('%', '')) / 100.0 * 90
attack = data['属性']['基础攻击'] + data['属性']['额外攻击']
cr = data['属性']['暴击率'] + extra['暴击率']
cd = data['属性']['暴击伤害']
if len(data['命座']) < 2:
defense = dc(role_level)
else:
defense = dc(role_level, ignore=0.6)
dmg_bonus = 1 + data['属性']['伤害加成'][2] + extra['增伤'] + e_bonus
percent_value = float(skill_data['奥义·梦想真说']['数值']['梦想一刀基础伤害'][skill_level].replace('%', '')) / 100.0
num_value = float(skill_data['奥义·梦想真说']['数值']['愿力加成'][skill_level].split('%/')[0].replace('每层', '')) / 100.0 * num
damage = (attack * (percent_value + num_value)) * (1 + cr * cd) * dmg_bonus * rc() * defense
return damage, damage / (1 + cr * cd) * (1 + cd)
def cal_q_a_dmg(data: dict, extra: dict, num: int) -> Tuple[Tuple[float, float], Tuple[float, float]]:
"""
计算雷神梦想一心重击的伤害
:param data: 角色数据
:param extra: 针对大招的额外数值
:param num: 愿力层数
:return: 期望伤害和暴击后伤害
"""
role_level = data['等级']
skill_level = data['天赋'][2]['等级'] - 1
e_skill_level = data['天赋'][1]['等级'] - 1
e_bonus = float(
skill_data['神变·恶曜开眼']['数值']['元素爆发伤害提高'][e_skill_level].replace('每点元素能量', '').replace('%', '')) / 100.0 * 90
attack = data['属性']['基础攻击'] + data['属性']['额外攻击']
cr = data['属性']['暴击率'] + extra['暴击率']
cd = data['属性']['暴击伤害']
if len(data['命座']) < 2:
defense = dc(role_level)
else:
defense = dc(role_level, ignore=0.6)
dmg_bonus = 1 + data['属性']['伤害加成'][2] + extra['增伤'] + e_bonus
percent_value = skill_data['奥义·梦想真说']['数值']['重击伤害'][skill_level].split('+')
percent_value1 = float(percent_value[0].replace('%', '')) / 100.0
percent_value2 = float(percent_value[1].replace('%', '')) / 100.0
num_value = float(skill_data['奥义·梦想真说']['数值']['愿力加成'][skill_level].split('%/')[1].replace('%攻击力', '')) / 100.0 * num
damage1 = (attack * (percent_value1 + num_value)) * (1 + cr * cd) * dmg_bonus * rc() * defense
damage2 = (attack * (percent_value2 + num_value)) * (1 + cr * cd) * dmg_bonus * rc() * defense
return (damage1, damage1 / (1 + cr * cd) * (1 + cd)), (damage2, damage2 / (1 + cr * cd) * (1 + cd))
def cal_q_energy(data: dict) -> float:
"""
计算雷神大招的能量回复
:param data: 角色数据
:return: 能量回复
"""
role_level = data['等级']
if role_level >= 70:
extra_energy = (data['属性']['元素充能效率'] - 1) * 0.6
else:
extra_energy = 0
skill_level = data['天赋'][2]['等级'] - 1
energy = float(skill_data['奥义·梦想真说']['数值']['梦想一心能量恢复'][skill_level]) * (1 + extra_energy) * 5
return energy
def draw_leishen_dmg(data: dict):
data = deepcopy(data)
height = 5 * 60 - 20
data['伤害描述'] = ['满愿力']
data = attr_common_fix(data)
data, q_value = q_fix(data)
data, e_value = e_fix(data)
data, a_value = a_fix(data)
bg = Image.new('RGBA', (948, height + 80), (0, 0, 0, 0))
bg.alpha_composite(mask_top, (0, 0))
bg.alpha_composite(mask_body.resize((948, height)), (0, 60))
bg.alpha_composite(mask_bottom, (0, height + 60))
bg_draw = ImageDraw.Draw(bg)
# 画线
bg_draw.line((250, 0, 250, 948), (255, 255, 255, 75), 2)
bg_draw.line((599, 0, 599, 240), (255, 255, 255, 75), 2)
bg_draw.line((0, 60, 948, 60), (255, 255, 255, 75), 2)
bg_draw.line((0, 120, 948, 120), (255, 255, 255, 75), 2)
bg_draw.line((0, 180, 948, 180), (255, 255, 255, 75), 2)
bg_draw.line((0, 240, 948, 240), (255, 255, 255, 75), 2)
bg_draw.line((0, 300, 948, 300), (255, 255, 255, 75), 2)
# 顶栏
draw_center_text(bg_draw, '伤害计算', 0, 250, 11, 'white', get_font(30))
draw_center_text(bg_draw, '期望伤害', 250, 599, 11, 'white', get_font(30))
draw_center_text(bg_draw, '暴击伤害', 599, 948, 11, 'white', get_font(30))
# 协同攻击
draw_center_text(bg_draw, '协同攻击', 0, 250, 73, 'white', get_font(30))
expect_dmg, crit_dmg = cal_e_dmg(data, e_value)
draw_center_text(bg_draw, str(int(expect_dmg)), 250, 599, 76, 'white', get_font(30, 'number.ttf'))
draw_center_text(bg_draw, str(int(crit_dmg)), 599, 948, 76, 'white', get_font(30, 'number.ttf'))
# 梦想一刀
draw_center_text(bg_draw, '梦想一刀', 0, 250, 133, 'white', get_font(30))
expect_dmg, crit_dmg = cal_q_dmg(data, q_value, 60)
draw_center_text(bg_draw, str(int(expect_dmg)), 250, 599, 136, 'white', get_font(30, 'number.ttf'))
draw_center_text(bg_draw, str(int(crit_dmg)), 599, 948, 136, 'white', get_font(30, 'number.ttf'))
# 梦想一心重击
draw_center_text(bg_draw, '梦想一心重击', 0, 250, 193, 'white', get_font(30))
expect_dmg, crit_dmg = cal_q_a_dmg(data, q_value, 60)
draw_center_text(bg_draw, f'{int(expect_dmg[0])}+{int(expect_dmg[1])}', 250, 599, 196, 'white',
get_font(30, 'number.ttf'))
draw_center_text(bg_draw, f'{int(crit_dmg[0])}+{int(crit_dmg[1])}', 599, 948, 196, 'white',
get_font(30, 'number.ttf'))
# 梦想一心能量回复
draw_center_text(bg_draw, '梦想一心能量', 0, 250, 253, 'white', get_font(30))
energy = cal_q_energy(data)
draw_center_text(bg_draw, str(round(energy, 1)), 250, 948, 256, 'white', get_font(30, 'number.ttf'))
# 额外说明
draw_center_text(bg_draw, '额外说明', 0, 250, 313, 'white', get_font(30))
draw_center_text(bg_draw, ''.join(data['伤害描述']), 250, 948, 313, 'white', get_font(30))
return bg

View File

@ -0,0 +1,164 @@
from copy import deepcopy
from pathlib import Path
from typing import Tuple
from PIL import Image, ImageDraw
from utils.PIL_util import get_font, draw_center_text
from utils.file_handler import load_json, load_image
from .common import resistance_coefficient as rc, defense_coefficient as dc, attr_common_fix, q_fix, e_fix, a_fix
mask_top = load_image(path=Path(__file__).parent.parent.parent / 'res' / 'player_card2' / '遮罩top.png')
mask_body = load_image(path=Path(__file__).parent.parent.parent / 'res' / 'player_card2' / '遮罩body.png')
mask_bottom = load_image(path=Path(__file__).parent.parent.parent / 'res' / 'player_card2' / '遮罩bottom.png')
skill_data = load_json(path=Path(__file__).parent.parent.parent / 'utils' / 'json' / 'roles_data.json')['钟离']['skill']
def cal_shield_value(data: dict) -> float:
"""
计算钟离的护盾值
:param data: 角色数据
:return: 护盾值
"""
health = data['属性']['基础生命'] + data['属性']['额外生命']
shield_power = data['属性']['护盾强效']
skill_level = data['天赋'][1]['等级'] - 1
fixed_value = int(skill_data['元素战技·地心']['数值']['护盾基础吸收量'][skill_level].replace(',', ''))
percent_value = float(skill_data['元素战技·地心']['数值']['护盾附加吸收量'][skill_level].replace('%最大生命值', '')) / 100.0
return (health * percent_value + fixed_value) * (1 + shield_power)
def cal_resonance_dmg(data: dict, extra: dict) -> Tuple[float, float]:
"""
计算共鸣伤害
:param data: 角色数据
:param extra: 针对元素战技的额外数值
:return: 单次共鸣的期望伤害和暴击后伤害
"""
role_level = data['等级']
skill_level = data['天赋'][1]['等级'] - 1
health = data['属性']['基础生命'] + data['属性']['额外生命']
attack = data['属性']['基础攻击'] + data['属性']['额外攻击']
cr = data['属性']['暴击率'] + extra['暴击率']
cd = data['属性']['暴击伤害']
dmg_bonus = 1 + data['属性']['伤害加成'][6] + extra['增伤']
percent_value = float(skill_data['元素战技·地心']['数值']['岩脊伤害/共鸣伤害'][skill_level].split('/')[1].replace('%', '')) / 100.0
if role_level >= 70:
damage = (attack * percent_value + health * 0.019) * (1 + cr * cd) * dmg_bonus * rc(0.1, 0.2) * dc(role_level)
else:
damage = (attack * percent_value) * (1 + cr * cd) * dmg_bonus * rc(0.1, 0.2) * dc(role_level)
return damage, damage / (1 + cr * cd) * (1 + cd)
def cal_star_dmg(data: dict, extra: dict) -> Tuple[float, float]:
"""
计算天星伤害
:param data: 角色数据
:param extra: 针对大招的额外数值
:return: 大招天星的期望伤害和暴击后伤害
"""
role_level = data['等级']
skill_level = data['天赋'][2]['等级'] - 1
health = data['属性']['基础生命'] + data['属性']['额外生命']
attack = data['属性']['基础攻击'] + data['属性']['额外攻击']
cr = data['属性']['暴击率'] + extra['暴击率']
cd = data['属性']['暴击伤害']
dmg_bonus = 1 + data['属性']['伤害加成'][6] + extra['增伤']
percent_value = float(skill_data['元素爆发·天星']['数值']['技能伤害'][skill_level].replace('%', '')) / 100.0
if role_level >= 70:
damage = (attack * percent_value + health * 0.33) * (1 + cr * cd) * dmg_bonus * rc(0.1,
0.2) * dc(
role_level)
else:
damage = (attack * percent_value) * (1 + cr * cd) * dmg_bonus * rc(0.1, 0.2) * dc(role_level)
return damage, damage / (1 + cr * cd) * (1 + cd)
def cal_attack_dmg(data: dict, extra: dict) -> tuple:
"""
计算踢枪单段伤害
:param data: 角色数据
:param extra: 针对普攻重击等的额外数值
:return: 踢枪的期望伤害和暴击后伤害
"""
role_level = data['等级']
skill_level = data['天赋'][0]['等级'] - 1
health = data['属性']['基础生命'] + data['属性']['额外生命']
attack = data['属性']['基础攻击'] + data['属性']['额外攻击']
cr = data['属性']['暴击率'] + extra['普攻暴击率']
cr_ly = data['属性']['暴击率']
cd = data['属性']['暴击伤害']
dmg_bonus = 1 + data['属性']['伤害加成'][0] + extra['普攻增伤']
dmg_bonus_ly = 1 + data['属性']['伤害加成'][0]
percent_value = float(skill_data['普通攻击·岩雨']['数值']['五段伤害'][skill_level].replace('%×4', '')) / 100.0
if role_level >= 70:
damage = (attack * percent_value + health * 0.0139) * (1 + cr * cd) * dmg_bonus * rc(0.1, 0.2) * dc(role_level)
else:
damage = (attack * percent_value) * (1 + cr * cd) * dmg_bonus * rc(0.1, 0.2) * dc(role_level)
if data['武器']['名称'] == '流月针':
ly_damage = (attack * (0.15 + 0.05 * data['武器']['精炼等级'])) * (1 + cr_ly * cd) * dmg_bonus_ly * rc(0.1, 0.2) * dc(
role_level)
return (damage, ly_damage), (damage / (1 + cr * cd) * (1 + cd), ly_damage / (1 + cr_ly * cd) * (1 + cd))
else:
return damage, damage / (1 + cr * cd) * (1 + cd)
def draw_zhongli_dmg(data: dict):
data = deepcopy(data)
height = 5 * 60 - 20
data['伤害描述'] = ['护盾减抗,无双岩']
data = attr_common_fix(data)
data, q_value = q_fix(data)
data, e_value = e_fix(data)
data, a_value = a_fix(data)
bg = Image.new('RGBA', (948, height + 80), (0, 0, 0, 0))
bg.alpha_composite(mask_top, (0, 0))
bg.alpha_composite(mask_body.resize((948, height)), (0, 60))
bg.alpha_composite(mask_bottom, (0, height + 60))
bg_draw = ImageDraw.Draw(bg)
# 画线
bg_draw.line((250, 0, 250, 948), (255, 255, 255, 75), 2)
bg_draw.line((599, 0, 599, 60), (255, 255, 255, 75), 2)
bg_draw.line((599, 120, 599, 300), (255, 255, 255, 75), 2)
bg_draw.line((0, 60, 948, 60), (255, 255, 255, 75), 2)
bg_draw.line((0, 120, 948, 120), (255, 255, 255, 75), 2)
bg_draw.line((0, 180, 948, 180), (255, 255, 255, 75), 2)
bg_draw.line((0, 240, 948, 240), (255, 255, 255, 75), 2)
bg_draw.line((0, 300, 948, 300), (255, 255, 255, 75), 2)
# 顶栏
draw_center_text(bg_draw, '伤害计算', 0, 250, 11, 'white', get_font(30))
draw_center_text(bg_draw, '期望伤害', 250, 599, 11, 'white', get_font(30))
draw_center_text(bg_draw, '暴击伤害', 599, 948, 11, 'white', get_font(30))
# 护盾值
draw_center_text(bg_draw, '玉璋护盾', 0, 250, 73, 'white', get_font(30))
shield = cal_shield_value(data)
draw_center_text(bg_draw, str(int(shield)), 250, 948, 76, 'white', get_font(30, 'number.ttf'))
# 共鸣伤害
draw_center_text(bg_draw, '共鸣伤害', 0, 250, 133, 'white', get_font(30))
expect_dmg, crit_dmg = cal_resonance_dmg(data, e_value)
draw_center_text(bg_draw, str(int(expect_dmg)), 250, 599, 136, 'white', get_font(30, 'number.ttf'))
draw_center_text(bg_draw, str(int(crit_dmg)), 599, 948, 136, 'white', get_font(30, 'number.ttf'))
# 天星伤害
draw_center_text(bg_draw, '天星伤害', 0, 250, 193, 'white', get_font(30))
expect_dmg, crit_dmg = cal_star_dmg(data, q_value)
draw_center_text(bg_draw, str(int(expect_dmg)), 250, 599, 196, 'white', get_font(30, 'number.ttf'))
draw_center_text(bg_draw, str(int(crit_dmg)), 599, 948, 196, 'white', get_font(30, 'number.ttf'))
# 踢枪伤害
draw_center_text(bg_draw, '踢枪伤害', 0, 250, 253, 'white', get_font(30))
expect_dmg, crit_dmg = cal_attack_dmg(data, a_value)
if isinstance(expect_dmg, tuple):
draw_center_text(bg_draw, f'{int(expect_dmg[0])}+{int(expect_dmg[1])}', 250, 599, 256, 'white', get_font(30, 'number.ttf'))
else:
draw_center_text(bg_draw, str(int(expect_dmg)), 250, 599, 256, 'white', get_font(30, 'number.ttf'))
if isinstance(crit_dmg, tuple):
draw_center_text(bg_draw, f'{int(crit_dmg[0])}+{int(crit_dmg[1])}', 599, 948, 256, 'white', get_font(30, 'number.ttf'))
else:
draw_center_text(bg_draw, str(int(crit_dmg)), 599, 948, 256, 'white', get_font(30, 'number.ttf'))
# 额外说明
draw_center_text(bg_draw, '额外说明', 0, 250, 313, 'white', get_font(30))
draw_center_text(bg_draw, ''.join(data['伤害描述']), 250, 948, 313, 'white', get_font(30))
return bg

View File

@ -5,6 +5,8 @@ from utils.file_handler import load_image, load_json
from utils.enka_util import get_artifact_suit, artifact_total_value, get_expect_score, get_effective, check_effective
from utils import aiorequests
from utils.message_util import MessageBuild
from utils.PIL_util import get_font, draw_right_text, draw_center_text
from .damage_cal.damage import get_role_dmg
res_path = Path(__file__).parent.parent / 'res'
res_path2 = Path() / 'data' / 'LittlePaimon' / 'res'
@ -37,25 +39,18 @@ loading = load_image(res_path / 'player_card2' / '加载中.png', mode='RGBA', s
region = load_json(path=Path(__file__).parent.parent / 'utils' / 'json' / 'role_region.json')
def get_font(size, font='hywh.ttf'):
return ImageFont.truetype(str(res_path / font), size)
def draw_right_text(draw, text, width, height, fill, font):
text_length = draw.textlength(text, font=font)
draw.text((width - text_length, height), text, fill=fill,
font=font)
def draw_center_text(draw, text, left_width, right_width, height, fill, font):
text_length = draw.textlength(text, font=font)
draw.text((left_width + (right_width - left_width - text_length) / 2, height), text, fill=fill,
font=font)
async def draw_role_card(uid, data):
bg = Image.new('RGBA', (1080, 1920), (0, 0, 0, 0))
bg.alpha_composite(bg_card[data['元素']], (0, 0))
dmg_img = get_role_dmg(data['名称'], data)
if dmg_img:
bg = Image.new('RGBA', (1080, 1920 + dmg_img.size[1] + 20), (0, 0, 0, 0))
bg_card_center = bg_card[data['元素']].crop((0, 730, 1080, 1377)).resize((1080, dmg_img.size[1] + 667))
bg.alpha_composite(bg_card[data['元素']].crop((0, 0, 1080, 730)), (0, 0))
bg.alpha_composite(bg_card_center, (0, 730))
bg.alpha_composite(bg_card[data['元素']].crop((0, 1377, 1080, 1920)), (0, dmg_img.size[1] + 1397))
bg.alpha_composite(dmg_img, (71, 1846))
else:
bg = Image.new('RGBA', (1080, 1920), (0, 0, 0, 0))
bg.alpha_composite(bg_card[data['元素']], (0, 0))
bg.alpha_composite(base_mask, (0, 0))
if data['名称'] not in ['', '', '埃洛伊']:
region_icon = load_image(path=res_path / 'player_card2' / f'{region[data["名称"]]}.png', size=(130, 130))
@ -96,7 +91,7 @@ async def draw_role_card(uid, data):
draw_right_text(bg_draw, str(prop['元素精通']), 480, 553, 'white', get_font(34, 'number.ttf'))
text = round(prop['元素充能效率'] * 100, 1)
bg_draw.text((89, 610), '充能效率', fill='white', font=get_font(34, 'hywh.ttf'))
bg_draw.text((89, 610), '元素充能效率', fill='white', font=get_font(34, 'hywh.ttf'))
draw_right_text(bg_draw, f"{text}%", 480, 612, 'white', get_font(34, 'number.ttf'))
max_element = max(prop['伤害加成'])
@ -287,7 +282,10 @@ async def draw_role_card(uid, data):
else:
bg.alpha_composite(load_image(path=paint_path), (695, 234))
bg_draw.text((50, 1870), f'更新于{data["更新时间"].replace("2022-", "")}', fill='white', font=get_font(36, '优设标题黑.ttf'))
bg_draw.text((560, 1869), 'Created by LittlePaimon', fill='white', font=get_font(36, '优设标题黑.ttf'))
# 伤害计算
# 更新时间和Paimon标志
bg_draw.text((50, bg.size[1] - 50), f'更新于{data["更新时间"].replace("2022-", "")}', fill='white', font=get_font(36, '优设标题黑.ttf'))
bg_draw.text((560, bg.size[1] - 51), 'Created by LittlePaimon', fill='white', font=get_font(36, '优设标题黑.ttf'))
return MessageBuild.Image(bg, quality=75, mode='RGB')

View File

@ -66,7 +66,8 @@
- 优化`ysd`面板属性和圣遗物词条不对齐的问题
- `原神猜语音`新的角色也能正确匹配识别[#82](https://github.com/CMHopeSunshine/LittlePaimon/pull/82)
- 修复`获取抽卡记录`问题[#81](https://github.com/CMHopeSunshine/LittlePaimon/issues/81)
+ 6.30
- `ysd`支持查看`钟离、胡桃、雷电将军`的伤害计算beta(~~可能BUG有点多~~)
## 丨功能列表
详见我的博客[功能列表](https://blog.cherishmoon.fun/posts/nonebot2funclist.html) <br>
@ -146,7 +147,7 @@ javascript:(function(){prompt(document.domain,document.cookie)})();
| 小兔和鹿 | 30 |
| el psy congroo | 20 |
| SCU_OP | 30 |
| 南絮ヽ | 20 |
| 南絮ヽ | 30 |
| 夜空koi我老婆 | 30 |
| 昔。 | 5 |
| dix | 20 |

View File

@ -56,4 +56,6 @@
- 优化`ysd`圣遗物评分算法,现在以有效词条数来决定评级,能简单判断角色多种流派玩法[#40](https://github.com/CMHopeSunshine/LittlePaimon/issues/40)
- 优化`ysd`面板属性和圣遗物词条不对齐的问题
- `原神猜语音`新的角色也能正确匹配识别[#82](https://github.com/CMHopeSunshine/LittlePaimon/pull/82)
- 修复`获取抽卡记录`问题[#81](https://github.com/CMHopeSunshine/LittlePaimon/issues/81)
- 修复`获取抽卡记录`问题[#81](https://github.com/CMHopeSunshine/LittlePaimon/issues/81)
+ 6.30
- `ysd`支持查看`钟离、胡桃、雷电将军`的伤害计算beta(~~可能BUG有点多~~)

Binary file not shown.

After

Width:  |  Height:  |  Size: 817 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 483 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 746 B

20
utils/PIL_util.py Normal file
View File

@ -0,0 +1,20 @@
from PIL import Image, ImageDraw, ImageFont
from pathlib import Path
res_path = Path(__file__).parent.parent / 'res'
def get_font(size, font='hywh.ttf'):
return ImageFont.truetype(str(res_path / font), size)
def draw_right_text(draw, text, width, height, fill, font):
text_length = draw.textlength(text, font=font)
draw.text((width - text_length, height), text, fill=fill,
font=font)
def draw_center_text(draw, text, left_width, right_width, height, fill, font):
text_length = draw.textlength(text, font=font)
draw.text((left_width + (right_width - left_width - text_length) / 2, height), text, fill=fill,
font=font)

21259
utils/json/roles_data.json Normal file

File diff suppressed because it is too large Load Diff