2022-07-13 23:30:52 +08:00

359 lines
14 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']
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'] if fight_prop['physicalDmgBonus'] <= fight_prop['dmgBonus'] else fight_prop['physicalDmgBonus']
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]
if weaponType == '法器' or char_name in ['荒泷一斗', '刻晴', '诺艾尔']:
prop['A_dmgBonus'] = dmgBonus
prop['B_dmgBonus'] = dmgBonus
prop['C_dmgBonus'] = dmgBonus
elif weaponType == '':
prop['A_dmgBonus'] = physicalDmgBonus
prop['B_dmgBonus'] = dmgBonus
prop['C_dmgBonus'] = physicalDmgBonus
else:
prop['A_dmgBonus'] = physicalDmgBonus
prop['B_dmgBonus'] = physicalDmgBonus
prop['C_dmgBonus'] = physicalDmgBonus
prop['E_dmgBonus'] = 0
prop['Q_dmgBonus'] = 0
prop['A_critrate'] = 0
prop['B_critrate'] = 0
prop['C_critrate'] = 0
prop['E_critrate'] = 0
prop['Q_critrate'] = 0
prop['A_critdmg'] = 0
prop['B_critdmg'] = 0
prop['C_critdmg'] = 0
prop['E_critdmg'] = 0
prop['Q_critdmg'] = 0
prop['A_addDmg'] = 0
prop['B_addDmg'] = 0
prop['C_addDmg'] = 0
prop['E_addDmg'] = 0
prop['Q_addDmg'] = 0
prop['hp_green'] = fight_prop['addHp']
prop['attack_green'] = fight_prop['addAtk']
prop['defense_green'] = fight_prop['addDef']
prop['r'] = 0.1
prop['d'] = 0
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
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添加入属性
print(all_effect)
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
print(prop)
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'] + 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 = (char_level + 100) / ((char_level + 100) + (1-prop['d']) * (char_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 * r + add_dmg
avg_dmg = (crit_dmg - add_dmg) * critrate_cal + (1 - critrate_cal) * (effect_prop * power_percent + power_value) * (1 + dmgBonus_cal) * d * 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