mirror of
https://github.com/KimigaiiWuyi/GenshinUID.git
synced 2025-05-07 20:45:49 +08:00
✨ 新增角色深渊详情可莉
(#499)
This commit is contained in:
parent
e32e1637a7
commit
0f2807c346
@ -3,7 +3,6 @@ from pathlib import Path
|
||||
from typing import Union
|
||||
|
||||
from PIL import Image, ImageDraw
|
||||
|
||||
from gsuid_core.logger import logger
|
||||
|
||||
from .gs_config import gsconfig
|
||||
|
@ -9,6 +9,10 @@ from ..genshinuid_xkdata import draw_xk_abyss_img
|
||||
from ..genshinuid_help.draw_help_card import draw_help_img
|
||||
from ..genshinuid_guide.get_abyss_data import generate_data
|
||||
from ..utils.resource.generate_char_card import create_all_char_card
|
||||
from ..genshinuid_xkdata.get_all_char_data import (
|
||||
save_all_char_info,
|
||||
save_all_abyss_rank,
|
||||
)
|
||||
|
||||
|
||||
async def all_start():
|
||||
@ -19,6 +23,8 @@ async def all_start():
|
||||
await create_all_char_card()
|
||||
await draw_xk_abyss_img()
|
||||
await generate_data()
|
||||
await save_all_char_info()
|
||||
await save_all_abyss_rank()
|
||||
except Exception as e:
|
||||
logger.exception(e)
|
||||
|
||||
|
@ -6,11 +6,10 @@ from http.cookies import SimpleCookie
|
||||
from typing import Any, List, Tuple, Union, Literal
|
||||
|
||||
import qrcode
|
||||
from qrcode.constants import ERROR_CORRECT_L
|
||||
|
||||
from gsuid_core.bot import Bot
|
||||
from gsuid_core.models import Event
|
||||
from gsuid_core.logger import logger
|
||||
from qrcode.constants import ERROR_CORRECT_L
|
||||
from gsuid_core.segment import MessageSegment
|
||||
|
||||
from ..utils.mys_api import mys_api
|
||||
|
@ -7,6 +7,7 @@ from gsuid_core.models import Event
|
||||
from gsuid_core.aps import scheduler
|
||||
|
||||
from ..utils.image.convert import convert_img
|
||||
from .draw_char_abyss import draw_char_abyss_info
|
||||
from .draw_abyss_total import TOTAL_IMG, draw_xk_abyss_img
|
||||
from .get_all_char_data import save_all_char_info, save_all_abyss_rank
|
||||
|
||||
@ -32,3 +33,9 @@ async def send_abyss_pic(bot: Bot, ev: Event):
|
||||
img = await convert_img(TOTAL_IMG)
|
||||
await bot.logger.info('获得深渊概览图片成功!')
|
||||
await bot.send(img)
|
||||
|
||||
|
||||
@sv_get_abyss_database.on_prefix(('角色深渊详情', '角色深渊'), block=True)
|
||||
async def send_char_abyss_pic(bot: Bot, ev: Event):
|
||||
im = await draw_char_abyss_info(ev.text)
|
||||
await bot.send(im)
|
||||
|
140
GenshinUID/genshinuid_xkdata/draw_char_abyss.py
Normal file
140
GenshinUID/genshinuid_xkdata/draw_char_abyss.py
Normal file
@ -0,0 +1,140 @@
|
||||
from pathlib import Path
|
||||
from typing import Union
|
||||
|
||||
from PIL import Image, ImageDraw
|
||||
|
||||
from ..utils.image.convert import convert_img
|
||||
from ..utils.map.GS_MAP_PATH import artifact2attr
|
||||
from .get_all_char_data import get_akasha_char_data
|
||||
from ..utils.fonts.genshin_fonts import gs_font_20, gs_font_40
|
||||
from ..utils.image.image_tools import get_color_bg, draw_pic_with_ring
|
||||
from ..utils.resource.generate_char_card import create_single_item_card
|
||||
from ..utils.map.name_covert import name_to_avatar_id, alias_to_char_name
|
||||
from ..utils.resource.RESOURCE_PATH import REL_PATH, CHAR_PATH, WEAPON_PATH
|
||||
|
||||
black = (10, 10, 10)
|
||||
grey = (40, 40, 40)
|
||||
|
||||
green = (205, 255, 168)
|
||||
red = (255, 168, 168)
|
||||
|
||||
TEXT_PATH = Path(__file__).parent / 'texture2d'
|
||||
|
||||
rank_dict = {
|
||||
90: (189, 64, 64),
|
||||
80: (189, 64, 148),
|
||||
60: (95, 64, 189),
|
||||
40: (64, 140, 189),
|
||||
20: (64, 189, 125),
|
||||
0: (200, 200, 200),
|
||||
}
|
||||
|
||||
|
||||
async def draw_char_abyss_info(char_name: str) -> Union[bytes, str]:
|
||||
char_name = await alias_to_char_name(char_name)
|
||||
char_id = await name_to_avatar_id(char_name)
|
||||
# _char_id = char_id[1:].lstrip('0')
|
||||
char_useage_rank = []
|
||||
char_img = Image.open(CHAR_PATH / f'{char_id}.png')
|
||||
char_pic = await draw_pic_with_ring(char_img, 264)
|
||||
|
||||
_data = await get_akasha_char_data(char_name)
|
||||
if _data is None:
|
||||
return '没有该角色的数据...'
|
||||
|
||||
all_char_info, char_useage_rank = _data[0], _data[1]
|
||||
|
||||
char_useage_rank.sort(key=lambda d: int(d['v']))
|
||||
|
||||
title_bg = Image.open(TEXT_PATH / 'title_bg.png')
|
||||
|
||||
# 计算宽高
|
||||
h = 1080 + len(char_useage_rank) * 30
|
||||
|
||||
# 开始绘图
|
||||
img = await get_color_bg(900, h, '_abyss_char')
|
||||
_img = Image.new('RGBA', img.size)
|
||||
img.paste(char_pic, (300, 118), char_pic)
|
||||
img.paste(title_bg, (0, 400), title_bg)
|
||||
|
||||
# 基础文字部分
|
||||
img_draw = ImageDraw.Draw(_img)
|
||||
img_draw.text((450, 450), f'{char_name}的深渊统计', 'White', gs_font_40, 'mm')
|
||||
|
||||
# 绘图
|
||||
r = 20
|
||||
bg_color = (255, 255, 255, 120)
|
||||
img_draw.rounded_rectangle((24, 538, 876, 746), r, bg_color)
|
||||
img_draw.rounded_rectangle((24, 761, 876, 969), r, bg_color)
|
||||
img_draw.rounded_rectangle((24, 988, 876, h - 40), r, bg_color)
|
||||
|
||||
_start = 1020
|
||||
bar_bg = (0, 0, 0, 128)
|
||||
|
||||
for index, rank in enumerate(char_useage_rank):
|
||||
_intent = _start + index * 30
|
||||
y1, y2 = _intent + 9, _intent + 23
|
||||
img_draw.rounded_rectangle((108, y1, 708, y2), r, bar_bg)
|
||||
|
||||
d = float(rank["d"])
|
||||
_pixel = int((d / 100) * 600)
|
||||
for _p in rank_dict:
|
||||
if d >= _p:
|
||||
fill = rank_dict[_p]
|
||||
break
|
||||
else:
|
||||
fill = (255, 255, 255)
|
||||
img_draw.rounded_rectangle((108, y1, 108 + _pixel, y2), r, fill)
|
||||
|
||||
value = f'{rank["d"]}% / {rank["r"]}名'
|
||||
img_draw.text(
|
||||
(37, 16 + _intent), f'版本{rank["v"]}', 'Black', gs_font_20, 'lm'
|
||||
)
|
||||
img_draw.text((730, 16 + _intent), value, 'Black', gs_font_20, 'lm')
|
||||
|
||||
img.paste(_img, (0, 0), _img)
|
||||
|
||||
# 开始
|
||||
for index, weapon in enumerate(all_char_info['weapons']):
|
||||
if weapon['name'] == '渔获':
|
||||
weapon_name = '「渔获」'
|
||||
else:
|
||||
weapon_name = weapon['name']
|
||||
weapon_img = Image.open(WEAPON_PATH / f'{weapon_name}.png')
|
||||
item = await create_single_item_card(weapon_img, weapon['rarity'])
|
||||
item_draw = ImageDraw.Draw(item)
|
||||
weapon_rate = weapon['rate'] + '%'
|
||||
item_draw.text((128, 280), weapon_rate, 'Black', gs_font_40, 'mm')
|
||||
item = item.resize((128, 155))
|
||||
img.paste(item, (47 + 135 * index, 565), item)
|
||||
if index >= 5:
|
||||
break
|
||||
|
||||
for index, equip in enumerate(all_char_info['equips']):
|
||||
item_list = []
|
||||
item_type = 0
|
||||
for set in equip['set_list']:
|
||||
for part in artifact2attr:
|
||||
if artifact2attr[part] == set['name']:
|
||||
part_name = part
|
||||
break
|
||||
else:
|
||||
part_name = '冰风迷途的勇士'
|
||||
item = Image.open(REL_PATH / f'{part_name}.png')
|
||||
item_list.append(item)
|
||||
item_type += int(set['count'])
|
||||
|
||||
item = await create_single_item_card(item_list, '5')
|
||||
|
||||
item_draw = ImageDraw.Draw(item)
|
||||
equip_rate = equip['rate'] + '%'
|
||||
item_draw.text((128, 280), equip_rate, 'Black', gs_font_40, 'mm')
|
||||
|
||||
item_draw.rounded_rectangle((200, 20, 240, 60), 15, (255, 255, 255))
|
||||
item_draw.text((220, 40), f'{item_type}', 'Black', gs_font_40, 'mm')
|
||||
|
||||
item = item.resize((128, 155))
|
||||
img.paste(item, (47 + 135 * index, 788), item)
|
||||
if index >= 5:
|
||||
break
|
||||
return await convert_img(img)
|
@ -22,13 +22,13 @@ abyss_rank_path = DATA_PATH / 'abyss_rank.json'
|
||||
async def save_all_char_info():
|
||||
all_char_info = await get_akasha_all_char_info()
|
||||
async with aiofiles.open(all_char_info_path, 'w') as f:
|
||||
await f.write(str(all_char_info))
|
||||
await f.write(json.dumps(all_char_info))
|
||||
|
||||
|
||||
async def save_all_abyss_rank():
|
||||
abyss_rank = await get_akasha_abyss_rank()
|
||||
async with aiofiles.open(abyss_rank_path, 'w') as f:
|
||||
await f.write(str(abyss_rank))
|
||||
await f.write(json.dumps(abyss_rank))
|
||||
|
||||
|
||||
async def get_akasha_char_data(
|
||||
@ -52,7 +52,7 @@ async def get_akasha_char_data(
|
||||
if not char_id:
|
||||
return None
|
||||
|
||||
_char_id = char_id.lstrip('100000').strip('0')
|
||||
_char_id = char_id.lstrip('1').lstrip('0')
|
||||
if _char_id not in all_char_info:
|
||||
return None
|
||||
|
||||
|
BIN
GenshinUID/genshinuid_xkdata/texture2d/title_bg.png
Normal file
BIN
GenshinUID/genshinuid_xkdata/texture2d/title_bg.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.6 KiB |
BIN
GenshinUID/utils/image/bg/sp_bg/_abyss_char.jpg
Normal file
BIN
GenshinUID/utils/image/bg/sp_bg/_abyss_char.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 109 KiB |
@ -1,4 +1,4 @@
|
||||
from typing import Union
|
||||
from typing import List, Union
|
||||
|
||||
from PIL import Image
|
||||
from gsuid_core.logger import logger
|
||||
@ -9,6 +9,32 @@ from .RESOURCE_PATH import CHAR_PATH, TEXT2D_PATH, CHAR_CARD_PATH
|
||||
texture2d_path = TEXT2D_PATH / 'char_card'
|
||||
|
||||
|
||||
async def create_single_item_card(
|
||||
item_img: Union[List[Image.Image], Image.Image], star: Union[int, str]
|
||||
) -> Image.Image:
|
||||
if isinstance(item_img, List):
|
||||
img = Image.new('RGBA', (256, 256))
|
||||
for i, item in enumerate(item_img):
|
||||
_intent = int(128 / (i + 1))
|
||||
_intent2 = int((256 + (128 * (len(item_img) - 1))) / len(item_img))
|
||||
item = item.resize((_intent2, _intent2))
|
||||
img.paste(item, (128 - _intent, 128 - _intent), item)
|
||||
item_img = img
|
||||
|
||||
if item_img.size != (256, 256):
|
||||
item_img = item_img.resize((256, 256))
|
||||
char_frame = Image.open(texture2d_path / 'frame.png')
|
||||
char_bg = Image.open(texture2d_path / f'star{star}bg.png')
|
||||
mask = Image.open(texture2d_path / 'mask.png')
|
||||
img = Image.new('RGBA', (256, 310))
|
||||
img_mask = Image.new('RGBA', (256, 310))
|
||||
img_mask.paste(char_bg, (0, 0), char_bg)
|
||||
img_mask.paste(item_img, (0, 0), item_img)
|
||||
img_mask.paste(char_frame, (0, 0), char_frame)
|
||||
img.paste(img_mask, (0, 0), mask)
|
||||
return img
|
||||
|
||||
|
||||
async def create_single_char_card(char_id: Union[str, int]) -> Image.Image:
|
||||
if str(char_id) not in avatarId2Star_data:
|
||||
logger.warning(f'资源文件夹发现异常图片{char_id}....忽略加载...')
|
||||
|
BIN
GenshinUID/utils/resource/texture2d/char_card/star1bg.png
Normal file
BIN
GenshinUID/utils/resource/texture2d/char_card/star1bg.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
BIN
GenshinUID/utils/resource/texture2d/char_card/star2bg.png
Normal file
BIN
GenshinUID/utils/resource/texture2d/char_card/star2bg.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 31 KiB |
BIN
GenshinUID/utils/resource/texture2d/char_card/star3bg.png
Normal file
BIN
GenshinUID/utils/resource/texture2d/char_card/star3bg.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 31 KiB |
Loading…
x
Reference in New Issue
Block a user