mirror of
https://github.com/baiqwerdvd/StarRailUID.git
synced 2025-05-05 19:23:45 +08:00
✨初步完成面板查询
This commit is contained in:
parent
2da65b6992
commit
a71f476773
@ -13,10 +13,6 @@ from ..utils.convert import get_uid
|
||||
from ..utils.error_reply import UID_HINT
|
||||
from ..utils.image.convert import convert_img
|
||||
from .draw_char_img import draw_char_info_img
|
||||
|
||||
# from ..utils.map.GS_MAP_PATH import alias_data
|
||||
# from .draw_char_rank import draw_cahrcard_list
|
||||
# from .get_enka_img import draw_enka_img, get_full_char
|
||||
from ..utils.resource.RESOURCE_PATH import TEMP_PATH
|
||||
|
||||
sv_char_info_config = SV('sr面板设置', pm=2)
|
||||
|
@ -1,12 +1,80 @@
|
||||
import re
|
||||
import json
|
||||
from pathlib import Path
|
||||
from typing import Dict, Union, Optional
|
||||
|
||||
from mpmath import mp, nstr
|
||||
from PIL import Image, ImageDraw
|
||||
from gsuid_core.logger import logger
|
||||
from gsuid_core.utils.error_reply import CHAR_HINT
|
||||
from gsuid_core.utils.image.convert import convert_img
|
||||
from gsuid_core.utils.image.image_tools import draw_text_by_line
|
||||
|
||||
from .mono.Character import Character
|
||||
from ..utils.resource.RESOURCE_PATH import PLAYER_PATH
|
||||
from ..utils.map.SR_MAP_PATH import RelicId2Rarity
|
||||
from ..utils.excel.read_excel import light_cone_ranks
|
||||
from ..utils.map.name_covert import name_to_avatar_id, alias_to_char_name
|
||||
from ..utils.resource.RESOURCE_PATH import (
|
||||
RELIC_PATH,
|
||||
SKILL_PATH,
|
||||
PLAYER_PATH,
|
||||
WEAPON_PATH,
|
||||
CHAR_PORTRAIT,
|
||||
)
|
||||
from ..utils.fonts.starrail_fonts import (
|
||||
sr_font_20,
|
||||
sr_font_23,
|
||||
sr_font_24,
|
||||
sr_font_26,
|
||||
sr_font_28,
|
||||
sr_font_34,
|
||||
sr_font_38,
|
||||
)
|
||||
|
||||
mp.dps = 14
|
||||
|
||||
TEXT_PATH = Path(__file__).parent / 'texture2D'
|
||||
|
||||
bg_img = Image.open(TEXT_PATH / "bg.png")
|
||||
white_color = (213, 213, 213)
|
||||
|
||||
NUM_MAP = {
|
||||
0: '零',
|
||||
1: '一',
|
||||
2: '二',
|
||||
3: '三',
|
||||
4: '四',
|
||||
5: '五',
|
||||
6: '六',
|
||||
}
|
||||
|
||||
RANK_MAP = {
|
||||
1: '_rank1.png',
|
||||
2: '_rank2.png',
|
||||
3: '_ultimate.png',
|
||||
4: '_rank4.png',
|
||||
5: '_skill.png',
|
||||
6: '_rank6.png',
|
||||
}
|
||||
|
||||
skill_type_map = {
|
||||
'Normal': ('普攻', 'basic_atk'),
|
||||
'BPSkill': ('战技', 'skill'),
|
||||
'Ultra': ('终结技', 'ultimate'),
|
||||
'': ('天赋', 'talent'),
|
||||
'MazeNormal': 'dev_连携',
|
||||
'Maze': ('秘技', 'technique'),
|
||||
}
|
||||
|
||||
|
||||
RELIC_POS = {
|
||||
'1': (26, 1162),
|
||||
'2': (367, 1162),
|
||||
'3': (700, 1162),
|
||||
'4': (26, 1593),
|
||||
'5': (367, 1593),
|
||||
'6': (700, 1593),
|
||||
}
|
||||
|
||||
|
||||
async def draw_char_info_img(raw_mes: str, sr_uid: str, url: Optional[str]):
|
||||
@ -14,8 +82,396 @@ async def draw_char_info_img(raw_mes: str, sr_uid: str, url: Optional[str]):
|
||||
char_name = ' '.join(re.findall('[\u4e00-\u9fa5]+', raw_mes))
|
||||
|
||||
char_data = await get_char_data(sr_uid, char_name)
|
||||
print(char_data)
|
||||
await cal_char_info(char_data)
|
||||
char = await cal_char_info(char_data)
|
||||
|
||||
# 放角色立绘
|
||||
char_info = bg_img.copy()
|
||||
char_img = Image.open(CHAR_PORTRAIT / f'{char.char_id}.png').resize(
|
||||
(1050, 1050)
|
||||
)
|
||||
char_info.paste(char_img, (-140, -100), char_img)
|
||||
|
||||
# 放属性图标
|
||||
attr_img = Image.open(TEXT_PATH / f'IconAttribute{char.char_element}.png')
|
||||
char_info.paste(attr_img, (580, 131), attr_img)
|
||||
|
||||
# 放角色名
|
||||
char_img_draw = ImageDraw.Draw(char_info)
|
||||
char_img_draw.text(
|
||||
(690, 175), char.char_name, white_color, sr_font_38, 'mm'
|
||||
)
|
||||
|
||||
# 放等级
|
||||
char_img_draw.text(
|
||||
(765, 183), f'LV.{str(char.char_level)}', white_color, sr_font_20, 'mm'
|
||||
)
|
||||
|
||||
# 放星级
|
||||
rarity_img = Image.open(
|
||||
TEXT_PATH / f'LightCore_Rarity{char.char_rarity}.png'
|
||||
).resize((306, 72))
|
||||
char_info.paste(rarity_img, (540, 198), rarity_img)
|
||||
|
||||
# 放命座
|
||||
rank_img = Image.open(TEXT_PATH / 'ImgNewBg.png')
|
||||
rank_img_draw = ImageDraw.Draw(rank_img)
|
||||
rank_img_draw.text(
|
||||
(70, 44), f'{NUM_MAP[char.char_rank]} 命', white_color, sr_font_28, 'mm'
|
||||
)
|
||||
char_info.paste(rank_img, (772, 190), rank_img)
|
||||
|
||||
# 放属性列表
|
||||
attr_bg = Image.open(TEXT_PATH / 'attr_bg.png')
|
||||
attr_bg_draw = ImageDraw.Draw(attr_bg)
|
||||
# 生命值
|
||||
hp = mp.mpf(char.base_attributes.get('hp'))
|
||||
add_hp = mp.mpf(
|
||||
char.add_attr['HPDelta'] if char.add_attr.get('HPDelta') else 0
|
||||
) + hp * mp.mpf(
|
||||
char.add_attr['HPAddedRatio']
|
||||
if char.add_attr.get('HPAddedRatio')
|
||||
else 0
|
||||
)
|
||||
hp = int(mp.floor(hp))
|
||||
add_hp = int(mp.floor(add_hp))
|
||||
attr_bg_draw.text(
|
||||
(500, 31), f'{hp + add_hp} (+{add_hp})', white_color, sr_font_26, 'rm'
|
||||
)
|
||||
# 攻击力
|
||||
attack = mp.mpf(char.base_attributes['attack'])
|
||||
add_attack = mp.mpf(
|
||||
char.add_attr['AttackDelta'] if char.add_attr.get('AttackDelta') else 0
|
||||
) + attack * mp.mpf(
|
||||
char.add_attr['AttackAddedRatio']
|
||||
if char.add_attr.get('AttackAddedRatio')
|
||||
else 0
|
||||
)
|
||||
atk = int(mp.floor(attack))
|
||||
add_attack = int(mp.floor(add_attack))
|
||||
attr_bg_draw.text(
|
||||
(500, 31 + 48),
|
||||
f'{atk + add_attack} (+{add_attack})',
|
||||
white_color,
|
||||
sr_font_26,
|
||||
'rm',
|
||||
)
|
||||
# 防御力
|
||||
defence = mp.mpf(char.base_attributes['defence'])
|
||||
add_defence = mp.mpf(
|
||||
char.add_attr.get('DefenceDelta')
|
||||
if char.add_attr.get('DefenceDelta')
|
||||
else 0
|
||||
) + defence * mp.mpf(
|
||||
char.add_attr.get('DefenceAddedRatio')
|
||||
if char.add_attr.get('DefenceAddedRatio')
|
||||
else 0
|
||||
)
|
||||
defence = int(mp.floor(defence))
|
||||
add_defence = int(mp.floor(add_defence))
|
||||
attr_bg_draw.text(
|
||||
(500, 31 + 48 * 2),
|
||||
f'{defence + add_defence} (+{add_defence})',
|
||||
white_color,
|
||||
sr_font_26,
|
||||
'rm',
|
||||
)
|
||||
# 速度
|
||||
speed = mp.mpf(char.base_attributes['speed'])
|
||||
add_speed = mp.mpf(
|
||||
char.add_attr['SpeedDelta'] if char.add_attr.get('SpeedDelta') else 0
|
||||
)
|
||||
speed = int(mp.floor(speed))
|
||||
add_speed = int(mp.floor(add_speed))
|
||||
attr_bg_draw.text(
|
||||
(500, 31 + 48 * 3),
|
||||
f'{speed + add_speed} (+{add_speed})',
|
||||
white_color,
|
||||
sr_font_26,
|
||||
'rm',
|
||||
)
|
||||
# 暴击率
|
||||
critical_chance = mp.mpf(char.base_attributes['CriticalChance'])
|
||||
critical_chance_base = mp.mpf(
|
||||
char.add_attr['CriticalChanceBase']
|
||||
if char.add_attr.get('CriticalChanceBase')
|
||||
else 0
|
||||
)
|
||||
critical_chance = (critical_chance + critical_chance_base) * 100
|
||||
critical_chance = nstr(critical_chance, 3)
|
||||
attr_bg_draw.text(
|
||||
(500, 31 + 48 * 4),
|
||||
f'{critical_chance}%',
|
||||
white_color,
|
||||
sr_font_26,
|
||||
'rm',
|
||||
)
|
||||
# 暴击伤害
|
||||
critical_damage = mp.mpf(char.base_attributes['CriticalDamage'])
|
||||
critical_damage_base = mp.mpf(
|
||||
char.add_attr['CriticalDamageBase']
|
||||
if char.add_attr.get('CriticalDamageBase')
|
||||
else 0
|
||||
)
|
||||
critical_damage = (critical_damage + critical_damage_base) * 100
|
||||
critical_damage = nstr(critical_damage, 4)
|
||||
attr_bg_draw.text(
|
||||
(500, 31 + 48 * 5),
|
||||
f'{critical_damage}%',
|
||||
white_color,
|
||||
sr_font_26,
|
||||
'rm',
|
||||
)
|
||||
# 效果命中
|
||||
status_probability_base = (
|
||||
mp.mpf(
|
||||
char.add_attr.get('StatusProbabilityBase')
|
||||
if char.add_attr.get('StatusProbabilityBase')
|
||||
else 0
|
||||
)
|
||||
* 100
|
||||
)
|
||||
status_probability = nstr(status_probability_base, 3)
|
||||
attr_bg_draw.text(
|
||||
(500, 31 + 48 * 6),
|
||||
f'{status_probability}%',
|
||||
white_color,
|
||||
sr_font_26,
|
||||
'rm',
|
||||
)
|
||||
# 效果抵抗
|
||||
status_resistance_base = (
|
||||
mp.mpf(
|
||||
char.add_attr['StatusResistanceBase']
|
||||
if char.add_attr.get('StatusResistanceBase')
|
||||
else 0
|
||||
)
|
||||
* 100
|
||||
)
|
||||
status_resistance = nstr(status_resistance_base, 3)
|
||||
attr_bg_draw.text(
|
||||
(500, 31 + 48 * 7),
|
||||
f'{status_resistance}%',
|
||||
white_color,
|
||||
sr_font_26,
|
||||
'rm',
|
||||
)
|
||||
char_info.paste(attr_bg, (517, 265), attr_bg)
|
||||
|
||||
# 命座
|
||||
lock_img = Image.open(TEXT_PATH / 'icon_lock.png').resize((50, 50))
|
||||
for rank in range(0, 6):
|
||||
rank_bg = Image.open(TEXT_PATH / 'mz_bg.png')
|
||||
if rank < char.char_rank:
|
||||
rank_img = Image.open(
|
||||
SKILL_PATH / f'{char.char_id}{RANK_MAP[rank + 1]}'
|
||||
).resize((50, 50))
|
||||
rank_bg.paste(rank_img, (19, 19), rank_img)
|
||||
char_info.paste(rank_bg, (20 + rank * 80, 630), rank_bg)
|
||||
else:
|
||||
rank_img = Image.open(
|
||||
SKILL_PATH / f'{char.char_id}{RANK_MAP[rank + 1]}'
|
||||
).resize((50, 50))
|
||||
rank_bg.paste(rank_img, (19, 19), rank_img)
|
||||
rank_bg.paste(lock_img, (19, 19), lock_img)
|
||||
char_info.paste(rank_bg, (20 + rank * 80, 630), rank_bg)
|
||||
|
||||
# 技能
|
||||
skill_bg = Image.open(TEXT_PATH / 'skill_bg.png')
|
||||
i = 0
|
||||
for skill in char.char_skill:
|
||||
skill_attr_img = Image.open(TEXT_PATH / 'skill_attr4.png')
|
||||
skill_panel_img = Image.open(TEXT_PATH / 'skill_panel.png')
|
||||
skill_img = Image.open(
|
||||
SKILL_PATH / f'{char.char_id}_'
|
||||
f'{skill_type_map[skill["skillAttackType"]][1]}.png'
|
||||
).resize((55, 55))
|
||||
skill_panel_img.paste(skill_img, (18, 15), skill_img)
|
||||
skill_panel_img.paste(skill_attr_img, (80, 10), skill_attr_img)
|
||||
skill_panel_img_draw = ImageDraw.Draw(skill_panel_img)
|
||||
skill_panel_img_draw.text(
|
||||
(108, 25),
|
||||
f'{skill_type_map[skill["skillAttackType"]][0]}',
|
||||
white_color,
|
||||
sr_font_26,
|
||||
'lm',
|
||||
)
|
||||
skill_panel_img_draw.text(
|
||||
(89, 55),
|
||||
f'Lv.{skill["skillLevel"]}',
|
||||
white_color,
|
||||
sr_font_26,
|
||||
'lm',
|
||||
)
|
||||
skill_panel_img_draw.text(
|
||||
(60, 88),
|
||||
f'{skill["skillName"]}',
|
||||
(105, 105, 105),
|
||||
sr_font_20,
|
||||
'lm',
|
||||
)
|
||||
skill_bg.paste(skill_panel_img, (50 + 187 * i, 35), skill_panel_img)
|
||||
i += 1
|
||||
char_info.paste(skill_bg, (0, 710), skill_bg)
|
||||
|
||||
# 武器
|
||||
weapon_bg = Image.open(TEXT_PATH / 'weapon_bg.png')
|
||||
weapon_id = char.equipment['equipmentID']
|
||||
weapon_img = Image.open(WEAPON_PATH / f'{weapon_id}.png').resize(
|
||||
(240, 240)
|
||||
)
|
||||
weapon_bg.paste(weapon_img, (-10, 50), weapon_img)
|
||||
weapon_bg_draw = ImageDraw.Draw(weapon_bg)
|
||||
weapon_bg_draw.text(
|
||||
(370, 47),
|
||||
f'{char.equipment["equipmentName"]}',
|
||||
white_color,
|
||||
sr_font_34,
|
||||
'mm',
|
||||
)
|
||||
weapon_bg_draw.text(
|
||||
(536, 47),
|
||||
f'{NUM_MAP[char.equipment["equipmentRank"]]} 阶',
|
||||
white_color,
|
||||
sr_font_28,
|
||||
'mm',
|
||||
)
|
||||
rarity_img = Image.open(
|
||||
TEXT_PATH / f'LightCore_Rarity{char.equipment["equipmentRank"]}.png'
|
||||
).resize((306, 72))
|
||||
weapon_bg.paste(rarity_img, (160, 55), rarity_img)
|
||||
weapon_bg_draw.text(
|
||||
(430, 90),
|
||||
f'Lv.{char.equipment["equipmentLevel"]}',
|
||||
white_color,
|
||||
sr_font_28,
|
||||
'mm',
|
||||
)
|
||||
|
||||
# 武器技能
|
||||
desc = light_cone_ranks[str(char.equipment['equipmentID'])]['desc']
|
||||
desc_params = light_cone_ranks[str(char.equipment['equipmentID'])][
|
||||
'params'
|
||||
][char.equipment['equipmentRank']]
|
||||
for i in range(0, len(desc_params)):
|
||||
desc = desc.replace(f'#{i + 1}[i]%', f'{str(desc_params[i] * 100)}%')
|
||||
for i in range(0, len(desc_params)):
|
||||
desc = desc.replace(f'#{i + 1}[i]', str(desc_params[i]))
|
||||
draw_text_by_line(weapon_bg, (220, 115), desc, sr_font_24, '#F9F9F9', 372)
|
||||
char_info.paste(weapon_bg, (22, 870), weapon_bg)
|
||||
|
||||
# 遗器
|
||||
weapon_rank_bg = Image.open(TEXT_PATH / 'rank_bg.png')
|
||||
char_info.paste(weapon_rank_bg, (690, 880), weapon_rank_bg)
|
||||
|
||||
for relic in char.char_relic:
|
||||
relic_img = Image.open(TEXT_PATH / 'yq_bg3.png')
|
||||
if str(relic["SetId"])[0] == '3':
|
||||
relic_piece_img = Image.open(
|
||||
RELIC_PATH / f'{relic["SetId"]}_{relic["Type"] - 5}.png'
|
||||
)
|
||||
else:
|
||||
relic_piece_img = Image.open(
|
||||
RELIC_PATH / f'{relic["SetId"]}_{relic["Type"] - 1}.png'
|
||||
)
|
||||
relic_piece_new_img = relic_piece_img.resize(
|
||||
(105, 105), Image.Resampling.LANCZOS
|
||||
).convert("RGBA")
|
||||
relic_img.paste(relic_piece_new_img, (200, 90), relic_piece_new_img)
|
||||
rarity_img = Image.open(
|
||||
TEXT_PATH
|
||||
/ f'LightCore_Rarity{RelicId2Rarity[str(relic["relicId"])]}.png'
|
||||
).resize((200, 48))
|
||||
relic_img.paste(rarity_img, (-20, 80), rarity_img)
|
||||
relic_img_draw = ImageDraw.Draw(relic_img)
|
||||
# if len(relic['name']) <= 5:
|
||||
# main_name = relic['relicName']
|
||||
# else:
|
||||
# main_name = (
|
||||
# relic['relicName'][:2] + relic['relicName'][4:]
|
||||
# )
|
||||
if len(relic['name']) <= 5:
|
||||
main_name = relic['name']
|
||||
else:
|
||||
main_name = relic['name'][:2] + relic['name'][4:]
|
||||
relic_img_draw.text(
|
||||
(30, 70),
|
||||
main_name,
|
||||
(255, 255, 255),
|
||||
sr_font_34,
|
||||
anchor='lm',
|
||||
)
|
||||
|
||||
# 主属性
|
||||
main_value = mp.mpf(relic['MainAffix']['Value'])
|
||||
main_name: str = relic['MainAffix']['Name']
|
||||
main_level: int = relic['Level']
|
||||
|
||||
if main_name in ['攻击力', '生命值', '防御力', '速度']:
|
||||
mainValueStr = nstr(main_value, 3)
|
||||
else:
|
||||
mainValueStr = nstr(main_value * 100, 3) + '%'
|
||||
|
||||
mainNameNew = (
|
||||
main_name.replace('百分比', '')
|
||||
.replace('伤害加成', '伤加成')
|
||||
.replace('属性伤害', '伤害')
|
||||
)
|
||||
|
||||
relic_img_draw.text(
|
||||
(35, 150),
|
||||
mainNameNew,
|
||||
(255, 255, 255),
|
||||
sr_font_28,
|
||||
anchor='lm',
|
||||
)
|
||||
relic_img_draw.text(
|
||||
(35, 195),
|
||||
'+{}'.format(mainValueStr),
|
||||
(255, 255, 255),
|
||||
sr_font_28,
|
||||
anchor='lm',
|
||||
)
|
||||
relic_img_draw.text(
|
||||
(230, 60),
|
||||
'+{}'.format(str(main_level)),
|
||||
(255, 255, 255),
|
||||
sr_font_23,
|
||||
anchor='mm',
|
||||
)
|
||||
|
||||
# relicScore = 0
|
||||
for index, i in enumerate(relic['SubAffixList']):
|
||||
subName: str = i['Name']
|
||||
subValue = mp.mpf(i['Value'])
|
||||
if subName in ['攻击力', '生命值', '防御力', '速度']:
|
||||
subValueStr = nstr(subValue, 3)
|
||||
else:
|
||||
subValueStr = nstr(subValue * 100, 3) + '%'
|
||||
subNameStr = subName.replace('百分比', '').replace('元素', '')
|
||||
# 副词条文字颜色
|
||||
relic_color = (255, 255, 255)
|
||||
|
||||
relic_img_draw.text(
|
||||
(47, 237 + index * 47),
|
||||
'{}'.format(subNameStr),
|
||||
relic_color,
|
||||
sr_font_26,
|
||||
anchor='lm',
|
||||
)
|
||||
relic_img_draw.text(
|
||||
(290, 237 + index * 47),
|
||||
'{}'.format(subValueStr),
|
||||
relic_color,
|
||||
sr_font_26,
|
||||
anchor='rm',
|
||||
)
|
||||
|
||||
char_info.paste(relic_img, RELIC_POS[str(relic["Type"])], relic_img)
|
||||
|
||||
# 发送图片
|
||||
res = await convert_img(char_info)
|
||||
logger.info('[sr面板]绘图已完成,等待发送!')
|
||||
return res
|
||||
|
||||
|
||||
async def cal_char_info(char_data: dict):
|
||||
@ -23,6 +479,7 @@ async def cal_char_info(char_data: dict):
|
||||
await char.get_equipment_info()
|
||||
await char.get_char_attribute_bonus()
|
||||
await char.get_relic_info()
|
||||
return char
|
||||
|
||||
|
||||
async def get_char_data(
|
||||
@ -30,9 +487,7 @@ async def get_char_data(
|
||||
) -> Union[Dict, str]:
|
||||
player_path = PLAYER_PATH / str(sr_uid)
|
||||
SELF_PATH = player_path / 'SELF'
|
||||
print(char_name)
|
||||
char_id = await name_to_avatar_id(char_name)
|
||||
print(char_id)
|
||||
if '开拓者' in char_name:
|
||||
char_name = '开拓者'
|
||||
else:
|
||||
|
@ -18,6 +18,7 @@ class Character:
|
||||
self.char_id: str = card_prop['avatarId']
|
||||
self.char_name: str = card_prop['avatarName']
|
||||
self.char_rank = card_prop['rank'] if card_prop.get('rank') else 0
|
||||
self.char_rarity = card_prop['avatarRarity']
|
||||
self.char_element = card_prop['avatarElement']
|
||||
self.char_promotion = card_prop['avatarPromotion']
|
||||
self.char_skill = card_prop['avatarSkill']
|
||||
@ -81,7 +82,6 @@ class Character:
|
||||
# 计算圣遗物效果
|
||||
set_id_list = []
|
||||
for relic in self.char_relic:
|
||||
print(json.dumps(relic, ensure_ascii=False))
|
||||
set_id_list.append(relic['SetId'])
|
||||
# 处理主属性
|
||||
relic_property = relic['MainAffix']['Property']
|
||||
|
BIN
StarRailUID/starrailuid_charinfo/texture2D/LightCore_Rarity1.png
Normal file
BIN
StarRailUID/starrailuid_charinfo/texture2D/LightCore_Rarity1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.0 KiB |
BIN
StarRailUID/starrailuid_charinfo/texture2D/LightCore_Rarity2.png
Normal file
BIN
StarRailUID/starrailuid_charinfo/texture2D/LightCore_Rarity2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.0 KiB |
BIN
StarRailUID/starrailuid_charinfo/texture2D/LightCore_Rarity3.png
Normal file
BIN
StarRailUID/starrailuid_charinfo/texture2D/LightCore_Rarity3.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.7 KiB |
BIN
StarRailUID/starrailuid_charinfo/texture2D/LightCore_Rarity4.png
Normal file
BIN
StarRailUID/starrailuid_charinfo/texture2D/LightCore_Rarity4.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.9 KiB |
BIN
StarRailUID/starrailuid_charinfo/texture2D/LightCore_Rarity5.png
Normal file
BIN
StarRailUID/starrailuid_charinfo/texture2D/LightCore_Rarity5.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.7 KiB |
BIN
StarRailUID/starrailuid_charinfo/texture2D/icon_lock.png
Normal file
BIN
StarRailUID/starrailuid_charinfo/texture2D/icon_lock.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 639 B |
@ -14,16 +14,19 @@ from .cal_value import cal_relic_sub_affix, cal_relic_main_affix
|
||||
from ..utils.excel.read_excel import AvatarPromotion, EquipmentPromotion
|
||||
from ..utils.map.SR_MAP_PATH import (
|
||||
SetId2Name,
|
||||
ItemId2Name,
|
||||
Property2Name,
|
||||
RelicId2SetId,
|
||||
EquipmentID2Name,
|
||||
EquipmentID2Rarity,
|
||||
rankId2Name,
|
||||
skillId2Name,
|
||||
skillId2Type,
|
||||
avatarId2Name,
|
||||
skillId2Effect,
|
||||
avatarId2EnName,
|
||||
avatarId2Rarity,
|
||||
characterSkillTree,
|
||||
skillId2AttackType,
|
||||
avatarId2DamageType,
|
||||
)
|
||||
|
||||
@ -55,7 +58,6 @@ async def api_to_dict(
|
||||
return []
|
||||
if isinstance(sr_data, dict):
|
||||
if 'PlayerDetailInfo' not in sr_data:
|
||||
print(sr_data)
|
||||
im = '服务器正在维护或者关闭中...\n检查lulu api是否可以访问\n如可以访问,尝试上报Bug!'
|
||||
return im
|
||||
elif sr_data is None:
|
||||
@ -124,7 +126,12 @@ async def get_data(char: dict, sr_data: dict, sr_uid: str):
|
||||
char['AvatarID'] * 100 + behavior['BehaviorID'] % 10
|
||||
)
|
||||
skill_temp['skillName'] = skillId2Name[str(skill_temp['skillId'])]
|
||||
skill_temp['skillType'] = skillId2Type[str(skill_temp['skillId'])]
|
||||
skill_temp['skillEffect'] = skillId2Effect[
|
||||
str(skill_temp['skillId'])
|
||||
]
|
||||
skill_temp['skillAttackType'] = skillId2AttackType[
|
||||
str(skill_temp['skillId'])
|
||||
]
|
||||
skill_temp['skillLevel'] = behavior['Level']
|
||||
char_data['avatarSkill'].append(skill_temp)
|
||||
|
||||
@ -172,8 +179,9 @@ async def get_data(char: dict, sr_data: dict, sr_uid: str):
|
||||
for relic in char['RelicList']:
|
||||
relic_temp = {}
|
||||
relic_temp['relicId'] = relic['ID']
|
||||
relic_temp['relicName'] = ItemId2Name[str(relic['ID'])]
|
||||
relic_temp['SetId'] = int(RelicId2SetId[str(relic['ID'])])
|
||||
relic_temp['name'] = SetId2Name[str(relic_temp['SetId'])]
|
||||
relic_temp['SetName'] = SetId2Name[str(relic_temp['SetId'])]
|
||||
relic_temp['Level'] = relic['Level'] if 'Level' in relic else 1
|
||||
relic_temp['Type'] = relic['Type']
|
||||
|
||||
@ -275,6 +283,9 @@ async def get_data(char: dict, sr_data: dict, sr_uid: str):
|
||||
equipment_info['equipmentLevel'] = char['EquipmentID']['Level']
|
||||
equipment_info['equipmentPromotion'] = char['EquipmentID']['Promotion']
|
||||
equipment_info['equipmentRank'] = char['EquipmentID']['Rank']
|
||||
equipment_info['equipmentRarity'] = EquipmentID2Rarity[
|
||||
str(equipment_info['equipmentID'])
|
||||
]
|
||||
equipment_base_attributes = {}
|
||||
equipment_promotion_base = EquipmentPromotion[
|
||||
str(equipment_info['equipmentID'])
|
||||
|
3148
StarRailUID/utils/excel/light_cone_ranks.json
Normal file
3148
StarRailUID/utils/excel/light_cone_ranks.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -14,3 +14,6 @@ with open(EXCEL / 'AvatarPromotionConfig.json', 'r', encoding='utf8') as f:
|
||||
|
||||
with open(EXCEL / 'EquipmentPromotionConfig.json', 'r', encoding='utf8') as f:
|
||||
EquipmentPromotion = json.load(f)
|
||||
|
||||
with open(EXCEL / 'light_cone_ranks.json', 'r', encoding='utf8') as f:
|
||||
light_cone_ranks = json.load(f)
|
||||
|
@ -15,6 +15,7 @@ sr_font_15 = starrail_font_origin(15)
|
||||
sr_font_18 = starrail_font_origin(18)
|
||||
sr_font_20 = starrail_font_origin(20)
|
||||
sr_font_22 = starrail_font_origin(22)
|
||||
sr_font_23 = starrail_font_origin(23)
|
||||
sr_font_24 = starrail_font_origin(24)
|
||||
sr_font_25 = starrail_font_origin(25)
|
||||
sr_font_26 = starrail_font_origin(26)
|
||||
|
@ -4,8 +4,8 @@ from io import BytesIO
|
||||
from pathlib import Path
|
||||
from typing import Tuple, Union, Optional
|
||||
|
||||
from PIL import Image
|
||||
from httpx import get
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
|
||||
from ...starrailuid_config.sr_config import srconfig
|
||||
from ..resource.RESOURCE_PATH import CU_BG_PATH, TEXT2D_PATH
|
||||
@ -24,6 +24,51 @@ else:
|
||||
bg_path = NM_BG_PATH
|
||||
|
||||
|
||||
def draw_text_by_line(
|
||||
img: Image.Image,
|
||||
pos: Tuple[int, int],
|
||||
text: str,
|
||||
font: ImageFont.FreeTypeFont,
|
||||
fill: Union[Tuple[int, int, int, int], str],
|
||||
max_length: float,
|
||||
center=False,
|
||||
line_space: Optional[float] = None,
|
||||
):
|
||||
"""
|
||||
在图片上写长段文字, 自动换行
|
||||
max_length单行最大长度, 单位像素
|
||||
line_space 行间距, 单位像素, 默认是字体高度的0.3倍
|
||||
"""
|
||||
x, y = pos
|
||||
_, h = font.getsize('X')
|
||||
if line_space is None:
|
||||
y_add = math.ceil(1.3 * h)
|
||||
else:
|
||||
y_add = math.ceil(h + line_space)
|
||||
draw = ImageDraw.Draw(img)
|
||||
row = "" # 存储本行文字
|
||||
length = 0 # 记录本行长度
|
||||
for character in text:
|
||||
w, h = font.getsize(character) # 获取当前字符的宽度
|
||||
if length + w * 2 <= max_length:
|
||||
row += character
|
||||
length += w
|
||||
else:
|
||||
row += character
|
||||
if center:
|
||||
font_size = font.getsize(row)
|
||||
x = math.ceil((img.size[0] - font_size[0]) / 2)
|
||||
draw.text((x, y), row, font=font, fill=fill)
|
||||
row = ""
|
||||
length = 0
|
||||
y += y_add
|
||||
if row != "":
|
||||
if center:
|
||||
font_size = font.getsize(row)
|
||||
x = math.ceil((img.size[0] - font_size[0]) / 2)
|
||||
draw.text((x, y), row, font=font, fill=fill)
|
||||
|
||||
|
||||
async def get_qq_avatar(
|
||||
qid: Optional[Union[int, str]] = None, avatar_url: Optional[str] = None
|
||||
) -> Image.Image:
|
||||
|
@ -26,6 +26,10 @@ EquipmentID2AbilityProperty_fileName = (
|
||||
f'EquipmentID2AbilityProperty_mapping_{version}.json'
|
||||
)
|
||||
RelicSetSkill_fileName = f'RelicSetSkill_mapping_{version}.json'
|
||||
skillId2AttackType_fileName = f'skillId2AttackType_mapping_{version}.json'
|
||||
EquipmentID2Rarity_fileName = f'EquipmentID2Rarity_mapping_{version}.json'
|
||||
RelicId2Rarity_fileName = f'RelicId2Rarity_mapping_{version}.json'
|
||||
ItemId2Name_fileName = f'ItemId2Name_mapping_{version}.json'
|
||||
|
||||
|
||||
class TS(TypedDict):
|
||||
@ -49,7 +53,7 @@ with open(MAP / skillId2Name_fileName, 'r', encoding='UTF-8') as f:
|
||||
skillId2Name = msgjson.decode(f.read(), type=Dict[str, str])
|
||||
|
||||
with open(MAP / skillId2Type_fileName, 'r', encoding='UTF-8') as f:
|
||||
skillId2Type = msgjson.decode(f.read(), type=Dict[str, str])
|
||||
skillId2Effect = msgjson.decode(f.read(), type=Dict[str, str])
|
||||
|
||||
with open(MAP / Property2Name_fileName, 'r', encoding='UTF-8') as f:
|
||||
Property2Name = msgjson.decode(f.read(), type=Dict[str, str])
|
||||
@ -84,3 +88,15 @@ with open(
|
||||
|
||||
with open(MAP / RelicSetSkill_fileName, 'r', encoding='UTF-8') as f:
|
||||
RelicSetSkill = msgjson.decode(f.read(), type=Dict[str, dict])
|
||||
|
||||
with open(MAP / skillId2AttackType_fileName, 'r', encoding='UTF-8') as f:
|
||||
skillId2AttackType = msgjson.decode(f.read(), type=Dict[str, str])
|
||||
|
||||
with open(MAP / EquipmentID2Rarity_fileName, 'r', encoding='UTF-8') as f:
|
||||
EquipmentID2Rarity = msgjson.decode(f.read(), type=Dict[str, int])
|
||||
|
||||
with open(MAP / RelicId2Rarity_fileName, 'r', encoding='UTF-8') as f:
|
||||
RelicId2Rarity = msgjson.decode(f.read(), type=Dict[str, int])
|
||||
|
||||
with open(MAP / ItemId2Name_fileName, 'r', encoding='UTF-8') as f:
|
||||
ItemId2Name = msgjson.decode(f.read(), type=Dict[str, str])
|
||||
|
@ -0,0 +1 @@
|
||||
{"20000": 3, "20001": 3, "20002": 3, "20003": 3, "20004": 3, "20005": 3, "20006": 3, "20007": 3, "20008": 3, "20009": 3, "20010": 3, "20011": 3, "20012": 3, "20013": 3, "20014": 3, "20015": 3, "20016": 3, "20017": 3, "20018": 3, "20019": 3, "20020": 3, "21000": 4, "21001": 4, "21002": 4, "21003": 4, "21004": 4, "21005": 4, "21006": 4, "21007": 4, "21008": 4, "21009": 4, "21010": 4, "21011": 4, "21012": 4, "21013": 4, "21014": 4, "21015": 4, "21016": 4, "21017": 4, "21018": 4, "21019": 4, "21020": 4, "21021": 4, "21022": 4, "21023": 4, "21024": 4, "21025": 4, "21026": 4, "21027": 4, "21028": 4, "21029": 4, "21030": 4, "21031": 4, "21032": 4, "21033": 4, "21034": 4, "23000": 5, "23001": 5, "23002": 5, "23003": 5, "23004": 5, "23005": 5, "23010": 5, "23012": 5, "23013": 5, "24000": 5, "24001": 5, "24002": 5, "29000": 3}
|
File diff suppressed because one or more lines are too long
@ -0,0 +1 @@
|
||||
{"31011": 2, "31012": 2, "31013": 2, "31014": 2, "31021": 2, "31022": 2, "31023": 2, "31024": 2, "31031": 2, "31032": 2, "31033": 2, "31034": 2, "31041": 2, "31042": 2, "31043": 2, "31044": 2, "31051": 2, "31052": 2, "31053": 2, "31054": 2, "31061": 2, "31062": 2, "31063": 2, "31064": 2, "31071": 2, "31072": 2, "31073": 2, "31074": 2, "31081": 2, "31082": 2, "31083": 2, "31084": 2, "31091": 2, "31092": 2, "31093": 2, "31094": 2, "31101": 2, "31102": 2, "31103": 2, "31104": 2, "31111": 2, "31112": 2, "31113": 2, "31114": 2, "31121": 2, "31122": 2, "31123": 2, "31124": 2, "33015": 2, "33016": 2, "33025": 2, "33026": 2, "33035": 2, "33036": 2, "33045": 2, "33046": 2, "33055": 2, "33056": 2, "33065": 2, "33066": 2, "33075": 2, "33076": 2, "33085": 2, "33086": 2, "41011": 3, "41012": 3, "41013": 3, "41014": 3, "41021": 3, "41022": 3, "41023": 3, "41024": 3, "41031": 3, "41032": 3, "41033": 3, "41034": 3, "41041": 3, "41042": 3, "41043": 3, "41044": 3, "41051": 3, "41052": 3, "41053": 3, "41054": 3, "41061": 3, "41062": 3, "41063": 3, "41064": 3, "41071": 3, "41072": 3, "41073": 3, "41074": 3, "41081": 3, "41082": 3, "41083": 3, "41084": 3, "41091": 3, "41092": 3, "41093": 3, "41094": 3, "41101": 3, "41102": 3, "41103": 3, "41104": 3, "41111": 3, "41112": 3, "41113": 3, "41114": 3, "41121": 3, "41122": 3, "41123": 3, "41124": 3, "43015": 3, "43016": 3, "43025": 3, "43026": 3, "43035": 3, "43036": 3, "43045": 3, "43046": 3, "43055": 3, "43056": 3, "43065": 3, "43066": 3, "43075": 3, "43076": 3, "43085": 3, "43086": 3, "51011": 4, "51012": 4, "51013": 4, "51014": 4, "51021": 4, "51022": 4, "51023": 4, "51024": 4, "51031": 4, "51032": 4, "51033": 4, "51034": 4, "51041": 4, "51042": 4, "51043": 4, "51044": 4, "51051": 4, "51052": 4, "51053": 4, "51054": 4, "51061": 4, "51062": 4, "51063": 4, "51064": 4, "51071": 4, "51072": 4, "51073": 4, "51074": 4, "51081": 4, "51082": 4, "51083": 4, "51084": 4, "51091": 4, "51092": 4, "51093": 4, "51094": 4, "51101": 4, "51102": 4, "51103": 4, "51104": 4, "51111": 4, "51112": 4, "51113": 4, "51114": 4, "51121": 4, "51122": 4, "51123": 4, "51124": 4, "53015": 4, "53016": 4, "53025": 4, "53026": 4, "53035": 4, "53036": 4, "53045": 4, "53046": 4, "53055": 4, "53056": 4, "53065": 4, "53066": 4, "53075": 4, "53076": 4, "53085": 4, "53086": 4, "55001": 4, "55002": 4, "55003": 4, "55004": 4, "55005": 4, "55006": 4, "61011": 5, "61012": 5, "61013": 5, "61014": 5, "61021": 5, "61022": 5, "61023": 5, "61024": 5, "61031": 5, "61032": 5, "61033": 5, "61034": 5, "61041": 5, "61042": 5, "61043": 5, "61044": 5, "61051": 5, "61052": 5, "61053": 5, "61054": 5, "61061": 5, "61062": 5, "61063": 5, "61064": 5, "61071": 5, "61072": 5, "61073": 5, "61074": 5, "61081": 5, "61082": 5, "61083": 5, "61084": 5, "61091": 5, "61092": 5, "61093": 5, "61094": 5, "61101": 5, "61102": 5, "61103": 5, "61104": 5, "61111": 5, "61112": 5, "61113": 5, "61114": 5, "61121": 5, "61122": 5, "61123": 5, "61124": 5, "63015": 5, "63016": 5, "63025": 5, "63026": 5, "63035": 5, "63036": 5, "63045": 5, "63046": 5, "63055": 5, "63056": 5, "63065": 5, "63066": 5, "63075": 5, "63076": 5, "63085": 5, "63086": 5}
|
@ -0,0 +1 @@
|
||||
{"100101": "Normal", "100103": "Ultra", "100104": "", "100106": "MazeNormal", "100107": "Maze", "100201": "Normal", "100202": "BPSkill", "100203": "Ultra", "100204": "", "100206": "MazeNormal", "100207": "Maze", "100302": "BPSkill", "100306": "MazeNormal", "100307": "Maze", "100401": "Normal", "100402": "BPSkill", "100404": "", "100406": "MazeNormal", "100501": "Normal", "100502": "BPSkill", "100503": "Ultra", "100504": "", "100506": "MazeNormal", "100507": "Maze", "100801": "Normal", "100802": "BPSkill", "100803": "Ultra", "100804": "", "100806": "MazeNormal", "100807": "Maze", "100901": "Normal", "100902": "BPSkill", "100903": "Ultra", "100904": "", "100906": "MazeNormal", "100907": "Maze", "101301": "Normal", "101302": "BPSkill", "101303": "Ultra", "101304": "", "101306": "MazeNormal", "101307": "Maze", "110101": "Normal", "110102": "BPSkill", "110103": "Ultra", "110104": "", "110106": "MazeNormal", "110107": "Maze", "110203": "Ultra", "110206": "MazeNormal", "110207": "Maze", "110301": "Normal", "110302": "BPSkill", "110303": "Ultra", "110304": "", "110306": "MazeNormal", "110307": "Maze", "110401": "Normal", "110402": "BPSkill", "110403": "Ultra", "110404": "", "110406": "MazeNormal", "110407": "Maze", "110501": "Normal", "110502": "BPSkill", "110503": "Ultra", "110506": "MazeNormal", "110601": "Normal", "110602": "BPSkill", "110604": "", "110606": "MazeNormal", "110607": "Maze", "110801": "Normal", "110802": "BPSkill", "110803": "Ultra", "110806": "MazeNormal", "110807": "Maze", "110901": "Normal", "110902": "BPSkill", "110903": "Ultra", "110904": "", "110906": "MazeNormal", "110907": "Maze", "110909": "BPSkill", "120101": "Normal", "120108": "Normal", "120103": "Ultra", "120104": "", "120106": "MazeNormal", "120107": "Maze", "120201": "Normal", "120206": "MazeNormal", "120207": "Maze", "120301": "Normal", "120302": "BPSkill", "120303": "Ultra", "120304": "", "120306": "MazeNormal", "120307": "Maze", "120601": "Normal", "120602": "BPSkill", "120603": "Ultra", "120604": "", "120606": "MazeNormal", "120607": "Maze", "120901": "Normal", "120902": "BPSkill", "120903": "Ultra", "120904": "", "120906": "MazeNormal", "120907": "Maze", "121101": "Normal", "121102": "BPSkill", "121103": "Ultra", "121106": "MazeNormal", "121107": "Maze", "800101": "Normal", "800102": "BPSkill", "800103": "Ultra", "800104": "", "800106": "MazeNormal", "800107": "Maze", "800108": "Ultra", "800109": "Ultra", "800201": "Normal", "800202": "BPSkill", "800203": "Ultra", "800204": "", "800206": "MazeNormal", "800207": "Maze", "800208": "Ultra", "800209": "Ultra", "800301": "Normal", "800308": "Normal", "800303": "Ultra", "800304": "", "800306": "MazeNormal", "800307": "Maze", "800401": "Normal", "800408": "Normal", "800403": "Ultra", "800404": "", "800406": "MazeNormal", "800407": "Maze", "100601": "Normal", "100602": "BPSkill", "100603": "Ultra", "100604": "", "100606": "MazeNormal", "100607": "Maze", "120401": "Normal", "120402": "BPSkill", "120403": "Ultra", "120404": "", "120406": "MazeNormal", "909807": "Maze", "110603": "Ultra", "110507": "Maze", "800402": "BPSkill", "800302": "BPSkill", "120202": "BPSkill", "120204": "", "110804": "", "110504": "", "110202": "BPSkill", "110204": "", "100301": "Normal", "100304": "", "100303": "Ultra", "110701": "Normal", "110702": "BPSkill", "110703": "Ultra", "110704": "", "110706": "MazeNormal", "110707": "Maze", "110201": "Normal", "121104": "", "120407": "Maze", "100407": "Maze", "120102": "BPSkill", "100102": "BPSkill", "120203": "Ultra", "100403": "Ultra"}
|
@ -14,6 +14,7 @@ CHAR_ICON_PATH = RESOURCE_PATH / 'character'
|
||||
WEAPON_PATH = RESOURCE_PATH / 'light_cone'
|
||||
CHAR_PORTRAIT = RESOURCE_PATH / 'character_portrait'
|
||||
SKILL_PATH = RESOURCE_PATH / 'skill'
|
||||
RELIC_PATH = RESOURCE_PATH / 'relic'
|
||||
TEXT2D_PATH = Path(__file__).parent / 'texture2d'
|
||||
|
||||
|
||||
@ -29,6 +30,7 @@ def init_dir():
|
||||
TEMP_PATH,
|
||||
CHAR_PORTRAIT,
|
||||
SKILL_PATH,
|
||||
RELIC_PATH,
|
||||
]:
|
||||
i.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user