mirror of
https://github.com/KimigaiiWuyi/GenshinUID.git
synced 2025-05-30 04:00:31 +08:00
323 lines
12 KiB
Python
323 lines
12 KiB
Python
import re
|
||
import json
|
||
from typing import List
|
||
from pathlib import Path
|
||
from copy import deepcopy
|
||
|
||
import httpx
|
||
|
||
Genshin_version = '3.0.0'
|
||
|
||
path = (
|
||
Path(__file__).parents[1]
|
||
/ 'utils'
|
||
/ 'enka_api'
|
||
/ 'map'
|
||
/ f'avatarId2Name_mapping_{Genshin_version}.json'
|
||
)
|
||
element_path = (
|
||
Path(__file__).parents[1]
|
||
/ 'utils'
|
||
/ 'enka_api'
|
||
/ 'map'
|
||
/ f'avatarName2Element_mapping_{Genshin_version}.json'
|
||
)
|
||
with open(path, 'r', encoding='utf-8') as f:
|
||
char_id_list = json.load(f)
|
||
|
||
with open(element_path, 'r', encoding='utf-8') as f:
|
||
char_element_list = json.load(f)
|
||
|
||
char_list = []
|
||
char_action = {}
|
||
INDEX_MAP = ['', 'A', 'E', 'Q']
|
||
attack_type_list = {'普通攻击': 'A', '重击': 'B', '下落攻击': 'C', '战技': 'E', '爆发': 'Q'}
|
||
label_type_list = {
|
||
'普通攻击': 'A',
|
||
'重击': 'B',
|
||
'下落攻击': 'C',
|
||
'攻击': 'attack',
|
||
'充能效率': 'ce',
|
||
'生命值': 'hp',
|
||
'防御': 'defense',
|
||
'暴击率': 'critrate',
|
||
'暴击伤害': 'critDmg',
|
||
'元素精通': 'em',
|
||
}
|
||
extra = {
|
||
'胡桃': {'A重击伤害': '蒸发', 'Q低血量时技能伤害': '蒸发'},
|
||
'香菱': {'E喷火伤害': '蒸发', 'Q旋火轮伤害': '蒸发'},
|
||
'达达利亚': {'Q技能伤害·近战': '蒸发', 'Q技能伤害·远程': '蒸发'},
|
||
'重云': {'Q技能伤害': '融化'},
|
||
'雷电将军': {
|
||
'E协同攻击伤害': '超激化',
|
||
'Q梦想一刀基础伤害': '满愿力',
|
||
'Q一段伤害': '超激化',
|
||
'Q重击伤害': '超激化',
|
||
},
|
||
'甘雨': {'A霜华矢命中伤害': '融化', 'A霜华矢·霜华绽发伤害': '融化'},
|
||
'可莉': {'A重击伤害': '蒸发'},
|
||
'优菈': {'Q光降之剑基础伤害': '13层'},
|
||
'行秋': {'E技能伤害': '蒸发'},
|
||
'莫娜': {'A重击伤害': '蒸发', 'Q泡影破裂伤害': '蒸发'},
|
||
'迪卢克': {'Q斩击伤害': '蒸发'},
|
||
'芭芭拉': {'A重击伤害': '蒸发'},
|
||
'七七': {'Q技能伤害': '融化'},
|
||
'八重神子': {'Q天狐霆雷伤害': '超激化', 'E杀生樱伤害·叁阶': '超激化', 'E杀生樱伤害·肆阶': '超激化'},
|
||
'菲谢尔': {'E奥兹攻击伤害': '超激化'},
|
||
'久岐忍': {'Q单次伤害': '超激化'},
|
||
'柯莱': {'Q跃动伤害': '蔓激化', 'E技能伤害': '蔓激化'},
|
||
'提纳里': {'E技能伤害': '蔓激化', 'Q缠藤箭伤害': '蔓激化', 'Q次级缠藤箭伤害': '蔓激化'},
|
||
'刻晴': {'A重击伤害': '超激化', 'Q技能伤害': '超激化', 'Q连斩伤害': '超激化', 'Q最后一击伤害': '超激化'},
|
||
'北斗': {'Q闪雷伤害': '超激化'},
|
||
}
|
||
template = {'A重击伤害': {'name': 'A重击伤害', 'type': '', 'plus': 1, 'value': []}}
|
||
|
||
|
||
def fill_label(label_name: str, index: int) -> str:
|
||
label_name = INDEX_MAP[index] + label_name
|
||
return label_name
|
||
|
||
|
||
def from_type_to_value(value_type: str, para):
|
||
value = ''
|
||
if value_type == 'F1P':
|
||
value = '%.1f%%' % (para * 100)
|
||
elif value_type == 'F2P':
|
||
value = '%.2f%%' % (para * 100)
|
||
elif value_type == 'F1':
|
||
value = '%.1f' % (para)
|
||
elif value_type == 'F2':
|
||
value = '%.2f' % (para)
|
||
elif value_type == 'P':
|
||
value = str(round(para * 100)) + '%'
|
||
elif value_type == 'I':
|
||
value = '%.2f' % para
|
||
return value
|
||
|
||
|
||
def find_tag(labels: List, index: int, char: str, parameters: dict) -> dict:
|
||
result = {}
|
||
for label in labels:
|
||
if char != '旅行者':
|
||
if char_element_list[char] == 'Anemo':
|
||
if 'A扩散伤害' not in result:
|
||
result['A扩散伤害'] = {
|
||
'name': 'A扩散伤害',
|
||
'type': '扩散',
|
||
'plus': 0,
|
||
'value': [str(i) for i in range(1, 11)],
|
||
}
|
||
# 拿到形如{param1:F1P}的字典
|
||
label_split = label.split('|')[-1]
|
||
# 拿到单个标签的名称,形如一段伤害
|
||
label_name = label.split('|')[0]
|
||
# 寻找label中带*的倍数倍率,比如 攻击力*3
|
||
label_plus = 1
|
||
if '*' in label_split:
|
||
label_plus = label_split.split('*')[-1]
|
||
label_plus = int(re.findall(r'[0-9]+', label_plus)[0])
|
||
# 如果在label_split内拿到了形如每秒{param2:F2P}生命值上限+{param3:I},获取汉字转换类型
|
||
laber_kanji_list = re.findall(r'[\u4e00-\u9fa5]+', label_split)
|
||
# 如果label_split中有汉字,则获取汉字的类型
|
||
laber_kanji_list_str = ''.join(laber_kanji_list).replace('每秒', '')
|
||
for type in label_type_list:
|
||
if type in laber_kanji_list_str:
|
||
label_kanji = type
|
||
break
|
||
else:
|
||
label_kanji = '攻击力'
|
||
# 找到标签{param1:F1P}的List
|
||
label_attr = re.findall(r'{[a-zA-Z0-9]+:[a-zA-Z0-9]+}', label_split)
|
||
# 例如"持续治疗|每秒{param2:F2P}生命值上限+{param3:I}",
|
||
# 对单个标签内多个param进行处理,处理成形如['{param2:F2P}', '{param3:I}']
|
||
value_type = ''
|
||
temp_value = []
|
||
temp_temp = []
|
||
for indexA, k in enumerate(label_attr):
|
||
# 去除多多余字符 变成 param2:F2P
|
||
k_deal = k.replace('{', '').replace('}', '')
|
||
value_type = k_deal.split(':')[-1] # F2P
|
||
value_index = k_deal.split(':')[0] # param2
|
||
temp = [
|
||
from_type_to_value(value_type, parameter)
|
||
for parameter in parameters[value_index]
|
||
]
|
||
if indexA == 0:
|
||
temp_value = temp
|
||
# 只采用高空坠地的倍率
|
||
elif indexA == 1 and '低空/高空坠地' in label:
|
||
temp_value = temp
|
||
# 阿忍仅计算50%血量以下伤害
|
||
elif indexA == 1 and char == '久岐忍':
|
||
temp_value = temp
|
||
# 埃洛伊特殊值
|
||
elif indexA == 2 and char == '埃洛伊':
|
||
temp_value = temp
|
||
# 烟绯满层丹火印
|
||
elif indexA == 4 and char == '烟绯':
|
||
temp_value = temp
|
||
# 无例外情况倍率全部相加
|
||
else:
|
||
temp_value = [f'{i}+{j}' for i, j in zip(temp_temp, temp)]
|
||
# 读入缓存
|
||
temp_temp = temp
|
||
# 制作倍率单元素
|
||
parameter_list = {
|
||
'name': '',
|
||
'type': label_kanji,
|
||
'plus': label_plus,
|
||
'value': temp_value,
|
||
}
|
||
|
||
# 特殊化处理
|
||
if '心海' in char:
|
||
label_name = label_name.replace('提升', '提高')
|
||
label_name = label_name.replace('低空/高空坠地冲击伤害', '高空下落伤害')
|
||
label_name = label_name.replace('技能', '')
|
||
|
||
# 提升指提升百分比 例如 E:dmgBouns+50%
|
||
# 提高指提高固定值 例如 Q:addDmg+40%defense
|
||
|
||
label_keyword_hurt_list = ['一段', '壹阶', '贰阶', '叁阶', '肆阶']
|
||
label_keyword_up_list = {
|
||
'普通攻击': 'A:addDmg',
|
||
'重击': 'B:addDmg',
|
||
'攻击': 'attack',
|
||
'生命值': 'hp',
|
||
'防御': 'defense',
|
||
'暴击率': 'critrate',
|
||
'充能效率': 'ce',
|
||
'元素精通': 'em',
|
||
}
|
||
|
||
if '持续时间' in label_name:
|
||
continue
|
||
elif '提升' in label_name:
|
||
# 云瑾和申鹤
|
||
if '伤害值提升' in label_name:
|
||
parameter_list['name'] = fill_label(label_name, index)
|
||
result[fill_label(label_name, index)] = parameter_list
|
||
elif '伤害提升' in label_name:
|
||
add_type = ''
|
||
# 寻找有没有合适的加成eg
|
||
target = 0
|
||
for attack_type in attack_type_list:
|
||
if attack_type in label_name:
|
||
add_type += attack_type_list[attack_type]
|
||
target += 1
|
||
# 没有就对E进行加成
|
||
else:
|
||
if target > 0:
|
||
if '变格' in label_name:
|
||
parameter_list['plus'] = 4
|
||
else:
|
||
add_type += 'E'
|
||
# 格式化加:
|
||
if add_type:
|
||
add_type = add_type + ':'
|
||
add_attr = '{}dmgBonus+'.format(add_type) + '{' + '}'
|
||
parameter_list['effect'] = add_attr
|
||
parameter_list['name'] = fill_label(label_name, index)
|
||
if 'effect' not in result:
|
||
result['effect'] = []
|
||
result['effect'].append(parameter_list)
|
||
else:
|
||
continue
|
||
elif '提高' in label_name:
|
||
# 阻止雷电将军E
|
||
if '元素爆发伤害提高' in label_name:
|
||
continue
|
||
if '攻击速度' in label_name:
|
||
continue
|
||
for attack_type in label_type_list:
|
||
if attack_type in label_name:
|
||
add_prop = label_keyword_up_list[attack_type]
|
||
break
|
||
else:
|
||
add_prop = 'E:addDmg'
|
||
|
||
for attack_type in label_type_list:
|
||
if attack_type in label_kanji:
|
||
base_prop = label_keyword_up_list[attack_type]
|
||
break
|
||
else:
|
||
base_prop = 'attack'
|
||
add_attr = add_prop + '+{' + '}' + base_prop
|
||
parameter_list['effect'] = add_attr
|
||
parameter_list['name'] = fill_label(label_name, index)
|
||
if 'effect' not in result:
|
||
result['effect'] = []
|
||
result['effect'].append(parameter_list)
|
||
elif '伤害' in label_name:
|
||
if '段' in label_name or '阶' in label_name:
|
||
for label_keyword in label_keyword_hurt_list:
|
||
if label_keyword in label_name:
|
||
parameter_list['name'] = fill_label(label_name, index)
|
||
result[fill_label(label_name, index)] = parameter_list
|
||
elif '低空/高空坠地冲击伤害' in label_name and char not in ['魈']:
|
||
continue
|
||
elif '下坠期间伤害' in label_name:
|
||
continue
|
||
else:
|
||
parameter_list['name'] = fill_label(label_name, index)
|
||
result[fill_label(label_name, index)] = parameter_list
|
||
elif '治疗' in label_name:
|
||
parameter_list['name'] = fill_label(label_name, index)
|
||
result[fill_label(label_name, index)] = parameter_list
|
||
elif '护盾' in label_name:
|
||
parameter_list['name'] = fill_label(label_name, index)
|
||
result[fill_label(label_name, index)] = parameter_list
|
||
elif '满蓄力瞄准射击' in label_name:
|
||
parameter_list['name'] = fill_label(label_name, index)
|
||
result[fill_label(label_name, index)] = parameter_list
|
||
elif '愿力加成' in label_name:
|
||
parameter_list['name'] = fill_label(label_name, index)
|
||
result['extra'] = parameter_list
|
||
|
||
if char in extra:
|
||
for extra_name in extra[char]:
|
||
temp_name = extra_name.replace('技能', '')
|
||
if fill_label(label_name, index) == temp_name:
|
||
new_parameter_list = deepcopy(parameter_list)
|
||
new_parameter_list['name'] = (
|
||
fill_label(label_name, index)
|
||
+ f'({extra[char][extra_name]})'
|
||
)
|
||
result[
|
||
fill_label(label_name, index)
|
||
+ f'({extra[char][extra_name]})'
|
||
] = new_parameter_list
|
||
|
||
return result
|
||
|
||
|
||
for char_id in char_id_list:
|
||
char_list.append(char_id_list[char_id])
|
||
|
||
for char in char_list:
|
||
talent_data = httpx.get(
|
||
f'https://info.minigg.cn/talents?query={char}'
|
||
).json()
|
||
if 'errcode' in talent_data:
|
||
continue
|
||
result = {}
|
||
for i in range(1, 4):
|
||
skill = talent_data['combat{}'.format(str(i))]
|
||
labels = skill['attributes']['labels']
|
||
parameters = skill['attributes']['parameters']
|
||
result = dict(result, **find_tag(labels, i, char, parameters))
|
||
char_action[char] = result
|
||
|
||
with open(
|
||
str(
|
||
Path(__file__).parents[1]
|
||
/ 'genshinuid_enka'
|
||
/ 'dmgCalc'
|
||
/ 'char_action.json'
|
||
),
|
||
'w',
|
||
encoding='UTF-8',
|
||
) as file:
|
||
json.dump(char_action, file, ensure_ascii=False)
|