2022-07-20 21:05:48 +08:00

422 lines
16 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from pathlib import Path
from typing import List, Optional, Tuple
import json
from PIL import Image, ImageDraw, ImageFont, ImageChops
DMG_PATH = Path(__file__).parents[0]
DMG_TEXT_PATH = DMG_PATH / 'texture2d'
version = '2.8.0'
avatarName2SkillAdd_fileName = f'avatarName2SkillAdd_mapping_{version}.json'
with open(DMG_PATH / avatarName2SkillAdd_fileName, "r", encoding='UTF-8') as f:
avatarName2SkillAdd = json.load(f)
with open(DMG_PATH / 'char_action.json', "r", encoding='UTF-8') as f:
char_action = json.load(f)
with open(DMG_PATH / 'artifacts_effect.json', "r", encoding='UTF-8') as f:
artifacts_effect_map = json.load(f)
with open(DMG_PATH / 'weapons_effect.json', "r", encoding='UTF-8') as f:
weapons_effect_map = json.load(f)
with open(DMG_PATH / 'char_talent_effect.json', "r", encoding='UTF-8') as f:
char_talent_effect_map = json.load(f)
with open(DMG_PATH / 'char_skill_effect.json', "r", encoding='UTF-8') as f:
char_skill_effect_map = json.load(f)
dmgBar_1 = Image.open(DMG_TEXT_PATH / 'dmgBar_1.png')
dmgBar_2 = Image.open(DMG_TEXT_PATH / 'dmgBar_2.png')
def genshin_font_origin(size: int) -> ImageFont:
return ImageFont.truetype(str(DMG_TEXT_PATH / 'yuanshen_origin.ttf'), size=size)
async def draw_dmgCacl_img(raw_data: dict) -> Image:
char_name = raw_data['avatarName']
char_level = int(raw_data['avatarLevel'])
weaponName = raw_data['weaponInfo']['weaponName']
weaponType = raw_data['weaponInfo']['weaponType']
weaponAffix = raw_data['weaponInfo']['weaponAffix']
skillList = raw_data['avatarSkill']
a_skill_name = skillList[0]['skillName'].replace('普通攻击·', '')
prop = {}
prop['A_skill_level'] = skillList[0]['skillLevel']
e_skill_name = skillList[1]['skillName']
prop['E_skill_level'] = skillList[1]['skillLevel']
q_skill_name = skillList[-1]['skillName']
prop['Q_skill_level'] = skillList[-1]['skillLevel']
enemy_level = char_level
skill_add = avatarName2SkillAdd[char_name]
for skillAdd_index in range(0, 2):
if len(raw_data['talentList']) >= 3 + skillAdd_index * 2:
if skill_add[skillAdd_index] == 'E':
prop['E_skill_level'] += 3
elif skill_add[skillAdd_index] == 'Q':
prop['Q_skill_level'] += 3
fight_prop = raw_data['avatarFightProp']
prop['basehp'] = fight_prop['baseHp']
prop['baseattack'] = fight_prop['baseAtk']
prop['basedefense'] = fight_prop['baseDef']
prop['hp'] = fight_prop['hp']
prop['attack'] = fight_prop['atk']
prop['defense'] = fight_prop['def']
prop['em'] = fight_prop['elementalMastery']
prop['critrate'] = fight_prop['critRate']
prop['critdmg'] = fight_prop['critDmg']
prop['ce'] = fight_prop['energyRecharge']
prop['physicalDmgBonus'] = physicalDmgBonus = fight_prop['physicalDmgBonus']
prop['dmgBonus'] = dmgBonus = fight_prop['dmgBonus']
prop['healBouns'] = fight_prop['healBonus']
prop['shieldBouns'] = 0
if char_name not in char_action:
faild_img = Image.new('RGBA', (950, 1))
return faild_img, 0
power_list = char_action[char_name]
for prop_attr in [
'dmgBonus',
'critrate',
'critdmg',
'addDmg',
'd',
'r',
'ignoreDef',
]:
if prop_attr in ['addDmg', 'd', 'r', 'ignoreDef']:
prop['{}'.format(prop_attr)] = 0
for prop_limit in ['A', 'B', 'C', 'E', 'Q']:
prop['{}_{}'.format(prop_limit, prop_attr)] = 0
for prop_limit in ['A', 'B', 'C', 'E', 'Q']:
if weaponType == '法器' or char_name in ['荒泷一斗', '刻晴', '诺艾尔']:
prop['{}_dmgBonus'.format(prop_limit)] = dmgBonus
elif weaponType == '':
if prop_limit in ['A', 'C']:
prop['{}_dmgBonus'.format(prop_limit)] = physicalDmgBonus
elif prop_limit in ['B', 'E', 'Q']:
prop['{}_dmgBonus'.format(prop_limit)] = dmgBonus
else:
if prop_limit in ['A', 'B', 'C']:
prop['{}_dmgBonus'.format(prop_limit)] = physicalDmgBonus
elif prop_limit in ['E', 'Q']:
prop['{}_dmgBonus'.format(prop_limit)] = dmgBonus
prop['hp_green'] = fight_prop['addHp']
prop['attack_green'] = fight_prop['addAtk']
prop['defense_green'] = fight_prop['addDef']
prop['r'] = 0.1
prop['a'] = 0
prop['g'] = 0
prop['k'] = 1
# 计算圣遗物套装
if 'equipSets' in raw_data:
equipSets = raw_data['equipSets']
else:
artifact_set_list = []
for i in raw_data['equipList']:
artifact_set_list.append(i['aritifactSetsName'])
equipSetList = set(artifact_set_list)
equipSets = {'type': '', 'set': ''}
for equip in equipSetList:
if artifact_set_list.count(equip) >= 4:
equipSets['type'] = '4'
equipSets['set'] = equip
break
elif artifact_set_list.count(equip) == 1:
pass
elif artifact_set_list.count(equip) >= 2:
equipSets['type'] += '2'
equipSets['set'] += '|' + equip
if equipSets['set'].startswith('|'):
equipSets['set'] = equipSets['set'][1:]
all_effect = []
# 计算圣遗物buff
if equipSets['type'] == '4':
all_effect.append(artifacts_effect_map[equipSets['set']]['4'])
elif equipSets['type'] == '2':
all_effect.append(artifacts_effect_map[equipSets['set']]['2'])
elif equipSets['type'] == '22':
if equipSets['set'][-2] == '':
first_artifact = equipSets['set'][-3:]
else:
first_artifact = equipSets['set'][-2:]
second_artifact = equipSets['set'][:2]
temp = []
temp_number = 0
for artifacts_single_effect in artifacts_effect_map:
if first_artifact in artifacts_single_effect:
temp_number += 1
temp.append(artifacts_effect_map[artifacts_single_effect]['2'])
if temp_number >= 2:
break
all_effect.extend(temp)
# 计算武器buff
weapon_effet = weapons_effect_map[weaponName][str(weaponAffix)]
all_effect.append(weapon_effet)
# 计算技能buff
for talent in char_talent_effect_map[char_name]:
if int(talent) <= len(raw_data['talentList']):
all_effect.append(char_talent_effect_map[char_name][talent])
else:
break
# 计算角色buff
for skill in char_skill_effect_map[char_name]:
if int(skill) <= char_level:
all_effect.append(char_skill_effect_map[char_name][skill])
else:
break
power_effect = ''
if 'effect' in power_list:
for skill_effect_single in power_list['effect']:
skill_effect_name = skill_effect_single['name']
skill_effect_value = skill_effect_single['value']
skill_effect = skill_effect_single['effect']
skill_effect_level = prop['{}_skill_level'.format(skill_effect_name)]
skill_effect_value_detail = skill_effect_value[skill_effect_level]
if skill_effect[-1] == '}':
skill_effect_value_detail = skill_effect_value_detail.replace('%', '')
add_limit = skill_effect.split(':')
if len(add_limit) == 1:
for i in power_list:
if i == 'effect':
pass
else:
power_list[i]['power_name'] = (
'{}'.format(skill_effect_name)
+ power_list[i]['power_name']
)
else:
for i in power_list:
if i == 'effect':
pass
else:
add_type = i[0]
if '重击' in i or '蓄力' in i:
add_type = 'B'
elif '冲击伤害' in i:
add_type = 'C'
if add_type in add_limit[0]:
power_list[i]['power_name'] = (
'{}'.format(skill_effect_name)
+ power_list[i]['power_name']
)
power_effect = skill_effect.format(skill_effect_value_detail)
all_effect.append(power_effect)
del power_list['effect']
sp = []
# 计算全部的buff添加入属性
if all_effect:
all_effect = ';'.join(all_effect)
all_effect_list = all_effect.split(';')
for effect in all_effect_list:
if effect == '':
continue
effect_limit = ''
if ':' in effect:
pass
else:
effect = ':' + effect
effect_limit = effect.split(':')[0]
effect_attr = effect.split(':')[1].split('+')[0]
effect_value = effect.split(':')[1].split('+')[-1]
base_check = True
if '%' in effect_value:
effect_value_base_on_attr = effect_value.split('%')[-1]
effect_value_base_on_value = '%'.join(effect_value.split('%')[:-1])
if '%' in effect_value_base_on_value:
effect_value_base_on_max_value = effect_value_base_on_value.split(
'%'
)[0]
effect_value_base_on_value = effect_value_base_on_value.split('%')[
-1
]
effect_now_value = (
float(effect_value_base_on_value)
* prop[effect_value_base_on_attr]
)
effect_value = (
float(effect_value_base_on_max_value)
if effect_now_value >= float(effect_value_base_on_max_value)
else effect_now_value
)
else:
effect_value = (
float(effect_value_base_on_value)
* prop[effect_value_base_on_attr]
)
base_check = False
if effect_attr != 'em':
effect_value = float(effect_value) / 100
if effect_attr in ['hp', 'attack', 'defense'] and base_check:
effect_value += effect_value * prop['base{}'.format(effect_attr)]
else:
effect_value = float(effect_value)
if effect_limit:
if '\u4e00' <= effect_limit[0] <= '\u9fff':
sp.append(
{
'effect_name': effect_limit,
'effect_attr': effect_attr,
'effect_value': effect_value,
}
)
else:
for limit in effect_limit:
prop['{}_{}'.format(limit, effect_attr)] += effect_value
else:
prop['{}'.format(effect_attr)] += effect_value
w = 950
h = 40 * (len(power_list) + 1)
result_img = Image.new('RGBA', (w, h), (0, 0, 0, 0))
for i in range(0, len(power_list) + 1):
if i % 2 == 0:
result_img.paste(dmgBar_1, (0, i * 40))
else:
result_img.paste(dmgBar_2, (0, i * 40))
result_draw = ImageDraw.Draw(result_img)
text_color = (255, 255, 255)
title_color = (255, 255, 100)
text_size = genshin_font_origin(28)
result_draw.text((45, 22), '角色动作', title_color, text_size, anchor='lm')
result_draw.text((460, 22), '暴击伤害', title_color, text_size, anchor='lm')
result_draw.text((695, 22), '期望伤害', title_color, text_size, anchor='lm')
for index, power_name in enumerate(power_list):
attack_type = power_name[0]
if '重击' in power_name or '瞄准射击' in power_name:
attack_type = 'B'
elif '冲击伤害' in power_name:
attack_type = 'C'
elif '' in power_name and '伤害' in power_name:
attack_type = 'A'
sp_dmgBonus = 0
sp_addDmg = 0
if sp:
for sp_single in sp:
if sp_single['effect_name'] == power_name[1:]:
if sp_single['effect_attr'] == 'dmgBouns':
sp_dmgBonus += sp_single['effect_value']
elif sp_single['effect_attr'] == 'addDmg':
sp_addDmg += sp_single['effect_value']
if '攻击' in power_list[power_name]['type']:
effect_prop = prop['attack']
elif '生命值' in power_list[power_name]['type']:
effect_prop = prop['hp']
elif '防御' in power_list[power_name]['type']:
effect_prop = prop['defense']
power = power_list[power_name]['value'][
prop['{}_skill_level'.format(power_name[0])]
]
power_plus = power_list[power_name]['plus']
power_percent, power_value = await power_to_value(power, power_plus)
dmgBonus_cal = prop['{}_dmgBonus'.format(attack_type)] + sp_dmgBonus
critdmg_cal = prop['critdmg'] + prop['{}_critdmg'.format(attack_type)]
critrate_cal = prop['critrate'] + prop['{}_critrate'.format(attack_type)]
d_cal = (char_level + 100) / (
(char_level + 100)
+ (1 - prop['{}_d'.format(attack_type)])
* (1 - prop['{}_ignoreDef'.format(attack_type)])
* (enemy_level + 100)
)
r = 1 - prop['r']
e_dmg = prop['k'] * (1 + (2.78 * prop['em']) / (prop['em'] + 1400) + prop['a'])
add_dmg = prop['{}_addDmg'.format(attack_type)] + sp_addDmg
if '治疗' in power_name:
crit_dmg = avg_dmg = (effect_prop * power_percent + power_value) * (
1 + prop['healBouns']
)
elif '护盾' in power_name:
crit_dmg = avg_dmg = (effect_prop * power_percent + power_value) * (
1 + prop['shieldBouns']
)
elif '提升' in power_name or '提高' in power_name:
continue
else:
crit_dmg = (effect_prop * power_percent + power_value) * (
1 + critdmg_cal
) * (1 + dmgBonus_cal) * d_cal * r + add_dmg
avg_dmg = (
(crit_dmg - add_dmg) * critrate_cal
+ (1 - critrate_cal)
* (effect_prop * power_percent + power_value)
* (1 + dmgBonus_cal)
* d_cal
* r
+ add_dmg
)
result_draw.text(
(45, 22 + (index + 1) * 40),
power_list[power_name]['power_name'],
text_color,
text_size,
anchor='lm',
)
result_draw.text(
(460, 22 + (index + 1) * 40),
str(round(crit_dmg)),
text_color,
text_size,
anchor='lm',
)
result_draw.text(
(695, 22 + (index + 1) * 40),
str(round(avg_dmg)),
text_color,
text_size,
anchor='lm',
)
return result_img, len(power_list) + 2
async def power_to_value(power: str, power_plus: int) -> List:
"""
将power转换为value
"""
if '+' in power:
power_percent = (float(power.split('+')[0].replace('%', '')) / 100) * power_plus
power_value = power.split('+')[1]
if '%' in power_value:
power_percent += float(power_value.replace('%', '')) / 100 * power_plus
power_value = 0
else:
power_value = float(power_value)
else:
power_percent = float(power.replace('%', '')) / 100 * power_plus
power_value = 0
return power_percent, power_value