from collections.abc import Mapping import sys from typing import Any, Literal from core.abstract.character import CharacterProperty from core.basic.skill import Skill from core.basic.equipment import EquEffect, OathSuit, OathSuitSkill, Suit from ..formula import get_base_attributes, 获取唤醒属性 from ..roleinfo import CharacterEmblemInfo, CharacterEquipInfo, get_key_by_value, CharacterOathInfo from .jade import Jade ELEMENT_STATUS_KEYS = { 'ElementA', 'ElementDB', 'ElementR', '火强', '冰强', '光强', '暗强', '火抗', '冰抗', '光抗', '暗抗', '火属性攻击', '冰属性攻击', '光属性攻击', '暗属性攻击', } class CharacterBase(CharacterProperty): # region 额外类属性(CharacterProperty 中未声明的) BindAwake: int """绑定觉醒等级""" skills: list['Skill'] skills_dict: dict[str, 'Skill'] skills_id_dict: dict[str, 'Skill'] skills_uuid_dict: dict[str, 'Skill'] skill_names_cache: dict[tuple[str, bool | str], list[str]] skills_cache: dict[tuple[str, bool | str], list['Skill']] equVersion: str = '0' """装备版本""" charEquipInfo: dict[str, 'CharacterEquipInfo'] """装备打造信息""" charEmblemInfo: list['CharacterEmblemInfo'] """徽章打造信息""" charOathInfo: list['CharacterOathInfo'] """誓约打造信息""" charOathSkillId: int """誓约技能ID""" suitInfo: list['Suit'] """套装信息""" oathSuitInfo: list['OathSuit'] """誓约套装信息""" oathSkillInfo: list['OathSuitSkill'] """誓约技能信息""" equ_effect: list['EquEffect'] """装备效果列表""" equ_options: dict[str, int] """装备选项列表""" EquEffectRatio = 1.0 """装备效果倍率""" max_point = 0 """套装效果点数""" buffer: bool = False # region 职业属性 实际名称: str = '' 名称: str = '' 角色: str = '' 角色类型: str = '' 职业: str = '' 武器选项: list[str] = [] 副武器选项: list[str] = [] 输出类型选项: list[str] = [] 防具精通属性: list[str] = [] 输出类型: str = '物理百分比' # endregion # endregion # region 跨 Mixin 方法前向声明(供静态类型检查使用,由对应 Mixin 实现) def load_skills(self) -> None: """加载技能(由 CalcEquipMixin 实现)""" def calc_carry_skills(self, DSB: bool, BUFF: bool) -> list: """计算输出技能(由 CalcCarryMixin 实现)""" return [] def get_carry_info(self) -> list: """获取输出信息(由 CalcCarryMixin 实现)""" return [] def calc_buffer_skills(self) -> list: """计算辅助技能(由 CalcBufferMixin 实现)""" return [] def get_buffer_info(self) -> list: """获取辅助信息(由 CalcBufferMixin 实现)""" return [] # endregion def __init__(self, equVersion, moduleName) -> None: self.equVersion = equVersion self.moduleName = moduleName # 工会四维 self.STR = 0 + 120 self.INT = 0 + 120 self.Spirit = 0 + 120 self.Vitality = 0 + 120 # 唤醒的情况下的基础数据 self.AtkP = 0 + 65 + 30 self.AtkM = 0 + 65 + 30 self.AtkI = 0 + 65 + 30 self.PAtkP = 1.0 self.PAtkM = 1.0 self.PAtkI = 1.0 self.ElementA = { '火': False, '冰': False, '光': False, '暗': False, } self.ElementDB = { '火': 13 + 7, '冰': 13 + 7, '光': 13 + 7, '暗': 13 + 7, } self.ElementR = { '火': 0, '冰': 0, '光': 0, '暗': 0, } self.Abnormal = { '出血': False, '灼伤': False, '感电': False, '中毒': False, } self.CriticalM = 0 self.CriticalP = 0 self.SkillAttack = 1 self.SpeedA = 0 self.SpeedM = 0 self.SpeedR = 0 self.HitP = 0 self.Hit = 0 self.MonsterInfo = { 'DefenseP': 0, 'DefenseM': 0, '火抗': 0, '冰抗': 0, '光抗': 0, '暗抗': 0, } self.Buffer = 0 self.BufferP = 1.0 self.Attack = 0 self.AttackP = 1.0 self.ElementIncrease = 1.0 self.equs = {} self.jade_effect = Jade() self.equ_effect = [] self.equ_options = {} self.max_point = 0 self.skills = [] self.skills_dict = {} self.skills_id_dict = {} self.skills_uuid_dict = {} self.skill_names_cache = {} self.skills_cache = {} self.load_skills() # region 角色属性设置 def SetBaseStatus(self) -> None: """设角色基础属性""" temp = get_base_attributes(self.role, self.name) 唤醒 = 获取唤醒属性() for index, i in enumerate([get_key_by_value(i) for i in ['力量', '体力', '智力', '精神']]): setattr(self, i, getattr(self, i) + temp[index] + 唤醒) def SetStatus( self, 力量=0, 智力=0, 力智=0, 体力=0, 精神=0, 体精=0, 四维=0, 物攻=0, 魔攻=0, 独立=0, 三攻=0, 技攻=0, 全属强=0, 全属抗=0, 移动速度=0, 攻击速度=0, 施放速度=0, 三速=0, 命中=0, 命中率=0, 物暴=0, 魔暴=0, 攻击强化=0, 攻击强化P=0, 增益量=0, 增益量P=0, **kwargs: Mapping[ Literal[ 'STR', 'INT', 'AtkP', 'AtkM', 'AtkI', 'PAtkP', 'PAtkM', 'PAtkI', 'PATKIPDamage', 'PDamageC', 'PSTR', 'PINT', 'PDamageB', 'ElementA', 'ElementDB', 'ElementR', 'CriticalMP', 'CriticalM', 'CriticalPP', 'CriticalP', 'EquipmentSkillAttack', 'SkillAttack', 'SpeedA', 'SpeedM', 'SpeedR', 'HitP', 'Hit', 'Attack', 'AttackP', 'Buffer', 'BufferP', 'Spirit', 'Vitality', 'EquEffectRatio', '火强', '冰强', '光强', '暗强', '火属性抗性', '冰属性抗性', '光属性抗性', '暗属性抗性', '火属性攻击', '冰属性攻击', '光属性攻击', '暗属性攻击', ], Any, ], ) -> None: """设置角色属性""" # if kwargs.get('SkillAttack', 0) != 0: # frame = sys._getframe(1) # 1 表示上一级调用帧 # if 'apply_uppercase_attrs' in frame.f_code.co_name: # frame = sys._getframe(2) # 2 表示上上级调用帧 # caller_name = frame.f_code.co_name # print(caller_name, kwargs.get('SkillAttack', 0)) kget = kwargs.get self.STR += 力量 + kget('STR', 0) + 四维 + 力智 self.INT += 智力 + kget('INT', 0) + 四维 + 力智 self.Spirit += 精神 + kget('Spirit', 0) + 四维 + 体精 self.Vitality += 体力 + kget('Vitality', 0) + 四维 + 体精 self.AtkP += 物攻 + kget('AtkP', 0) + 三攻 self.AtkM += 魔攻 + kget('AtkM', 0) + 三攻 self.AtkI += 独立 + kget('AtkI', 0) + 三攻 self.PAtkP *= kget('PAtkP', 1.0) self.PAtkM *= kget('PAtkM', 1.0) self.PAtkI *= kget('PAtkI', 1.0) if 全属强 or 全属抗 or ELEMENT_STATUS_KEYS.intersection(kwargs): element_a = kget('ElementA', {}) element_db = kget('ElementDB', {}) element_r = kget('ElementR', {}) for elem in ['火', '冰', '光', '暗']: self.ElementA[elem] = kget(f'{elem}属性攻击', False) or element_a.get(elem, False) or self.ElementA[elem] self.ElementDB[elem] += kget(f'{elem}强', 0) + element_db.get(elem, 0) + 全属强 self.ElementR[elem] += kget(f'{elem}抗', 0) + element_r.get(elem, 0) + 全属抗 self.CriticalM += kget('CriticalM', 0) + 魔暴 self.CriticalP += kget('CriticalP', 0) + 物暴 self.SkillAttack *= (1 + round(技攻,6)) * (1 +round( kget('SkillAttack', 0),6)) self.SpeedA += 攻击速度 + kget('SpeedA', 0) + 三速 self.SpeedM += 移动速度 + kget('SpeedM', 0) + 三速 self.SpeedR += 施放速度 + kget('SpeedR', 0) + 三速 self.HitP += 命中率 + kget('HitP', 0) self.Hit += 命中 + kget('Hit', 0) self.Attack += 攻击强化 + kget('Attack', 0) self.AttackP += 攻击强化P + kget('AttackP', 0.0) self.Buffer += 增益量 + kget('Buffer', 0) self.BufferP += 增益量P + kget('BufferP', 0) self.EquEffectRatio += kget('EquEffectRatio', 0.0) def AddElementDB(self, element: str, value: float, type: int = 0) -> None: """ 增加属性强化 type: 0 站街 1 进图 """ if element not in self.ElementDB: raise ValueError(f'Invalid element: {element}') if type == 0: value = value * (1 + self.jade_effect.ElementIncrease) if type == 1: value = int(value * (1 + self.jade_effect.ElementIncrease)) self.ElementDB[element] += value def AddSkillLv(self, min: int, max: int, lv: int, type=-1, exceptSkills: tuple[str, ...] = ()) -> None: """ 增加技能等级 type: -1 全部, 0 被动, 1 主动 """ skillType = 'all' if type == -1 else ('active' if type == 1 else 'passive') for skill in self.skills: if min <= skill.learnLv <= max: if (skillType == 'all' or skill.type == skillType) and skill.lv > 0 and skill.name not in exceptSkills: skill.lv += lv def SetSkillCD(self, min=1, max=100, cd=0, exclude: tuple[int, ...] = (50, 85, 100)) -> None: """设置技能CD""" for skill in self.skills: if min <= skill.learnLv <= max and (skill.type == 'active' or skill.damage) and skill.learnLv not in exclude: skill.cdReduce *= 1 - cd def SetSkillCDRecover(self, min=1, max=100, cd=0, exclude: tuple[int, ...] = (50, 85, 100)) -> None: """设置技能CD恢复""" for skill in self.skills: if min <= skill.learnLv <= max and (skill.type == 'active' or skill.damage) and skill.learnLv not in exclude: skill.cdRecover += cd def SetSkillRation(self, min=1, max=100, ratio=1, type=-1) -> None: """设置技能倍率 0 修改技能面板 1 不修改技能面板 type: -1 全部, 0 被动, 1 主动 """ for skill in self.skills: if min <= skill.learnLv <= max and skill.damage and skill.type == 'active': if type == 0: skill.skillRation *= 1 + ratio else: skill.skillDamage *= 1 + ratio # endregion # region 技能查询 def GetSkillByName(self, name) -> 'Skill': """通过技能名获取技能""" return self.skills_dict.get(name, None) def GetSkillByID(self, id: str) -> 'Skill': """通过技能ID获取技能""" return self.skills_id_dict.get(str(id), None) def GetSkillByUUID(self, uuid: str) -> 'Skill': """通过技能UUID获取技能""" return self.skills_uuid_dict.get(str(uuid), None) def GetSkillNames(self, type: Literal['active', 'passive', 'all'] = 'all', damage: Literal[True, False, 'all'] = 'all') -> list[str]: """获取技能名字""" return [skill.name for skill in self.GetSkills(type, damage)] def GetSkills(self, type: Literal['active', 'passive', 'all'] = 'all', damage: Literal[True, False, 'all'] = 'all') -> list['Skill']: """获取技能对象""" key = (type, damage) if key not in self.skills_cache: self.skills_cache[key] = [skill for skill in self.skills if (type == 'all' or skill.type == type) and (damage == 'all' or skill.damage == damage)] return self.skills_cache[key] def GetWeaponType(self) -> tuple[str, str]: """获取武器类型""" weapon = self.charEquipInfo['武器'].equInfo if weapon is None: return None, None else: return weapon.itemDetailType, weapon.categorize # endregion def GetReinforceSum(self) -> list[int]: """获取强化总和""" reinforce_0 = 0 """防具""" reinforce_1 = 0 """首饰""" reinforce_2 = 0 """特殊装备""" reinforce_3 = 0 """武器""" for part in self.charEquipInfo.keys(): if self.charEquipInfo[part] is None: continue num = self.charEquipInfo[part].reinforce # if part == '武器': # reinforce_3 += num if part in ['上衣', '头肩', '下装', '腰带', '鞋']: reinforce_0 += num if part in ['手镯', '项链', '戒指']: reinforce_1 += num if part in ['耳环', '辅助装备', '魔法石']: reinforce_2 += num reinforce = reinforce_0 + reinforce_1 + reinforce_2 + reinforce_3 return [reinforce, reinforce_0, reinforce_1, reinforce_2]