支持2.4

This commit is contained in:
baiqwerdvd 2024-07-31 17:11:18 +08:00
parent be48f78136
commit 7b9167d5c2
No known key found for this signature in database
GPG Key ID: 7717E46E1797411A
45 changed files with 57474 additions and 52252 deletions

View File

@ -2,7 +2,7 @@
"python.languageServer": "None", "python.languageServer": "None",
"editor.formatOnSave": true, "editor.formatOnSave": true,
"[python]": { "[python]": {
"editor.defaultFormatter": "ms-python.black-formatter", "editor.defaultFormatter": "charliermarsh.ruff",
"editor.formatOnSave": true, "editor.formatOnSave": true,
"editor.codeActionsOnSave": { "editor.codeActionsOnSave": {
"source.organizeImports": "explicit" "source.organizeImports": "explicit"
@ -18,4 +18,4 @@
"basedpyright.analysis.extraPaths": [ "basedpyright.analysis.extraPaths": [
"${workspaceFolder}/../../../" "${workspaceFolder}/../../../"
], ],
} }

View File

@ -1,5 +1,5 @@
"""Mihomo.me api 包装 """Mihomo.me api 包装"""
"""
from .models import MihomoData as MihomoData from .models import MihomoData as MihomoData
from .requests import get_char_card_info as requests from .requests import get_char_card_info as requests

View File

@ -0,0 +1,46 @@
from typing import TYPE_CHECKING
from ..utils.convert import get_uid
from ..utils.error_reply import UID_HINT
from ..utils.map.name_covert import (
alias_to_char_name,
name_to_avatar_id,
)
from ..utils.mys_api import mys_api
from ..utils.sr_prefix import PREFIX
from gsuid_core.sv import SV
from gsuid_core.utils.error_reply import get_error
if TYPE_CHECKING:
from gsuid_core.bot import Bot
from gsuid_core.models import Event
sv_char_calc = SV('sr养成计算')
@sv_char_calc.on_command(f'{PREFIX}养成计算', block=True)
async def send_char_calc_info(bot: 'Bot', ev: 'Event'):
name = ev.text.strip()
char_id = await name_to_avatar_id(name)
if char_id == '':
result_fake_name = await alias_to_char_name(name)
if result_fake_name is None:
return '请输入正确的角色名'
fake_name = result_fake_name
char_id = await name_to_avatar_id(fake_name)
uid = await get_uid(bot, ev, only_uid=True)
if uid is None:
return await bot.send(UID_HINT)
avatar_detail = await mys_api.get_avatar_detail(uid, str(char_id))
if isinstance(avatar_detail, int):
return get_error(avatar_detail)
avatar_skills = avatar_detail.skills + avatar_detail.skills_other
skill_list = []
for skill in avatar_skills:
skill_list.append(
f'{skill.point_id}({skill.cur_level}/{skill.max_level})'
)
return None

View File

@ -95,7 +95,9 @@ RELIC_CNT = {
} }
async def draw_char_img(char_data: Dict, sr_uid: str, msg: str) -> Union[bytes, str]: async def draw_char_img(
char_data: Dict, sr_uid: str, msg: str
) -> Union[bytes, str]:
if isinstance(char_data, str): if isinstance(char_data, str):
return char_data return char_data
char = await cal_char_info(char_data) char = await cal_char_info(char_data)
@ -132,7 +134,9 @@ async def draw_char_img(char_data: Dict, sr_uid: str, msg: str) -> Union[bytes,
# 放角色名 # 放角色名
char_img_draw = ImageDraw.Draw(char_info) char_img_draw = ImageDraw.Draw(char_info)
char_img_draw.text((620, 162), char.char_name, (255, 255, 255), sr_font_38, 'lm') char_img_draw.text(
(620, 162), char.char_name, (255, 255, 255), sr_font_38, 'lm'
)
if hasattr(sr_font_38, 'getsize'): if hasattr(sr_font_38, 'getsize'):
char_name_len = sr_font_38.getsize(char.char_name)[0] # type: ignore char_name_len = sr_font_38.getsize(char.char_name)[0] # type: ignore
else: else:
@ -184,7 +188,9 @@ async def draw_char_img(char_data: Dict, sr_uid: str, msg: str) -> Union[bytes,
0, 0,
) )
) )
attr_bg_draw.text((413, 31), f'{hp + add_hp}', white_color, sr_font_26, 'rm') attr_bg_draw.text(
(413, 31), f'{hp + add_hp}', white_color, sr_font_26, 'rm'
)
attr_bg_draw.text( attr_bg_draw.text(
(428, 31), (428, 31),
f'(+{round(add_hp)!s})', f'(+{round(add_hp)!s})',
@ -275,7 +281,9 @@ async def draw_char_img(char_data: Dict, sr_uid: str, msg: str) -> Union[bytes,
'rm', 'rm',
) )
# 效果命中 # 效果命中
status_probability_base = char.add_attr.get('StatusProbabilityBase', 0) * 100 status_probability_base = (
char.add_attr.get('StatusProbabilityBase', 0) * 100
)
attr_bg_draw.text( attr_bg_draw.text(
(500, 31 + 48 * 6), (500, 31 + 48 * 6),
f'{status_probability_base:.1f}%', f'{status_probability_base:.1f}%',
@ -293,7 +301,9 @@ async def draw_char_img(char_data: Dict, sr_uid: str, msg: str) -> Union[bytes,
'rm', 'rm',
) )
# 击破特攻 # 击破特攻
status_resistance_base = char.add_attr.get('BreakDamageAddedRatioBase', 0) * 100 status_resistance_base = (
char.add_attr.get('BreakDamageAddedRatioBase', 0) * 100
)
attr_bg_draw.text( attr_bg_draw.text(
(500, 31 + 48 * 8), (500, 31 + 48 * 8),
f'{status_resistance_base:.1f}%', f'{status_resistance_base:.1f}%',
@ -409,7 +419,8 @@ async def draw_char_img(char_data: Dict, sr_uid: str, msg: str) -> Union[bytes,
weapon_bg.paste(rank_img, (weapon_name_len + 330, 2), rank_img) weapon_bg.paste(rank_img, (weapon_name_len + 330, 2), rank_img)
rarity_img = Image.open( rarity_img = Image.open(
TEXT_PATH / f'LightCore_Rarity{char.equipment["equipmentRarity"]}.png' TEXT_PATH
/ f'LightCore_Rarity{char.equipment["equipmentRarity"]}.png'
).resize((306, 72)) ).resize((306, 72))
weapon_bg.paste(rarity_img, (223, 55), rarity_img) weapon_bg.paste(rarity_img, (223, 55), rarity_img)
weapon_bg_draw.text( weapon_bg_draw.text(
@ -422,9 +433,9 @@ async def draw_char_img(char_data: Dict, sr_uid: str, msg: str) -> Union[bytes,
# 武器技能 # 武器技能
desc = light_cone_ranks[str(char.equipment['equipmentID'])]['desc'] desc = light_cone_ranks[str(char.equipment['equipmentID'])]['desc']
desc_params = light_cone_ranks[str(char.equipment['equipmentID'])]['params'][ desc_params = light_cone_ranks[str(char.equipment['equipmentID'])][
char.equipment['equipmentRank'] - 1 'params'
] ][char.equipment['equipmentRank'] - 1]
for i in range(len(desc_params)): for i in range(len(desc_params)):
temp = math.floor(desc_params[i] * 1000) / 10 temp = math.floor(desc_params[i] * 1000) / 10
desc = desc.replace(f'#{i + 1}[i]%', f'{temp!s}%') desc = desc.replace(f'#{i + 1}[i]%', f'{temp!s}%')
@ -594,7 +605,9 @@ async def draw_char_img(char_data: Dict, sr_uid: str, msg: str) -> Union[bytes,
anchor='rm', anchor='rm',
) )
char_info.paste(relic_img, RELIC_POS[str(relic['Type'])], relic_img) char_info.paste(
relic_img, RELIC_POS[str(relic['Type'])], relic_img
)
relic_score += single_relic_score relic_score += single_relic_score
if relic_score > 210: if relic_score > 210:
relic_value_level = Image.open(TEXT_PATH / 'CommonIconSSS.png') relic_value_level = Image.open(TEXT_PATH / 'CommonIconSSS.png')
@ -666,7 +679,9 @@ async def draw_char_img(char_data: Dict, sr_uid: str, msg: str) -> Union[bytes,
damage_img = Image.open(TEXT_PATH / 'attack_1.png') damage_img = Image.open(TEXT_PATH / 'attack_1.png')
else: else:
damage_img = Image.open(TEXT_PATH / 'attack_2.png') damage_img = Image.open(TEXT_PATH / 'attack_2.png')
char_info.paste(damage_img, (0, 2028 + damage_num * 48), damage_img) char_info.paste(
damage_img, (0, 2028 + damage_num * 48), damage_img
)
char_img_draw.text( char_img_draw.text(
(55, 2048 + damage_num * 48), (55, 2048 + damage_num * 48),
f'{damage_info["name"]}', f'{damage_info["name"]}',
@ -821,7 +836,9 @@ async def get_relic_score(
add_value = subValue * 0.3 * 0.5 * weight_dict['AttackDelta'] * 1.0 add_value = subValue * 0.3 * 0.5 * weight_dict['AttackDelta'] * 1.0
relic_score += add_value relic_score += add_value
if subProperty == 'DefenceDelta': if subProperty == 'DefenceDelta':
add_value = subValue * 0.3 * 0.5 * weight_dict['DefenceDelta'] * 1.0 add_value = (
subValue * 0.3 * 0.5 * weight_dict['DefenceDelta'] * 1.0
)
relic_score += add_value relic_score += add_value
if subProperty == 'HPDelta': if subProperty == 'HPDelta':
add_value = subValue * 0.158 * 0.5 * weight_dict['HPDelta'] * 1.0 add_value = subValue * 0.158 * 0.5 * weight_dict['HPDelta'] * 1.0
@ -830,7 +847,9 @@ async def get_relic_score(
add_value = subValue * 1.5 * weight_dict['AttackAddedRatio'] * 100 add_value = subValue * 1.5 * weight_dict['AttackAddedRatio'] * 100
relic_score += add_value relic_score += add_value
if subProperty == 'DefenceAddedRatio': if subProperty == 'DefenceAddedRatio':
add_value = subValue * 1.19 * weight_dict['DefenceAddedRatio'] * 100 add_value = (
subValue * 1.19 * weight_dict['DefenceAddedRatio'] * 100
)
relic_score += add_value relic_score += add_value
if subProperty == 'HPAddedRatio': if subProperty == 'HPAddedRatio':
add_value = subValue * 1.5 * weight_dict['HPAddedRatio'] * 100 add_value = subValue * 1.5 * weight_dict['HPAddedRatio'] * 100
@ -839,12 +858,18 @@ async def get_relic_score(
add_value = subValue * 2.53 * weight_dict['SpeedDelta'] add_value = subValue * 2.53 * weight_dict['SpeedDelta']
relic_score += add_value relic_score += add_value
if subProperty == 'BreakDamageAddedRatioBase': if subProperty == 'BreakDamageAddedRatioBase':
add_value = subValue * 1.0 * weight_dict['BreakDamageAddedRatioBase'] * 100 add_value = (
subValue * 1.0 * weight_dict['BreakDamageAddedRatioBase'] * 100
)
relic_score += add_value relic_score += add_value
if subProperty == 'StatusProbabilityBase': if subProperty == 'StatusProbabilityBase':
add_value = subValue * 1.49 * weight_dict['StatusProbabilityBase'] * 100 add_value = (
subValue * 1.49 * weight_dict['StatusProbabilityBase'] * 100
)
relic_score += add_value relic_score += add_value
if subProperty == 'StatusResistanceBase': if subProperty == 'StatusResistanceBase':
add_value = subValue * 1.49 * weight_dict['StatusResistanceBase'] * 100 add_value = (
subValue * 1.49 * weight_dict['StatusResistanceBase'] * 100
)
relic_score += add_value relic_score += add_value
return relic_score return relic_score

View File

@ -97,11 +97,7 @@ async def get_char_args(
char_data = {} char_data = {}
weapon, weapon_affix = None, None weapon, weapon_affix = None, None
msg = ( msg = msg.replace('', '').replace('', '').replace('圣遗物', '遗器')
msg.replace('', '')
.replace('', '')
.replace('圣遗物', '遗器')
)
# 希儿带于夜色中换1000xxxx6希儿头 # 希儿带于夜色中换1000xxxx6希儿头
msg_list = msg.split('') msg_list = msg.split('')
@ -132,13 +128,17 @@ async def get_char_args(
if isinstance(char_data, str): if isinstance(char_data, str):
return char_data return char_data
else: else:
for i, s in enumerate(['头部', '手部', '躯干', '腿部', '位面球', '连结绳']): for i, s in enumerate(
['头部', '手部', '躯干', '腿部', '位面球', '连结绳']
):
if '赤沙' in part: if '赤沙' in part:
continue continue
if part[-1] in PieceName_ilst[i]: if part[-1] in PieceName_ilst[i]:
if isinstance(char_data, str): if isinstance(char_data, str):
return char_data return char_data
char_data = await change_equip(changeuid, char_data, part, s, i) char_data = await change_equip(
changeuid, char_data, part, s, i
)
if not char_data: if not char_data:
change_name = part.replace(part[-1], '') change_name = part.replace(part[-1], '')
return f'要替换的{change_name}{s}遗器不存在噢~' return f'要替换的{change_name}{s}遗器不存在噢~'
@ -149,7 +149,9 @@ async def get_char_args(
return char_data, weapon, weapon_affix, talent_num return char_data, weapon, weapon_affix, talent_num
async def change_equip(uid: str, char_data: Dict, part: str, s: str, i: int) -> Dict: async def change_equip(
uid: str, char_data: Dict, part: str, s: str, i: int
) -> Dict:
char_name = part.replace(part[-1], '').replace(uid, '') char_name = part.replace(part[-1], '').replace(uid, '')
fake_data = await get_char_data(uid, char_name) fake_data = await get_char_data(uid, char_name)
if isinstance(fake_data, str): if isinstance(fake_data, str):
@ -176,7 +178,9 @@ async def get_fake_char_str(char_name: str) -> Tuple[str, Optional[int]]:
""" """
talent_num = None talent_num = None
if ('' in char_name or '' in char_name) and char_name[0] in CHAR_TO_INT: if ('' in char_name or '' in char_name) and char_name[
0
] in CHAR_TO_INT:
talent_num = CHAR_TO_INT[char_name[0]] talent_num = CHAR_TO_INT[char_name[0]]
char_name = char_name[2:] char_name = char_name[2:]
return char_name, talent_num return char_name, talent_num
@ -258,18 +262,28 @@ async def make_new_charinfo(
char_id = await name_to_avatar_id(fake_name) char_id = await name_to_avatar_id(fake_name)
char_data['avatarId'] = int(char_id) char_data['avatarId'] = int(char_id)
char_data['avatarName'] = fake_name char_data['avatarName'] = fake_name
char_data['avatarElement'] = avatarId2DamageType[str(char_data['avatarId'])] char_data['avatarElement'] = avatarId2DamageType[
char_data['avatarRarity'] = str(avatarId2Rarity[str(char_data['avatarId'])]) str(char_data['avatarId'])
]
char_data['avatarRarity'] = str(
avatarId2Rarity[str(char_data['avatarId'])]
)
char_data['avatarPromotion'] = 6 char_data['avatarPromotion'] = 6
char_data['avatarLevel'] = 80 char_data['avatarLevel'] = 80
char_data['avatarSkill'] = await get_skill_list(char_data['avatarId']) char_data['avatarSkill'] = await get_skill_list(char_data['avatarId'])
char_data['avatarExtraAbility'] = await get_extra_list(char_data['avatarId']) char_data['avatarExtraAbility'] = await get_extra_list(
char_data['avatarAttributeBonus'] = await get_attribute_list(char_data['avatarId']) char_data['avatarId']
)
char_data['avatarAttributeBonus'] = await get_attribute_list(
char_data['avatarId']
)
char_data['RelicInfo'] = [] char_data['RelicInfo'] = []
char_data['avatarEnName'] = avatarId2EnName[str(char_data['avatarId'])] char_data['avatarEnName'] = avatarId2EnName[str(char_data['avatarId'])]
char_data['rank'] = 0 char_data['rank'] = 0
char_data['rankList'] = [] char_data['rankList'] = []
char_data['baseAttributes'] = await get_baseAttributes(char_data['avatarId']) char_data['baseAttributes'] = await get_baseAttributes(
char_data['avatarId']
)
char_data['equipmentInfo'] = {} char_data['equipmentInfo'] = {}
return char_data return char_data
@ -299,9 +313,13 @@ async def get_baseAttributes(
# 速度 # 速度
base_attributes['speed'] = avatar_promotion_base.SpeedBase.Value base_attributes['speed'] = avatar_promotion_base.SpeedBase.Value
# 暴击率 # 暴击率
base_attributes['CriticalChanceBase'] = avatar_promotion_base.CriticalChance.Value base_attributes['CriticalChanceBase'] = (
avatar_promotion_base.CriticalChance.Value
)
# 暴击伤害 # 暴击伤害
base_attributes['CriticalDamageBase'] = avatar_promotion_base.CriticalDamage.Value base_attributes['CriticalDamageBase'] = (
avatar_promotion_base.CriticalDamage.Value
)
# 嘲讽 # 嘲讽
base_attributes['BaseAggro'] = avatar_promotion_base.BaseAggro.Value base_attributes['BaseAggro'] = avatar_promotion_base.BaseAggro.Value
return base_attributes return base_attributes
@ -321,7 +339,9 @@ async def get_attribute_list(
attribute_bonus_temp['statusAdd'] = {} attribute_bonus_temp['statusAdd'] = {}
if status_add: if status_add:
for property_ in status_add: for property_ in status_add:
attribute_bonus_temp['statusAdd']['property'] = property_['type'] attribute_bonus_temp['statusAdd']['property'] = property_[
'type'
]
attribute_bonus_temp['statusAdd']['name'] = Property2Name[ attribute_bonus_temp['statusAdd']['name'] = Property2Name[
property_['type'] property_['type']
] ]
@ -351,7 +371,9 @@ async def get_skill_list(
skill_temp['skillId'] = char_id * 100 + skillid skill_temp['skillId'] = char_id * 100 + skillid
skill_temp['skillName'] = skillId2Name[str(skill_temp['skillId'])] skill_temp['skillName'] = skillId2Name[str(skill_temp['skillId'])]
skill_temp['skillEffect'] = skillId2Effect[str(skill_temp['skillId'])] skill_temp['skillEffect'] = skillId2Effect[str(skill_temp['skillId'])]
skill_temp['skillAttackType'] = skillId2AttackType[str(skill_temp['skillId'])] skill_temp['skillAttackType'] = skillId2AttackType[
str(skill_temp['skillId'])
]
skilllevel = 10 skilllevel = 10
if skillid == 1: if skillid == 1:
skilllevel = 6 skilllevel = 6
@ -404,7 +426,9 @@ async def get_char(
skill_id = item['id'] skill_id = item['id']
skill_up_num = item['num'] skill_up_num = item['num']
# 查找skill_id在不在avatarSkill中 # 查找skill_id在不在avatarSkill中
for index, skill_item in enumerate(char_data['avatarSkill']): for index, skill_item in enumerate(
char_data['avatarSkill']
):
if str(skill_id) == str(skill_item['skillId']): if str(skill_id) == str(skill_item['skillId']):
if skill_id[-1] == 1: if skill_id[-1] == 1:
skilllevel_max = 7 skilllevel_max = 7
@ -412,7 +436,9 @@ async def get_char(
skilllevel_max = 12 skilllevel_max = 12
skilllevel = min( skilllevel = min(
skilllevel_max, skilllevel_max,
char_data['avatarSkill'][index]['skillLevel'] char_data['avatarSkill'][index][
'skillLevel'
]
+ skill_up_num, + skill_up_num,
) )
char_data['avatarSkill'][index][ char_data['avatarSkill'][index][
@ -433,11 +459,13 @@ async def get_char(
equipment_info['equipmentLevel'] = 80 equipment_info['equipmentLevel'] = 80
equipment_info['equipmentPromotion'] = 6 equipment_info['equipmentPromotion'] = 6
equipment_info['equipmentRank'] = weapon_affix equipment_info['equipmentRank'] = weapon_affix
equipment_info['equipmentRarity'] = EquipmentID2Rarity[str(equipmentid)] equipment_info['equipmentRarity'] = EquipmentID2Rarity[
equipment_base_attributes = {} str(equipmentid)
equipment_promotion_base = EquipmentPromotionConfig.Equipment[str(equipmentid)][
'6'
] ]
equipment_base_attributes = {}
equipment_promotion_base = EquipmentPromotionConfig.Equipment[
str(equipmentid)
]['6']
# 生命值 # 生命值
equipment_base_attributes['hp'] = ( equipment_base_attributes['hp'] = (

View File

@ -62,7 +62,9 @@ async def draw_enka_card(uid: str, char_list: List, showfrom: int = 0):
return await convert_img(Image.new('RGBA', (0, 1), (255, 255, 255))) return await convert_img(Image.new('RGBA', (0, 1), (255, 255, 255)))
else: else:
line1 = f'UID {uid} 刷新成功' line1 = f'UID {uid} 刷新成功'
line2 = f'可以使用 sr查询{char_data_list[0]["avatarName"]} 查询详情角色面板' line2 = (
f'可以使用 sr查询{char_data_list[0]["avatarName"]} 查询详情角色面板'
)
char_num = len(char_data_list) char_num = len(char_data_list)
if char_num <= 4: if char_num <= 4:
based_w, based_h = 1380, 926 based_w, based_h = 1380, 926

View File

@ -1,12 +1,12 @@
from gsuid_core.sv import SV
from gsuid_core.bot import Bot
from gsuid_core.models import Event
from gsuid_core.logger import logger
from gsuid_core.utils.database.models import GsBind
from .set_config import set_config_func from .set_config import set_config_func
from ..starrailuid_config.sr_config import srconfig from ..starrailuid_config.sr_config import srconfig
from gsuid_core.bot import Bot
from gsuid_core.logger import logger
from gsuid_core.models import Event
from gsuid_core.sv import SV
from gsuid_core.utils.database.models import GsBind
PREFIX = srconfig.get_config('StarRailPrefix').data PREFIX = srconfig.get_config('StarRailPrefix').data
sv_self_config = SV('星穹铁道配置') sv_self_config = SV('星穹铁道配置')
@ -16,6 +16,9 @@ sv_self_config = SV('星穹铁道配置')
async def open_switch_func(bot: Bot, ev: Event): async def open_switch_func(bot: Bot, ev: Event):
uid = await GsBind.get_uid_by_game(ev.user_id, ev.bot_id, 'sr') uid = await GsBind.get_uid_by_game(ev.user_id, ev.bot_id, 'sr')
if uid is None: if uid is None:
return await bot.send('[星穹铁道] 你还没有绑定UID哦') return await bot.send('[星穹铁道] 你还没有绑定UID哦!')
logger.info(f'[{ev.user_id}] [UID{uid}]尝试[{ev.command[2:]}]了[{ev.text}]功能') logger.info(
f'[{ev.user_id}] [UID{uid}]尝试[{ev.command[2:]}]了[{ev.text}]功能'
)
await bot.send(await set_config_func(uid, ev)) await bot.send(await set_config_func(uid, ev))
return None

View File

@ -1,7 +1,7 @@
from gsuid_core.models import Event
from gsuid_core.logger import logger from gsuid_core.logger import logger
from gsuid_core.utils.database.models import GsUser from gsuid_core.models import Event
from gsuid_core.utils.database.config_switch import set_database_value from gsuid_core.utils.database.config_switch import set_database_value
from gsuid_core.utils.database.models import GsUser
async def set_config_func( async def set_config_func(
@ -11,11 +11,10 @@ async def set_config_func(
if '开启' in ev.command: if '开启' in ev.command:
if ev.user_type == 'direct': if ev.user_type == 'direct':
value = 'on' value = 'on'
elif ev.group_id:
value = ev.group_id
else: else:
if ev.group_id: value = 'on'
value = ev.group_id
else:
value = 'on'
else: else:
value = 'off' value = 'off'
@ -30,6 +29,5 @@ async def set_config_func(
) )
if text is None: if text is None:
return '[星穹铁道] 未找到配置项' return '[星穹铁道] 未找到配置项'
else: logger.success(f'[UID{uid}]成功将配置[SR自动签到]设置为[{value}]!')
logger.success(f'[UID{uid}]成功将配置[SR自动签到]设置为[{value}]!') return text
return text

View File

@ -70,7 +70,9 @@ async def get_role_img(uid: str) -> Union[bytes, str]:
return await draw_role_card(uid) return await draw_role_card(uid)
async def get_detail_img(qid: Union[str, int], uid: str, sender) -> Union[bytes, str]: async def get_detail_img(
qid: Union[str, int], uid: str, sender
) -> Union[bytes, str]:
return await get_detail_card(qid, uid, sender) return await get_detail_card(qid, uid, sender)

View File

@ -1,15 +1,15 @@
from gsuid_core.sv import SV
from gsuid_core.bot import Bot
from gsuid_core.models import Event
from gsuid_core.aps import scheduler
from gsuid_core.logger import logger
from gsuid_core.utils.database.models import GsBind
from gsuid_core.utils.sign.sign import sign_in, daily_sign
from gsuid_core.utils.boardcast.send_msg import send_board_cast_msg
from ..utils.sr_prefix import PREFIX
from ..utils.error_reply import UID_HINT
from ..starrailuid_config.sr_config import srconfig from ..starrailuid_config.sr_config import srconfig
from ..utils.error_reply import UID_HINT
from ..utils.sr_prefix import PREFIX
from gsuid_core.aps import scheduler
from gsuid_core.bot import Bot
from gsuid_core.logger import logger
from gsuid_core.models import Event
from gsuid_core.sv import SV
from gsuid_core.utils.boardcast.send_msg import send_board_cast_msg
from gsuid_core.utils.database.models import GsBind
from gsuid_core.utils.sign.sign import daily_sign, sign_in
SIGN_TIME = srconfig.get_config('SignTime').data SIGN_TIME = srconfig.get_config('SignTime').data
IS_REPORT = srconfig.get_config('PrivateSignReport').data IS_REPORT = srconfig.get_config('PrivateSignReport').data
@ -26,6 +26,7 @@ async def get_sign_func(bot: Bot, ev: Event):
return await bot.send(UID_HINT) return await bot.send(UID_HINT)
logger.info(f'[星穹铁道] [签到] UID: {uid}') logger.info(f'[星穹铁道] [签到] UID: {uid}')
await bot.send(await sign_in(uid, 'sr')) await bot.send(await sign_in(uid, 'sr'))
return None
@sv_sign_config.on_fullmatch(f'{PREFIX}全部重签') @sv_sign_config.on_fullmatch(f'{PREFIX}全部重签')

View File

@ -9,15 +9,13 @@ from gsuid_core.utils.database.models import GsBind
@overload @overload
async def get_uid( async def get_uid(
bot: Bot, ev: Event, get_user_id: bool = False, only_uid: bool = False bot: Bot, ev: Event, get_user_id: bool = False, only_uid: bool = False
) -> Optional[str]: ) -> Optional[str]: ...
...
@overload @overload
async def get_uid( async def get_uid(
bot: Bot, ev: Event, get_user_id: bool = True, only_uid: bool = False bot: Bot, ev: Event, get_user_id: bool = True, only_uid: bool = False
) -> Tuple[Optional[str], str]: ) -> Tuple[Optional[str], str]: ...
...
async def get_uid( async def get_uid(

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,14 +1,14 @@
from typing import Dict, List, Union from typing import Dict, List, Union
from msgspec import Struct
from .read_excel import ( from .read_excel import (
RelicSubAffix,
RelicMainAffix,
AvatarPromotion, AvatarPromotion,
EquipmentPromotion, EquipmentPromotion,
RelicMainAffix,
RelicSubAffix,
) )
from msgspec import Struct, convert
class PromotionCost(Struct): class PromotionCost(Struct):
ItemID: int ItemID: int
@ -71,205 +71,25 @@ class SingleRelicSubAffix(Struct):
StepNum: int StepNum: int
class AvatarPromotionConfigModel(Struct): # class AvatarPromotionConfigModel(Struct):
Avatar: Dict[str, Dict[str, SingleAvatarPromotion]] # Avatar: List[Dict[str, SingleAvatarPromotion]]
@classmethod
def from_json(cls, data: Dict):
return cls(
Avatar={
avatar_id: {
promotion: SingleAvatarPromotion(
AvatarID=promotion_dict[promotion]['AvatarID'],
Promotion=promotion_dict[promotion]['Promotion'],
PromotionCostList=[
PromotionCost(
ItemID=item['ItemID'], ItemNum=item['ItemNum']
)
for item in promotion_dict[promotion][
'PromotionCostList'
]
],
PlayerLevelRequire=promotion_dict[promotion].get(
'PlayerLevelRequire', None
),
WorldLevelRequire=promotion_dict[promotion].get(
'WorldLevelRequire', None
),
MaxLevel=promotion_dict[promotion]['MaxLevel'],
AttackBase=PromotionAttr(
Value=promotion_dict[promotion]['AttackBase'][
'Value'
]
),
AttackAdd=PromotionAttr(
Value=promotion_dict[promotion]['AttackAdd'][
'Value'
]
),
DefenceBase=PromotionAttr(
Value=promotion_dict[promotion]['DefenceBase'][
'Value'
]
),
DefenceAdd=PromotionAttr(
Value=promotion_dict[promotion]['DefenceAdd'][
'Value'
]
),
HPBase=PromotionAttr(
Value=promotion_dict[promotion]['HPBase']['Value']
),
HPAdd=PromotionAttr(
Value=promotion_dict[promotion]['HPAdd']['Value']
),
SpeedBase=PromotionAttr(
Value=promotion_dict[promotion]['SpeedBase'][
'Value'
]
),
CriticalChance=PromotionAttr(
Value=promotion_dict[promotion]['CriticalChance'][
'Value'
]
),
CriticalDamage=PromotionAttr(
Value=promotion_dict[promotion]['CriticalDamage'][
'Value'
]
),
BaseAggro=PromotionAttr(
Value=promotion_dict[promotion]['BaseAggro'][
'Value'
]
),
)
for promotion in promotion_dict.keys()
}
for avatar_id, promotion_dict in data.items()
}
)
class EquipmentPromotionConfigModel(Struct): # class EquipmentPromotionConfigModel(Struct):
Equipment: Dict[str, Dict[str, SingleEquipmentPromotion]] # Equipment: List[Dict[str, SingleEquipmentPromotion]]
@classmethod
def from_json(cls, data: Dict):
return cls(
Equipment={
equipment_id: {
promotion: SingleEquipmentPromotion(
EquipmentID=promotion_dict[promotion]['EquipmentID'],
Promotion=promotion_dict[promotion]['Promotion'],
PromotionCostList=[
PromotionCost(
ItemID=item['ItemID'], ItemNum=item['ItemNum']
)
for item in promotion_dict[promotion][
'PromotionCostList'
]
],
PlayerLevelRequire=promotion_dict[promotion].get(
'PlayerLevelRequire', None
),
WorldLevelRequire=promotion_dict[promotion].get(
'WorldLevelRequire', None
),
MaxLevel=promotion_dict[promotion]['MaxLevel'],
BaseHP=PromotionAttr(
Value=promotion_dict[promotion]['BaseHP']['Value']
),
BaseHPAdd=PromotionAttr(
Value=promotion_dict[promotion]['BaseHPAdd'][
'Value'
]
),
BaseAttack=PromotionAttr(
Value=promotion_dict[promotion]['BaseAttack'][
'Value'
]
),
BaseAttackAdd=PromotionAttr(
Value=promotion_dict[promotion]['BaseAttackAdd'][
'Value'
]
),
BaseDefence=PromotionAttr(
Value=promotion_dict[promotion]['BaseDefence'][
'Value'
]
),
BaseDefenceAdd=PromotionAttr(
Value=promotion_dict[promotion]['BaseDefenceAdd'][
'Value'
]
),
)
for promotion in promotion_dict.keys()
}
for equipment_id, promotion_dict in data.items()
}
)
class RelicMainAffixConfigModel(Struct): # class RelicMainAffixConfigModel(Struct):
Relic: Dict[str, Dict[str, SingleRelicMainAffix]] # Relic: List[Dict[str, SingleRelicMainAffix]]
@classmethod
def from_json(cls, data: Dict):
return cls(
Relic={
relic_id: {
group_id: SingleRelicMainAffix(
GroupID=affix_dict[group_id]['GroupID'],
AffixID=affix_dict[group_id]['AffixID'],
Property=affix_dict[group_id]['Property'],
BaseValue=PromotionAttr(
Value=affix_dict[group_id]['BaseValue']['Value']
),
LevelAdd=PromotionAttr(
Value=affix_dict[group_id]['LevelAdd']['Value']
),
IsAvailable=affix_dict[group_id]['IsAvailable'],
)
for group_id in affix_dict.keys()
}
for relic_id, affix_dict in data.items()
}
)
class RelicSubAffixConfigModel(Struct): # class RelicSubAffixConfigModel(Struct):
Relic: Dict[str, Dict[str, SingleRelicSubAffix]] # Relic: Dict[str, Dict[str, SingleRelicSubAffix]]
@classmethod
def from_json(cls, data: Dict):
return cls(
Relic={
relic_id: {
group_id: SingleRelicSubAffix(
GroupID=affix_dict[group_id]['GroupID'],
AffixID=affix_dict[group_id]['AffixID'],
Property=affix_dict[group_id]['Property'],
BaseValue=PromotionAttr(
Value=affix_dict[group_id]['BaseValue']['Value']
),
StepValue=PromotionAttr(
Value=affix_dict[group_id]['StepValue']['Value']
),
StepNum=affix_dict[group_id]['StepNum'],
)
for group_id in affix_dict.keys()
}
for relic_id, affix_dict in data.items()
}
)
AvatarPromotionConfig = AvatarPromotionConfigModel.from_json(AvatarPromotion) AvatarPromotionConfig = convert(AvatarPromotion, List[SingleAvatarPromotion])
EquipmentPromotionConfig = EquipmentPromotionConfigModel.from_json( EquipmentPromotionConfig = convert(
EquipmentPromotion EquipmentPromotion, List[SingleEquipmentPromotion]
) )
RelicMainAffixConfig = RelicMainAffixConfigModel.from_json(RelicMainAffix) RelicMainAffixConfig = convert(RelicMainAffix, List[SingleRelicMainAffix])
RelicSubAffixConfig = RelicSubAffixConfigModel.from_json(RelicSubAffix) RelicSubAffixConfig = convert(RelicSubAffix, List[SingleRelicSubAffix])

View File

@ -8,23 +8,19 @@ from PIL import Image, ImageFont
@overload @overload
async def convert_img(img: Image.Image, is_base64: bool = False) -> bytes: async def convert_img(img: Image.Image, is_base64: bool = False) -> bytes: ...
...
@overload @overload
async def convert_img(img: Image.Image, is_base64: bool = True) -> str: async def convert_img(img: Image.Image, is_base64: bool = True) -> str: ...
...
@overload @overload
async def convert_img(img: bytes, is_base64: bool = False) -> str: async def convert_img(img: bytes, is_base64: bool = False) -> str: ...
...
@overload @overload
async def convert_img(img: Path, is_base64: bool = False) -> str: async def convert_img(img: Path, is_base64: bool = False) -> str: ...
...
async def convert_img( async def convert_img(

View File

@ -1,11 +1,16 @@
import json import json
from pathlib import Path from pathlib import Path
from typing import Dict, List, Union, TypedDict from typing import Dict, List, Optional, TypedDict, Union
from msgspec import json as msgjson
from ...version import StarRail_version from ...version import StarRail_version
from .model.RelicSetSkill import RelicSetSkillModel
from msgspec import Struct, convert, json as msgjson
class RelicSetStatusAdd(Struct):
Property: str
Value: float
MAP = Path(__file__).parent / 'data' MAP = Path(__file__).parent / 'data'
@ -17,7 +22,7 @@ EquipmentID2Name_fileName = f'EquipmentID2Name_mapping_{version}.json'
EquipmentID2EnName_fileName = f'EquipmentID2EnName_mapping_{version}.json' EquipmentID2EnName_fileName = f'EquipmentID2EnName_mapping_{version}.json'
skillId2Name_fileName = f'skillId2Name_mapping_{version}.json' skillId2Name_fileName = f'skillId2Name_mapping_{version}.json'
skillId2Type_fileName = f'skillId2Type_mapping_{version}.json' skillId2Type_fileName = f'skillId2Type_mapping_{version}.json'
Property2Name_fileName = 'Property2Name.json' Property2Name_fileName = f'Property2Name_mapping_{version}.json'
RelicId2SetId_fileName = f'RelicId2SetId_mapping_{version}.json' RelicId2SetId_fileName = f'RelicId2SetId_mapping_{version}.json'
SetId2Name_fileName = f'SetId2Name_mapping_{version}.json' SetId2Name_fileName = f'SetId2Name_mapping_{version}.json'
rankId2Name_fileName = f'rankId2Name_mapping_{version}.json' rankId2Name_fileName = f'rankId2Name_mapping_{version}.json'
@ -98,9 +103,9 @@ with Path.open(
f.read(), type=Dict[str, Dict[str, List]] f.read(), type=Dict[str, Dict[str, List]]
) )
with Path.open(MAP / RelicSetSkill_fileName, encoding='UTF-8') as f: # with Path.open(MAP / RelicSetSkill_fileName, encoding='UTF-8') as f:
data = json.load(f) # RelicSetSkill = convert(json.load(f), Dict[str, Dict[str, object]])
RelicSetSkill = RelicSetSkillModel.from_json(data) # print(RelicSetSkill)
with Path.open(MAP / skillId2AttackType_fileName, encoding='UTF-8') as f: with Path.open(MAP / skillId2AttackType_fileName, encoding='UTF-8') as f:
skillId2AttackType = msgjson.decode(f.read(), type=Dict[str, str]) skillId2AttackType = msgjson.decode(f.read(), type=Dict[str, str])

View File

@ -2898,6 +2898,48 @@
} }
] ]
}, },
"21046": {
"1": [
{
"PropertyType": "AttackAddedRatio",
"Value": {
"Value": 0.16
}
}
],
"2": [
{
"PropertyType": "AttackAddedRatio",
"Value": {
"Value": 0.2
}
}
],
"3": [
{
"PropertyType": "AttackAddedRatio",
"Value": {
"Value": 0.24
}
}
],
"4": [
{
"PropertyType": "AttackAddedRatio",
"Value": {
"Value": 0.28
}
}
],
"5": [
{
"PropertyType": "AttackAddedRatio",
"Value": {
"Value": 0.32
}
}
]
},
"22002": { "22002": {
"1": [ "1": [
{ {
@ -2946,5 +2988,89 @@
"3": [], "3": [],
"4": [], "4": [],
"5": [] "5": []
},
"23030": {
"1": [
{
"PropertyType": "CriticalDamageBase",
"Value": {
"Value": 0.36
}
}
],
"2": [
{
"PropertyType": "CriticalDamageBase",
"Value": {
"Value": 0.42
}
}
],
"3": [
{
"PropertyType": "CriticalDamageBase",
"Value": {
"Value": 0.48
}
}
],
"4": [
{
"PropertyType": "CriticalDamageBase",
"Value": {
"Value": 0.54
}
}
],
"5": [
{
"PropertyType": "CriticalDamageBase",
"Value": {
"Value": 0.6
}
}
]
},
"23029": {
"1": [
{
"PropertyType": "StatusProbabilityBase",
"Value": {
"Value": 0.6
}
}
],
"2": [
{
"PropertyType": "StatusProbabilityBase",
"Value": {
"Value": 0.7
}
}
],
"3": [
{
"PropertyType": "StatusProbabilityBase",
"Value": {
"Value": 0.8
}
}
],
"4": [
{
"PropertyType": "StatusProbabilityBase",
"Value": {
"Value": 0.9
}
}
],
"5": [
{
"PropertyType": "StatusProbabilityBase",
"Value": {
"Value": 1
}
}
]
} }
} }

View File

@ -101,6 +101,9 @@
"23028": "YetHopeIsPriceless", "23028": "YetHopeIsPriceless",
"21044": "BoundlessChoreo", "21044": "BoundlessChoreo",
"21045": "AftertheCharmonyFall", "21045": "AftertheCharmonyFall",
"21046": "PoisedtoBloom",
"22002": "ForTomorrow'sJourney", "22002": "ForTomorrow'sJourney",
"23026": "FlowingNightglow" "23026": "FlowingNightglow",
"23030": "DanceatSunset",
"23029": "ThoseManySprings"
} }

View File

@ -101,6 +101,9 @@
"23028": "偏偏希望无价", "23028": "偏偏希望无价",
"21044": "无边曼舞", "21044": "无边曼舞",
"21045": "谐乐静默之后", "21045": "谐乐静默之后",
"21046": "芳华待灼",
"22002": "为了明日的旅途", "22002": "为了明日的旅途",
"23026": "夜色流光溢彩" "23026": "夜色流光溢彩",
"23030": "落日时起舞",
"23029": "那无数个春天"
} }

View File

@ -66,6 +66,7 @@
"21043": 4, "21043": 4,
"21044": 4, "21044": 4,
"21045": 4, "21045": 4,
"21046": 4,
"22000": 4, "22000": 4,
"22001": 4, "22001": 4,
"22002": 4, "22002": 4,
@ -98,6 +99,8 @@
"23026": 5, "23026": 5,
"23027": 5, "23027": 5,
"23028": 5, "23028": 5,
"23029": 5,
"23030": 5,
"24000": 5, "24000": 5,
"24001": 5, "24001": 5,
"24002": 5, "24002": 5,

View File

@ -1,55 +0,0 @@
{
"MaxHP": "生命值",
"Attack": "攻击力",
"Defence": "防御力",
"Speed": "速度",
"CriticalChance": "暴击率",
"CriticalDamage": "暴击伤害",
"BreakDamageAddedRatio": "击破特攻",
"BreakDamageAddedRatioBase": "击破特攻",
"HealRatio": "治疗量加成",
"MaxSP": "能量上限",
"SPRatio": "能量恢复效率",
"StatusProbability": "效果命中",
"StatusResistance": "效果抵抗",
"CriticalChanceBase": "暴击率",
"CriticalDamageBase": "暴击伤害",
"HealRatioBase": "治疗量加成",
"StanceBreakAddedRatio": "dev_失效字段",
"SPRatioBase": "能量恢复效率",
"StatusProbabilityBase": "效果命中",
"StatusResistanceBase": "效果抵抗",
"PhysicalAddedRatio": "物理属性伤害提高",
"PhysicalResistance": "物理属性抗性提高",
"FireAddedRatio": "火属性伤害提高",
"FireResistance": "火属性抗性提高",
"IceAddedRatio": "冰属性伤害提高",
"IceResistance": "冰属性抗性提高",
"ThunderAddedRatio": "雷属性伤害提高",
"ThunderResistance": "雷属性抗性提高",
"WindAddedRatio": "风属性伤害提高",
"WindResistance": "风属性抗性提高",
"QuantumAddedRatio": "量子属性伤害提高",
"QuantumResistance": "量子属性抗性提高",
"ImaginaryAddedRatio": "虚数属性伤害提高",
"ImaginaryResistance": "虚数属性抗性提高",
"BaseHP": "基础生命值提高<unbreak>#1[i]</unbreak>",
"HPDelta": "生命值",
"HPAddedRatio": "生命值百分比",
"BaseAttack": "基础攻击力提高<unbreak>#1[i]</unbreak>",
"AttackDelta": "攻击力",
"AttackAddedRatio": "攻击力百分比",
"BaseDefence": "基础防御力提高<unbreak>#1[i]</unbreak>",
"DefenceDelta": "防御力",
"DefenceAddedRatio": "防御力百分比",
"BaseSpeed": "速度",
"HealTakenRatio": "治疗量加成",
"PhysicalResistanceDelta": "物理属性抗性提高",
"FireResistanceDelta": "火属性抗性提高",
"IceResistanceDelta": "冰属性抗性提高",
"ThunderResistanceDelta": "雷属性抗性提高",
"WindResistanceDelta": "风属性抗性提高",
"QuantumResistanceDelta": "量子属性抗性提高",
"ImaginaryResistanceDelta": "虚数属性抗性提高",
"SpeedDelta": "速度"
}

View File

@ -9,7 +9,6 @@
"BreakDamageAddedRatioBase": "击破特攻", "BreakDamageAddedRatioBase": "击破特攻",
"HealRatio": "治疗量加成", "HealRatio": "治疗量加成",
"MaxSP": "能量上限", "MaxSP": "能量上限",
"SpecialMaxSP": "",
"SPRatio": "能量恢复效率", "SPRatio": "能量恢复效率",
"StatusProbability": "效果命中", "StatusProbability": "效果命中",
"StatusResistance": "效果抵抗", "StatusResistance": "效果抵抗",

View File

@ -1,238 +0,0 @@
{
"101": {
"2": {
"Property": "HealRatioBase",
"Value": 0.1
},
"4": {}
},
"102": {
"2": {
"Property": "AttackAddedRatio",
"Value": 0.12
},
"4": {
"Property": "SpeedAddedRatio",
"Value": 0.06
}
},
"103": {
"2": {
"Property": "DefenceAddedRatio",
"Value": 0.15
},
"4": {}
},
"104": {
"2": {
"Property": "IceAddedRatio",
"Value": 0.1
},
"4": {}
},
"105": {
"2": {
"Property": "PhysicalAddedRatio",
"Value": 0.1
},
"4": {}
},
"106": {
"2": {},
"4": {}
},
"107": {
"2": {
"Property": "FireAddedRatio",
"Value": 0.1
},
"4": {}
},
"108": {
"2": {
"Property": "QuantumAddedRatio",
"Value": 0.1
},
"4": {}
},
"109": {
"2": {
"Property": "ThunderAddedRatio",
"Value": 0.1
},
"4": {}
},
"110": {
"2": {
"Property": "WindAddedRatio",
"Value": 0.1
},
"4": {}
},
"111": {
"2": {
"Property": "BreakDamageAddedRatioBase",
"Value": 0.16
},
"4": {
"Property": "BreakDamageAddedRatioBase",
"Value": 0.16
}
},
"112": {
"2": {
"Property": "ImaginaryAddedRatio",
"Value": 0.1
},
"4": {}
},
"301": {
"2": {
"Property": "AttackAddedRatio",
"Value": 0.12
}
},
"302": {
"2": {
"Property": "HPAddedRatio",
"Value": 0.12
}
},
"303": {
"2": {
"Property": "StatusProbabilityBase",
"Value": 0.1
}
},
"304": {
"2": {
"Property": "DefenceAddedRatio",
"Value": 0.15
}
},
"305": {
"2": {
"Property": "CriticalDamageBase",
"Value": 0.16
}
},
"306": {
"2": {
"Property": "CriticalChanceBase",
"Value": 0.08
}
},
"307": {
"2": {
"Property": "BreakDamageAddedRatioBase",
"Value": 0.16
}
},
"308": {
"2": {
"Property": "SPRatioBase",
"Value": 0.05
}
},
"309": {
"2": {
"Property": "CriticalChanceBase",
"Value": 0.08
}
},
"310": {
"2": {
"Property": "StatusResistanceBase",
"Value": 0.1
}
},
"113": {
"2": {
"Property": "HPAddedRatio",
"Value": 0.12
},
"4": {}
},
"114": {
"2": {
"Property": "SpeedAddedRatio",
"Value": 0.06
},
"4": {}
},
"115": {
"2": {},
"4": {}
},
"116": {
"2": {
"Property": "AttackAddedRatio",
"Value": 0.12
},
"4": {}
},
"311": {
"2": {
"Property": "AttackAddedRatio",
"Value": 0.12
}
},
"312": {
"2": {
"Property": "SPRatioBase",
"Value": 0.05
}
},
"117": {
"2": {},
"4": {
"Property": "CriticalChanceBase",
"Value": 0.04
}
},
"118": {
"2": {
"Property": "BreakDamageAddedRatioBase",
"Value": 0.16
},
"4": {}
},
"313": {
"2": {
"Property": "CriticalChanceBase",
"Value": 0.04
}
},
"314": {
"2": {
"Property": "AttackAddedRatio",
"Value": 0.12
}
},
"119": {
"2": {
"Property": "BreakDamageAddedRatioBase",
"Value": 0.16
},
"4": {}
},
"120": {
"2": {
"Property": "AttackAddedRatio",
"Value": 0.12
},
"4": {
"Property": "CriticalChanceBase",
"Value": 0.06
}
},
"315": {
"2": {}
},
"316": {
"2": {
"Property": "SpeedAddedRatio",
"Value": 0.06
}
}
}

View File

@ -0,0 +1,238 @@
{
"101": {
"2": {
"Property": "HealRatioBase",
"Value": 0.1
},
"4": {}
},
"102": {
"2": {
"Property": "AttackAddedRatio",
"Value": 0.12
},
"4": {
"Property": "SpeedAddedRatio",
"Value": 0.06
}
},
"103": {
"2": {
"Property": "DefenceAddedRatio",
"Value": 0.15
},
"4": {}
},
"104": {
"2": {
"Property": "IceAddedRatio",
"Value": 0.1
},
"4": {}
},
"105": {
"2": {
"Property": "PhysicalAddedRatio",
"Value": 0.1
},
"4": {}
},
"106": {
"2": {},
"4": {}
},
"107": {
"2": {
"Property": "FireAddedRatio",
"Value": 0.1
},
"4": {}
},
"108": {
"2": {
"Property": "QuantumAddedRatio",
"Value": 0.1
},
"4": {}
},
"109": {
"2": {
"Property": "ThunderAddedRatio",
"Value": 0.1
},
"4": {}
},
"110": {
"2": {
"Property": "WindAddedRatio",
"Value": 0.1
},
"4": {}
},
"111": {
"2": {
"Property": "BreakDamageAddedRatioBase",
"Value": 0.16
},
"4": {
"Property": "BreakDamageAddedRatioBase",
"Value": 0.16
}
},
"112": {
"2": {
"Property": "ImaginaryAddedRatio",
"Value": 0.1
},
"4": {}
},
"301": {
"2": {
"Property": "AttackAddedRatio",
"Value": 0.12
}
},
"302": {
"2": {
"Property": "HPAddedRatio",
"Value": 0.12
}
},
"303": {
"2": {
"Property": "StatusProbabilityBase",
"Value": 0.1
}
},
"304": {
"2": {
"Property": "DefenceAddedRatio",
"Value": 0.15
}
},
"305": {
"2": {
"Property": "CriticalDamageBase",
"Value": 0.16
}
},
"306": {
"2": {
"Property": "CriticalChanceBase",
"Value": 0.08
}
},
"307": {
"2": {
"Property": "BreakDamageAddedRatioBase",
"Value": 0.16
}
},
"308": {
"2": {
"Property": "SPRatioBase",
"Value": 0.05
}
},
"309": {
"2": {
"Property": "CriticalChanceBase",
"Value": 0.08
}
},
"310": {
"2": {
"Property": "StatusResistanceBase",
"Value": 0.1
}
},
"113": {
"2": {
"Property": "HPAddedRatio",
"Value": 0.12
},
"4": {}
},
"114": {
"2": {
"Property": "SpeedAddedRatio",
"Value": 0.06
},
"4": {}
},
"115": {
"2": {},
"4": {}
},
"116": {
"2": {
"Property": "AttackAddedRatio",
"Value": 0.12
},
"4": {}
},
"311": {
"2": {
"Property": "AttackAddedRatio",
"Value": 0.12
}
},
"312": {
"2": {
"Property": "SPRatioBase",
"Value": 0.05
}
},
"117": {
"2": {},
"4": {
"Property": "CriticalChanceBase",
"Value": 0.04
}
},
"118": {
"2": {
"Property": "BreakDamageAddedRatioBase",
"Value": 0.16
},
"4": {}
},
"313": {
"2": {
"Property": "CriticalChanceBase",
"Value": 0.04
}
},
"314": {
"2": {
"Property": "AttackAddedRatio",
"Value": 0.12
}
},
"119": {
"2": {
"Property": "BreakDamageAddedRatioBase",
"Value": 0.16
},
"4": {}
},
"120": {
"2": {
"Property": "AttackAddedRatio",
"Value": 0.12
},
"4": {
"Property": "CriticalChanceBase",
"Value": 0.06
}
},
"315": {
"2": {}
},
"316": {
"2": {
"Property": "SpeedAddedRatio",
"Value": 0.06
}
}
}

View File

@ -36,6 +36,9 @@
"1214": "Quantum", "1214": "Quantum",
"1215": "Physical", "1215": "Physical",
"1217": "Wind", "1217": "Wind",
"1218": "Fire",
"1221": "Physical",
"1224": "Imaginary",
"1301": "Fire", "1301": "Fire",
"1302": "Physical", "1302": "Physical",
"1303": "Ice", "1303": "Ice",

View File

@ -36,6 +36,9 @@
"1214": "Xueyi", "1214": "Xueyi",
"1215": "Hanya", "1215": "Hanya",
"1217": "Huohuo", "1217": "Huohuo",
"1218": "Jiaoqiu",
"1221": "Yunli",
"1224": "March7th",
"1301": "Gallagher", "1301": "Gallagher",
"1302": "Argenti", "1302": "Argenti",
"1303": "RuanMei", "1303": "RuanMei",

View File

@ -36,6 +36,9 @@
"1214": "雪衣", "1214": "雪衣",
"1215": "寒鸦", "1215": "寒鸦",
"1217": "藿藿", "1217": "藿藿",
"1218": "椒丘",
"1221": "云璃",
"1224": "三月七",
"1301": "加拉赫", "1301": "加拉赫",
"1302": "银枝", "1302": "银枝",
"1303": "阮•梅", "1303": "阮•梅",

View File

@ -1,58 +0,0 @@
{
"1001": "4",
"1002": "4",
"1003": "5",
"1004": "5",
"1005": "5",
"1006": "5",
"1008": "4",
"1009": "4",
"1013": "4",
"1101": "5",
"1102": "5",
"1103": "4",
"1104": "5",
"1105": "4",
"1106": "4",
"1107": "5",
"1108": "4",
"1109": "4",
"1110": "4",
"1111": "4",
"1112": "5",
"1201": "4",
"1202": "4",
"1203": "5",
"1204": "5",
"1205": "5",
"1206": "4",
"1207": "4",
"1208": "5",
"1209": "5",
"1210": "4",
"1211": "5",
"1212": "5",
"1213": "5",
"1214": "4",
"1215": "4",
"1217": "5",
"1301": "4",
"1302": "5",
"1303": "5",
"1304": "5",
"1305": "5",
"1306": "5",
"1307": "5",
"1308": "5",
"1309": "5",
"1310": "5",
"1312": "4",
"1314": "5",
"1315": "5",
"8001": "5",
"8002": "5",
"8003": "5",
"8004": "5",
"8005": "5",
"8006": "5"
}

View File

@ -36,6 +36,9 @@
"1214": "4", "1214": "4",
"1215": "4", "1215": "4",
"1217": "5", "1217": "5",
"1218": "5",
"1221": "5",
"1224": "4",
"1301": "4", "1301": "4",
"1302": "5", "1302": "5",
"1303": "5", "1303": "5",

View File

@ -919,6 +919,82 @@
} }
], ],
"121706": [], "121706": [],
"121801": [],
"121802": [],
"121803": [
{
"id": "121802",
"num": 2
},
{
"id": "121801",
"num": 1
}
],
"121804": [],
"121805": [
{
"id": "121803",
"num": 2
},
{
"id": "121804",
"num": 2
}
],
"121806": [],
"122101": [],
"122102": [],
"122103": [
{
"id": "122103",
"num": 2
},
{
"id": "122101",
"num": 1
}
],
"122104": [],
"122105": [
{
"id": "122102",
"num": 2
},
{
"id": "122104",
"num": 2
}
],
"122106": [],
"122401": [],
"122402": [],
"122403": [
{
"id": "122402",
"num": 2
},
{
"id": "122401",
"num": 1
},
{
"id": "122408",
"num": 1
}
],
"122404": [],
"122405": [
{
"id": "122403",
"num": 2
},
{
"id": "122404",
"num": 2
}
],
"122406": [],
"130101": [], "130101": [],
"130102": [], "130102": [],
"130103": [ "130103": [

View File

@ -221,6 +221,24 @@
"121704": "坐卧不离,争拗难宁", "121704": "坐卧不离,争拗难宁",
"121705": "降妖捉鬼,十王敕令", "121705": "降妖捉鬼,十王敕令",
"121706": "同休共戚,相须而行", "121706": "同休共戚,相须而行",
"121801": "五味五走,生熟有定",
"121802": "爽口作疾,厚味措毒",
"121803": "和合之妙,敌不及拒",
"121804": "藏腑和平,血气资荣",
"121805": "明争天地,暗斗变击",
"121806": "九沸九变,火为之纪",
"122101": "沉锋离垢",
"122102": "初芒破生",
"122103": "九尺运斤",
"122104": "大匠击橐",
"122105": "恒兵匪石",
"122106": "剑胆琴心",
"122401": "初花学剑动星芒",
"122402": "白刃耀雪舞骇浪",
"122403": "头脑机灵本领强",
"122404": "龙飞凤舞不窝囊",
"122405": "多练武术少吃糖",
"122406": "天下第一本姑娘",
"130101": "盐与犬", "130101": "盐与犬",
"130102": "狮子之尾", "130102": "狮子之尾",
"130103": "逝者的新生", "130103": "逝者的新生",

View File

@ -358,5 +358,24 @@
"130603": "Ultra", "130603": "Ultra",
"130604": "", "130604": "",
"130606": "MazeNormal", "130606": "MazeNormal",
"130607": "Maze" "130607": "Maze",
} "121801": "Normal",
"121802": "BPSkill",
"121803": "Ultra",
"121804": "",
"121806": "MazeNormal",
"121807": "Maze",
"122401": "Normal",
"122408": "Normal",
"122402": "BPSkill",
"122403": "Ultra",
"122404": "",
"122406": "MazeNormal",
"122407": "Maze",
"122101": "Normal",
"122102": "BPSkill",
"122103": "Ultra",
"122104": "",
"122106": "MazeNormal",
"122107": "Maze"
}

View File

@ -358,5 +358,24 @@
"130603": "一人千役", "130603": "一人千役",
"130604": "叙述性诡计", "130604": "叙述性诡计",
"130606": "攻击", "130606": "攻击",
"130607": "不可靠叙事者" "130607": "不可靠叙事者",
"121801": "仁火攻心",
"121802": "燔燎急袭",
"121803": "鼎阵妙法,奇正相生",
"121804": "四示八权,纤滋精味",
"121806": "攻击",
"121807": "旺火却乱",
"122401": "荡涤妖邪琉璃剑",
"122408": "一扎眉攒,二扎心",
"122402": "师父,请喝茶!",
"122403": "盖世女侠三月七",
"122404": "师父,我悟了!",
"122406": "攻击",
"122407": "一气化三餐",
"122101": "翻风转日",
"122102": "飞铗震赫",
"122103": "剑为地纪,刃惊天宗",
"122104": "闪铄",
"122106": "攻击",
"122107": "后发先至"
} }

View File

@ -358,5 +358,24 @@
"130603": "辅助", "130603": "辅助",
"130604": "辅助", "130604": "辅助",
"130606": "", "130606": "",
"130607": "辅助" "130607": "辅助",
"121801": "单攻",
"121802": "扩散",
"121803": "群攻",
"121804": "妨害",
"121806": "",
"121807": "妨害",
"122401": "单攻",
"122408": "单攻",
"122402": "辅助",
"122403": "单攻",
"122404": "强化",
"122406": "",
"122407": "强化",
"122101": "单攻",
"122102": "扩散",
"122103": "强化",
"122104": "扩散",
"122106": "",
"122107": "强化"
} }

View File

@ -1,28 +1,6 @@
from typing import Dict, Union
from msgspec import Struct from msgspec import Struct
class RelicSetStatusAdd(Struct): class RelicSetStatusAdd(Struct):
Property: str Property: str
Value: float Value: float
class RelicSetSkillModel(Struct):
RelicSet: Dict[str, Dict[str, Union[RelicSetStatusAdd, None]]]
@classmethod
def from_json(cls, data: Dict):
return cls(
RelicSet={
str(k): {
str(k2): RelicSetStatusAdd(
Property=v2['Property'], Value=v2['Value']
)
if v2
else None
for k2, v2 in v.items()
}
for k, v in data.items()
}
)

View File

@ -1,2 +1,2 @@
StarRailUID_version = '0.1.0' StarRailUID_version = '0.1.0'
StarRail_version = '2.3.0' StarRail_version = '2.4.0'