diff --git a/StarRailUID/starrailuid_charinfo/__init__.py b/StarRailUID/starrailuid_charinfo/__init__.py index ef1e7fb..1df1970 100644 --- a/StarRailUID/starrailuid_charinfo/__init__.py +++ b/StarRailUID/starrailuid_charinfo/__init__.py @@ -11,14 +11,45 @@ from .to_card import api_to_card from ..utils.convert import get_uid from ..utils.sr_prefix import PREFIX from ..utils.error_reply import UID_HINT +from .get_char_img import draw_char_info_img from ..utils.image.convert import convert_img +from .draw_char_img import cal, get_char_data from ..utils.resource.RESOURCE_PATH import TEMP_PATH -from .draw_char_img import cal, get_char_data, draw_char_info_img sv_char_info_config = SV('sr面板设置', pm=2) sv_get_char_info = SV('sr面板查询', priority=10) sv_get_sr_original_pic = SV('sr查看面板原图', priority=5) sv_char_damage_cal = SV('sr伤害计算') +sv_group_damage_cal = SV('sr伤害计算') + + +@sv_group_damage_cal.on_prefix(f'{PREFIX}队伍伤害') +async def send_group_damage_msg(bot: Bot, ev: Event): + msg = ''.join(re.findall('[\u4e00-\u9fa5 ]', ev.text)) + if not msg: + return None + await bot.logger.info('开始执行[队伍伤害计算]') + # 获取uid + sr_uid = await get_uid(bot, ev) + if sr_uid is None: + return await bot.send(UID_HINT) + await bot.logger.info(f'[队伍伤害计算]uid: {sr_uid}') + char_name = ' '.join(re.findall('[\u4e00-\u9fa5]+', msg)) + char_list = char_name.split() + char_data_list = [] + for char_name in char_list: + char_data = await get_char_data(sr_uid, char_name) + if isinstance(char_data, str): + return await bot.send(char_data) + char_data_list.append(char_data) + im_list = [] + # im = await cal_group(char_data_list) + # for info_im in im: + # con = f'{info_im[0]} 暴击伤害: {info_im[1]}' + # con = f'{con} 期望伤害{info_im[2]} 满配辅助末日兽伤害{info_im[3]}' + # im_list.append(con) + await bot.send(im_list) + return None @sv_char_damage_cal.on_prefix(f'{PREFIX}伤害计算') @@ -73,12 +104,15 @@ async def send_char_info(bot: Bot, ev: Event): async def _get_char_info(bot: Bot, ev: Event, text: str): # 获取角色名 - msg = ''.join(re.findall('[\u4e00-\u9fa5 ]', text)) + msg = ''.join(re.findall('^[a-zA-Z0-9_\u4e00-\u9fa5]+$', text)) if not msg: return None await bot.logger.info('开始执行[查询角色面板]') # 获取uid - uid = await get_uid(bot, ev) + if '换' in msg or '拿' in msg or '圣遗物' in msg: + uid = await get_uid(bot, ev, False, True) + else: + uid = await get_uid(bot, ev) if uid is None: return await bot.send(UID_HINT) await bot.logger.info(f'[查询角色面板]uid: {uid}') diff --git a/StarRailUID/starrailuid_charinfo/draw_char_img.py b/StarRailUID/starrailuid_charinfo/draw_char_img.py index c53effa..cd94cbe 100644 --- a/StarRailUID/starrailuid_charinfo/draw_char_img.py +++ b/StarRailUID/starrailuid_charinfo/draw_char_img.py @@ -1,4 +1,3 @@ -import re import json import math from pathlib import Path @@ -76,11 +75,7 @@ RELIC_POS = { } -async def draw_char_info_img(raw_mes: str, sr_uid: str): - # 获取角色名 - char_name = ' '.join(re.findall('[\u4e00-\u9fa5]+', raw_mes)) - - char_data = await get_char_data(sr_uid, char_name) +async def draw_char_img(char_data: Dict, sr_uid: str, msg: str): if isinstance(char_data, str): return char_data char = await cal_char_info(char_data) @@ -106,6 +101,10 @@ async def draw_char_info_img(raw_mes: str, sr_uid: str): bg_height = 0 if damage_len > 0: bg_height = 48 * (1 + damage_len) + 48 + char_change = 0 + if '换' in msg or '拿' in msg or '圣遗物' in msg: + char_change = 1 + bg_height = bg_height + 80 # 放角色立绘 char_info = bg_img.copy() char_info = char_info.resize((1050, 2050 + bg_height)) @@ -499,14 +498,17 @@ async def draw_char_info_img(raw_mes: str, sr_uid: str): single_relic_score = 0 main_value_score = await get_relic_score( - relic['MainAffix']['Property'], main_value, char_name, True + relic['MainAffix']['Property'], + main_value, + char.char_name, + True, ) if main_property.__contains__('AddedRatio') and relic['Type'] == 5: attr_name = main_property.split('AddedRatio')[0] if attr_name == avatarId2DamageType[str(char.char_id)]: weight_dict = {} for item in AvatarRelicScore: - if item['role'] == char_name: + if item['role'] == char.char_name: weight_dict = item add_value = ( (main_value + 1) @@ -522,14 +524,14 @@ async def draw_char_info_img(raw_mes: str, sr_uid: str): subProperty = i['Property'] tmp_score = await get_relic_score( - subProperty, subValue, char_name, False + subProperty, subValue, char.char_name, False ) single_relic_score += tmp_score if subName in ['攻击力', '生命值', '防御力', '速度']: subValueStr = "{:.1f}".format(subValue) else: - subValueStr = "{:.1f}".format(subValue * 100) + '%' # type: ignore + subValueStr = "{:.1f}".format(subValue * 100) + '%' subNameStr = subName.replace('百分比', '').replace('元素', '') # 副词条文字颜色 relic_color = (255, 255, 255) @@ -660,6 +662,23 @@ async def draw_char_info_img(raw_mes: str, sr_uid: str): 'lm', ) + if char_change == 1: + char_img_draw.text( + (525, 2022 + bg_height - 80), + '面板数据来源于:【面板替换】', + (255, 255, 255), + sr_font_26, + 'mm', + ) + + char_img_draw.text( + (525, 2022 + bg_height - 50), + f'{msg}', + (255, 255, 255), + sr_font_26, + 'mm', + ) + # 写底层文字 char_img_draw.text( (525, 2022 + bg_height), diff --git a/StarRailUID/starrailuid_charinfo/effect/Role.py b/StarRailUID/starrailuid_charinfo/effect/Role.py index 96246aa..b00e571 100644 --- a/StarRailUID/starrailuid_charinfo/effect/Role.py +++ b/StarRailUID/starrailuid_charinfo/effect/Role.py @@ -250,7 +250,7 @@ class RoleInstance: ): skill_info[2] = skill_info[2] + 1 - attack = merged_attr['attack'] + attack = merged_attr.get('attack', 0) if self.raw_data.avatar.id_ == 1104: # 杰帕德天赋加攻 defence = merged_attr['defence'] @@ -481,6 +481,7 @@ class RoleInstance: damage_qw_z += damage_qw attr_value_tz: float = self.base_attr.get('attack', 0) + attribute_atk = self.attribute_bonus.get('AttackDelta', 0) attack_tz = ( attr_value_tz + attr_value_tz @@ -489,7 +490,7 @@ class RoleInstance: + self.attribute_bonus.get('AttackAddedRatio', 0) + 2.144 ) - + self.attribute_bonus['AttackDelta'] + + attribute_atk ) if self.raw_data.avatar.id_ in [1205, 1208]: attack_tz = (skill_multiplier * attack_tz) + ( diff --git a/StarRailUID/starrailuid_charinfo/get_char_img.py b/StarRailUID/starrailuid_charinfo/get_char_img.py new file mode 100644 index 0000000..b86f522 --- /dev/null +++ b/StarRailUID/starrailuid_charinfo/get_char_img.py @@ -0,0 +1,321 @@ +import re +import json +from pathlib import Path +from typing import Dict, Tuple, Union, Optional + +from gsuid_core.logger import logger + +from .to_data import api_to_dict +from .draw_char_img import draw_char_img +from ..utils.error_reply import CHAR_HINT +from ..utils.resource.RESOURCE_PATH import PLAYER_PATH +from ..utils.excel.model import EquipmentPromotionConfig +from ..utils.map.name_covert import ( + name_to_avatar_id, + name_to_weapon_id, + alias_to_char_name, +) +from ..utils.map.SR_MAP_PATH import ( + EquipmentID2Name, + EquipmentID2Rarity, + rankId2Name, + avatarId2Name, + avatarId2EnName, + avatarId2DamageType, +) + +WEAPON_TO_INT = { + '一': 1, + '二': 2, + '三': 3, + '四': 4, + '五': 5, + '满': 5, +} + +CHAR_TO_INT = { + '零': 0, + '一': 1, + '二': 2, + '三': 3, + '四': 4, + '五': 5, + '六': 6, + '满': 6, +} + +PieceName_ilst = { + 0: ['头', '帽子', '头部'], + 1: ['手', '手套', '手部'], + 2: ['衣', '衣服', '躯干'], + 3: ['鞋', '鞋子', '腿', '腿部'], + 4: ['球', '位面球'], + 5: ['绳', '绳子', '链', '链子', '连结绳'], +} + + +async def draw_char_info_img(raw_mes: str, sr_uid: str): + # 获取角色名 + # msg = ' '.join(re.findall('[\u4e00-\u9fa5]+', raw_mes)) + print(raw_mes) + _args = await get_char_args(raw_mes, sr_uid) + if isinstance(_args, str): + return _args + else: + if isinstance(_args[0], str): + return _args[0] + + char = await get_char(*_args) + + if isinstance(char, str): + logger.info('[sr查询角色] 绘图失败, 替换的武器不正确!') + return char + + im = await draw_char_img(char, sr_uid, raw_mes) + logger.info('[查询角色] 绘图完成,等待发送...') + return im + + +async def get_char_args( + msg: str, uid: str +) -> Union[Tuple[Dict, Optional[str], Optional[int], Optional[int]], str]: + # 可能进来的值 + # 六命希儿带于夜色中换1000xxxx4青雀遗器换1000xxxx6希儿头换银狼手 + # 六命希儿带于夜色中换1000xxxx6希儿头 + # 希儿换银狼手 + fake_name = '' + talent_num = None + char_data = {} + weapon, weapon_affix = None, None + + msg = ( + msg.replace('带', '换') + .replace('拿', '换') + .replace('圣遗物', '遗器') + .replace('命', '魂') + ) + + # 希儿带于夜色中换1000xxxx6希儿头 + msg_list = msg.split('换') + for index, part in enumerate(msg_list): + changeuid = await get_part_uid(part, uid) + # 判断主体 + if index == 0: + fake_name, talent_num = await get_fake_char_str(part) + # 判断是否开启fake_char + if '遗器' in msg: + char_data = await get_fake_char_data( + char_data, fake_name, changeuid + ) + else: + char_data = await get_char_data(uid, fake_name) + if isinstance(char_data, str): + return char_data + continue + + if '遗器' in part: + fake_data = await get_char_data( + changeuid, part.replace('遗器', '').replace(changeuid, '') + ) + if isinstance(fake_data, str): + return fake_data + char_data = await get_fake_char_data(fake_data, fake_name, uid) + if isinstance(char_data, str): + return char_data + else: + for i, s in enumerate(['头部', '手部', '躯干', '腿部', '位面球', '连结绳']): + if '赤沙' in part: + continue + if part[-1] in PieceName_ilst[i]: + if isinstance(char_data, str): + return char_data + char_data = await change_equip( + changeuid, char_data, part, s, i + ) + if not char_data: + return '要替换的部件不存在噢~' + break + else: + weapon, weapon_affix = await get_fake_weapon_str(part) + + return char_data, weapon, weapon_affix, talent_num + + +async def change_equip( + uid: str, char_data: Dict, part: str, s: str, i: int +) -> Dict: + char_name = part.replace(part[-1], '').replace(uid, '') + print(char_name) + print(uid) + fake_data = await get_char_data(uid, char_name) + if isinstance(fake_data, str): + return {} + relicmap = i + 1 + for equip in fake_data['RelicInfo']: + if str(str(equip['relicId'])[-1]) == str(relicmap): + char_data['RelicInfo'][i] = equip + break + return char_data + + +async def get_part_uid(part: str, uid: str): + print(part) + sr_uid = uid + uid_data = re.findall(r'\d{9}', part) + if uid_data: + sr_uid: Optional[str] = uid_data[0] + return sr_uid + + +async def get_fake_char_str(char_name: str) -> Tuple[str, Optional[int]]: + ''' + 获取一个角色信息 + + ''' + talent_num = None + if '魂' in char_name and char_name[0] in CHAR_TO_INT: + talent_num = CHAR_TO_INT[char_name[0]] + char_name = char_name[2:] + return char_name, talent_num + + +async def get_fake_weapon_str(msg: str) -> Tuple[str, Optional[int]]: + weapon_affix = 0 + if '精' in msg and msg[1] in WEAPON_TO_INT: + weapon_affix = WEAPON_TO_INT[msg[1]] + weapon = msg[2:] + else: + weapon = msg + return weapon, weapon_affix + + +async def get_fake_char_data( + char_data: Dict, fake_name: str, uid: str +) -> Union[Dict, str]: + fake_name = await alias_to_char_name(fake_name) + original_data = await get_char_data(uid, fake_name) + if isinstance(original_data, Dict): + char_data['RelicInfo'] = original_data['RelicInfo'] + char_data['avatarAttributeBonus'] = original_data[ + 'avatarAttributeBonus' + ] + char_data['rankList'] = original_data['rankList'] + char_data['avatarSkill'] = original_data['avatarSkill'] + char_data['avatarExtraAbility'] = original_data['avatarExtraAbility'] + char_data['equipmentInfo'] = original_data['equipmentInfo'] + char_data['baseAttributes'] = original_data['baseAttributes'] + char_data['uid'] = original_data['uid'] + char_data['rank'] = original_data['rank'] + char_data['nickName'] = original_data['nickName'] + char_data['avatarRarity'] = original_data['avatarRarity'] + char_data['avatarPromotion'] = original_data['avatarPromotion'] + char_data['avatarName'] = fake_name + char_data['avatarId'] = await name_to_avatar_id(fake_name) + en_name = avatarId2EnName(char_data['avatarId']) + char_data['avatarEnName'] = en_name + if str(char_data['avatarId']) in avatarId2DamageType: + char_data['avatarElement'] = avatarId2DamageType[ + str(char_data['avatarId']) + ] + else: + return '要查询的角色不存在...' + char_data['avatarLevel'] = '80' + + return char_data + + +async def get_char_data( + sr_uid: str, char_name: str, enable_self: bool = True +) -> Union[Dict, str]: + player_path = PLAYER_PATH / str(sr_uid) + SELF_PATH = player_path / 'SELF' + if "开拓者" in str(char_name): + char_name = "开拓者" + char_id = await name_to_avatar_id(char_name) + if char_id == '': + char_name = await alias_to_char_name(char_name) + if char_name is False: + return "请输入正确的角色名" + char_path = player_path / f'{char_name}.json' + char_self_path = SELF_PATH / f'{char_name}.json' + path = Path() + if char_path.exists(): + path = char_path + elif enable_self and char_self_path.exists(): + path = char_self_path + else: + char_data_list = await api_to_dict(sr_uid) + charname_list = [] + if isinstance(char_data_list, str): + return char_data_list + for char in char_data_list: + charname = avatarId2Name[str(char)] + charname_list.append(charname) + if str(char_name) in charname_list: + if char_path.exists(): + path = char_path + elif enable_self and char_self_path.exists(): + path = char_self_path + else: + return CHAR_HINT.format(char_name, char_name) + + with Path.open(path, encoding='utf8') as fp: + return json.load(fp) + + +async def get_char( + char_data: dict, + weapon: Optional[str] = None, + weapon_affix: Optional[int] = None, + talent_num: Optional[int] = None, +): + if talent_num: + # 处理命座 + rank_temp = [] + char_data['rank'] = talent_num + for index in range(talent_num): + rankTemp = {} + rank_id = int(str(char_data['avatarId']) + '0' + str(index + 1)) + rankTemp['rankId'] = rank_id + rankTemp['rankName'] = rankId2Name[str(rank_id)] + rank_temp.append(rankTemp) + char_data['rankList'] = rank_temp + print(weapon) + if weapon: + # 处理武器 + equipmentid = await name_to_weapon_id(weapon) + print(equipmentid) + equipment_info = {} + equipment_info['equipmentID'] = int(equipmentid) + equipment_info['equipmentName'] = EquipmentID2Name[str(equipmentid)] + + equipment_info['equipmentLevel'] = 80 + equipment_info['equipmentPromotion'] = 6 + equipment_info['equipmentRank'] = weapon_affix + equipment_info['equipmentRarity'] = EquipmentID2Rarity[ + str(equipmentid) + ] + equipment_base_attributes = {} + equipment_promotion_base = EquipmentPromotionConfig.Equipment[ + str(equipmentid) + ]['6'] + + # 生命值 + equipment_base_attributes['hp'] = ( + equipment_promotion_base.BaseHP.Value + + equipment_promotion_base.BaseHPAdd.Value * (80 - 1) + ) + # 攻击力 + equipment_base_attributes['attack'] = ( + equipment_promotion_base.BaseAttack.Value + + equipment_promotion_base.BaseAttackAdd.Value * (80 - 1) + ) + # 防御力 + equipment_base_attributes['defence'] = ( + equipment_promotion_base.BaseDefence.Value + + equipment_promotion_base.BaseDefenceAdd.Value * (80 - 1) + ) + equipment_info['baseAttributes'] = equipment_base_attributes + + char_data['equipmentInfo'] = equipment_info + return char_data