GenshinUID/GenshinUID/tools/get_action.py
2023-12-24 18:14:35 +08:00

342 lines
13 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.

import re
import sys
import json
import asyncio
from typing import List
from pathlib import Path
from copy import deepcopy
import httpx
sys.path.append(str(Path(__file__).parents[2]))
sys.path.append(str(Path(__file__).parents[5]))
__package__ = 'GenshinUID.tools'
from ..utils.ambr_to_minigg import convert_ambr_to_talent # noqa: E402
from ..utils.map.GS_MAP_PATH import ( # noqa: E402
avatarId2Name,
avatarName2Element,
)
char_list: List[str] = []
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重击伤害': '蒸发'},
'胡桃': {'A重击伤害': '蒸发', 'Q低血量时技能伤害': '蒸发'},
'安柏': {'A满蓄力瞄准射击': ['融化', '蒸发']},
'香菱': {'E喷火伤害': '蒸发', 'Q旋火轮伤害': '蒸发'},
'达达利亚': {'A满蓄力瞄准射击': '蒸发', 'Q技能伤害·近战': '蒸发', 'Q技能伤害·远程': '蒸发'},
'重云': {'Q技能伤害': '融化'},
'雷电将军': {
'E协同攻击伤害': '超激化',
'Q梦想一刀基础伤害': '满愿力',
'Q一段伤害': '满愿力',
'Q重击伤害': '满愿力',
},
'班尼特': {'Q技能伤害': '蒸发'},
'甘雨': {'A霜华矢命中伤害': '融化', 'A霜华矢·霜华绽发伤害': '融化'},
'可莉': {'A重击伤害': '蒸发'},
'优菈': {'Q光降之剑基础伤害': ['13层', '24层']},
'行秋': {'E技能伤害': '蒸发'},
'莫娜': {'A重击伤害': '蒸发', 'Q泡影破裂伤害': '蒸发'},
'迪卢克': {'Q斩击伤害': '蒸发'},
'芭芭拉': {'A重击伤害': '蒸发'},
'七七': {'Q技能伤害': '融化'},
'八重神子': {
'Q伤害': '超激化',
'Q天狐霆雷伤害': '超激化',
'E杀生樱伤害·叁阶': '超激化',
'E杀生樱伤害·肆阶': '超激化',
},
'菲谢尔': {'E奥兹攻击伤害': '超激化'},
'久岐忍': {'Q单次伤害': '超激化'},
'柯莱': {'Q跃动伤害': '蔓激化', 'E技能伤害': '蔓激化'},
'提纳里': {
'A藏蕴花矢伤害': '蔓激化',
'E技能伤害': '蔓激化',
'Q缠藤箭伤害': '蔓激化',
'Q次级缠藤箭伤害': '蔓激化',
},
'刻晴': {
'A重击伤害': '超激化',
'E雷楔伤害': '超激化',
'E斩击伤害': '超激化',
'Q技能伤害': '超激化',
'Q连斩伤害': '超激化*2',
'Q最后一击伤害': '超激化',
},
'北斗': {'Q闪雷伤害': '超激化'},
'赛诺': {'E冥祭伤害': '超激化', 'Q一段伤害': '超激化', 'Q重击伤害': '超激化'},
'纳西妲': {'E长按伤害': '蔓激化', 'E灭净三业伤害': ['蔓激化', '蔓激化·前台']},
'旅行者(草)': {'Q草灯莲攻击伤害': '蔓激化'},
'夜兰': {'E伤害': '蒸发'},
'艾尔海森': {'Q单次伤害': '蔓激化', 'E突进攻击伤害': '蔓激化', 'E1枚光幕攻击伤害': '蔓激化'},
'迪希雅': {
'E净焰昂藏伤害': '蒸发',
'E剑域炽焰伤害': '蒸发',
'E领域伤害': '蒸发',
'Q炽鬃拳伤害': '蒸发',
'Q焚落踢伤害': '蒸发',
},
'娜维娅': {
'E玫瑰晶弹基础伤害': ['3层', '6层'],
},
}
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 '旅行者' not in char:
if avatarName2Element[char] == 'Anemo':
if 'A扩散伤害' not in result:
result['A扩散伤害'] = {
'name': 'A扩散伤害',
'type': '扩散',
'plus': 0,
'value': [str(i) for i in range(1, 11)],
}
if char == '妮露':
if 'A丰穰之核(绽放)' not in result:
result['A丰穰之核(绽放)'] = {
'name': 'A丰穰之核(绽放)',
'type': '绽放',
'plus': 0,
'value': [str(i) for i in range(1, 11)],
}
if char == '久岐忍':
if 'A元素反应(超绽放)' not in result:
result['A元素反应(超绽放)'] = {
'name': 'A元素反应(超绽放)',
'type': '扩散',
'plus': 0,
'value': [str(i) for i in range(1, 11)],
}
if char == '托马':
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 == '久岐忍' and label_name == '总伤害':
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 = ['一段', '壹阶', '贰阶', '叁阶', '肆阶', '四阶高压粉碎']
if '炽焰箭' in label_name:
continue
elif char == '珊瑚宫心海' and '提高' in label_name:
continue
elif '元素爆发伤害提高' in label_name and char == '雷电将军':
continue
elif '持续时间' 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
else:
continue
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 or '回复' 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
if char in extra:
for extra_name in extra[char]:
temp_name = extra_name.replace('技能', '')
if fill_label(label_name, index) == temp_name:
if isinstance(extra[char][extra_name], List):
for extra_tag in extra[char][extra_name]:
new_parameter_list = deepcopy(parameter_list)
new_parameter_list['name'] = (
fill_label(label_name, index)
+ f'({extra_tag})'
)
result[
fill_label(label_name, index)
+ f'({extra_tag})'
] = new_parameter_list
else:
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
async def main():
for char_id in avatarId2Name:
char_list.append(avatarId2Name[char_id])
char_list.extend(['旅行者(风)', '旅行者(雷)', '旅行者(岩)', '旅行者(草)'])
for char in char_list:
print(char)
talent_data = httpx.get(
f'https://info.minigg.cn/talents?query={char}'
).json()
if 'retcode' in talent_data:
for _id in avatarId2Name:
if avatarId2Name[_id] == char:
char_id = _id
break
else:
continue
if int(char_id) >= 11000000:
continue
talent_data = await convert_ambr_to_talent(char_id)
if talent_data is None:
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'
/ 'effect'
/ 'char_action.json'
),
'w',
encoding='UTF-8',
) as file:
json.dump(char_action, file, ensure_ascii=False)
asyncio.run(main())