This commit was merged in pull request #1.
This commit is contained in:
2026-06-02 20:56:07 +08:00
parent f824177aa5
commit bb3ad71d21
38 changed files with 1304 additions and 532 deletions
+5 -4
View File
@@ -1,5 +1,6 @@
from abc import ABC, abstractmethod
from typing import Any, Literal, Mapping
from collections.abc import Mapping
from typing import Any, Literal
class CharacterProperty(ABC):
@@ -202,17 +203,17 @@ class CharacterProperty(ABC):
pass
@abstractmethod
def AddSkillLv(self, min: int, max: int, lv: int, type=-1, exceptSkills: list[str] = []) -> None:
def AddSkillLv(self, min: int, max: int, lv: int, type=-1, exceptSkills: tuple[str, ...] = ()) -> None:
"""增加技能等级"""
pass
@abstractmethod
def SetSkillCD(self, min=1, max=100, cd=0, exclude=[50, 85, 100]) -> None:
def SetSkillCD(self, min=1, max=100, cd=0, exclude: tuple[int, ...] = (50, 85, 100)) -> None:
"""设置技能CD"""
pass
@abstractmethod
def SetSkillCDRecover(self, min=1, max=100, cd=0, exclude=[50, 85, 100]) -> None:
def SetSkillCDRecover(self, min=1, max=100, cd=0, exclude: tuple[int, ...] = (50, 85, 100)) -> None:
"""设置技能CD恢复"""
pass
+19 -13
View File
@@ -1,5 +1,4 @@
from collections.abc import Mapping
import sys
from typing import Any, Literal
from core.abstract.character import CharacterProperty
@@ -15,8 +14,11 @@ class CharacterBase(CharacterProperty):
BindAwake: int
"""绑定觉醒等级"""
skills: list['Skill'] = []
skills_dict: dict[str, 'Skill'] = {}
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]]
equVersion: str = '0'
"""装备版本"""
charEquipInfo: dict[str, 'CharacterEquipInfo']
@@ -33,9 +35,9 @@ class CharacterBase(CharacterProperty):
"""誓约套装信息"""
oathSkillInfo: list['OathSuitSkill']
"""誓约技能信息"""
equ_effect: list['EquEffect'] = []
equ_effect: list['EquEffect']
"""装备效果列表"""
equ_options: dict[str, int] = {}
equ_options: dict[str, int]
"""装备选项列表"""
EquEffectRatio = 1.0
"""装备效果倍率"""
@@ -148,6 +150,9 @@ class CharacterBase(CharacterProperty):
self.max_point = 0
self.skills = []
self.skills_dict = {}
self.skills_id_dict = {}
self.skills_uuid_dict = {}
self.skill_names_cache = {}
self.load_skills()
# region 角色属性设置
@@ -285,7 +290,7 @@ class CharacterBase(CharacterProperty):
value = int(value * (1 + self.jade_effect.ElementIncrease))
self.ElementDB[element] += value
def AddSkillLv(self, min: int, max: int, lv: int, type=-1, exceptSkills: list[str] = []) -> None:
def AddSkillLv(self, min: int, max: int, lv: int, type=-1, exceptSkills: tuple[str, ...] = ()) -> None:
"""
增加技能等级
type: -1 全部, 0 被动, 1 主动
@@ -296,13 +301,13 @@ class CharacterBase(CharacterProperty):
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=[50, 85, 100]) -> None:
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=[50, 85, 100]) -> None:
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:
@@ -330,17 +335,18 @@ class CharacterBase(CharacterProperty):
def GetSkillByID(self, id: str) -> 'Skill':
"""通过技能ID获取技能"""
skill = list(filter(lambda x: str(x.id) == id, self.skills))
return skill[0] if len(skill) > 0 else None
return self.skills_id_dict.get(str(id), None)
def GetSkillByUUID(self, uuid: str) -> 'Skill':
"""通过技能UUID获取技能"""
skill = list(filter(lambda x: str(x.uuid) == uuid, self.skills))
return skill[0] if len(skill) > 0 else None
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.skills if (type == 'all' or skill.type == type) and (damage == 'all' or skill.damage == damage)]
key = (type, damage)
if key not in self.skill_names_cache:
self.skill_names_cache[key] = [skill.name for skill in self.skills if (type == 'all' or skill.type == type) and (damage == 'all' or skill.damage == damage)]
return self.skill_names_cache[key]
def GetWeaponType(self) -> tuple[str, str]:
"""获取武器类型"""
+55 -42
View File
@@ -1,4 +1,5 @@
import sys
from functools import cache
from uuid import uuid1
from core.basic.equipment import OathSuit, Suit, get_equipment
@@ -7,6 +8,16 @@ from ..roleinfo import CharacterEmblemInfo, CharacterEquipInfo, CharacterOathInf
from .base import CharacterBase
@cache
def get_skill_classes(module_name: str) -> tuple[type, ...]:
module = sys.modules[module_name]
return tuple(
memberClass
for name in dir(module)
if isinstance((memberClass := getattr(module, name)), type) and memberClass.__name__.startswith('Skill')
)
class CalcEquipMixin(CharacterBase):
"""装备计算、角色初始化相关方法"""
@@ -22,11 +33,12 @@ class CalcEquipMixin(CharacterBase):
info['emblems'] = {}
if info.get('oaths', None) is None:
info['oaths'] = {}
equs = get_equipment(self.equVersion)
for key in info['equips']:
self.charEquipInfo[key] = CharacterEquipInfo(info['equips'][key], self.equVersion, key)
self.charEquipInfo[key] = CharacterEquipInfo(info['equips'][key], self.equVersion, key, equs)
for key in info['oaths']:
# 导入誓约打造信息、誓约信息
self.charOathInfo.append(CharacterOathInfo(info['oaths'][key], self.equVersion, key))
self.charOathInfo.append(CharacterOathInfo(info['oaths'][key], self.equVersion, key, equs))
try:
# 异常处理 彩色等级自动取最小值
minEmblemLv = min([info['emblems'][key]['lv'] for key in ['红色', '蓝色', '绿色', '黄色']], default=1)
@@ -36,7 +48,7 @@ class CalcEquipMixin(CharacterBase):
info['emblems'][key]['part'] = key
self.charEmblemInfo.append(CharacterEmblemInfo(info['emblems'][key]))
pass
except Exception as e:
except Exception:
pass
self.charOathSkillId = info.get('oathSkill', 1)
@@ -59,13 +71,12 @@ class CalcEquipMixin(CharacterBase):
def load_skills(self) -> None:
"""加载技能"""
module = sys.modules[self.moduleName]
for name in dir(module):
memberClass = getattr(module, name)
if isinstance(memberClass, type) and memberClass.__name__.startswith('Skill'):
skill = memberClass(char=self)
self.skills_dict[skill.name] = skill
self.skills.append(skill)
for memberClass in get_skill_classes(self.moduleName):
skill = memberClass(char=self)
self.skills_dict[skill.name] = skill
self.skills_id_dict[str(skill.id)] = skill
self.skills_uuid_dict[str(skill.uuid)] = skill
self.skills.append(skill)
# endregion
@@ -77,27 +88,27 @@ class CalcEquipMixin(CharacterBase):
oathSuitInfo = {}
correction = 0
equs = get_equipment(self.equVersion)
for item in filter(lambda x: x.equInfo is not None, self.charEquipInfo.values()):
for item in self.charEquipInfo.values():
partEqu = item.equInfo
if partEqu is None:
continue
# partFusion = item.fusionInfo
if partEqu is not None:
for suit in partEqu.suit:
if suitInfo.get(suit, None) is None:
suitInfo[suit] = {'point': 0, 'count': 0}
if partEqu.Point == 0:
suitInfo[suit]['count'] += 1
else:
suitInfo[suit]['point'] += partEqu.Point
for suit in partEqu.suit:
suit_item = suitInfo.setdefault(suit, {'point': 0, 'count': 0})
if partEqu.Point == 0:
suit_item['count'] += 1
else:
suit_item['point'] += partEqu.Point
for item in self.charOathInfo:
partOath = item.oathInfo
if partOath is not None:
for suit in partOath.suit:
if oathSuitInfo.get(suit, None) is None:
oathSuitInfo[suit] = {'point': 0, 'count': 0}
if partOath.Point == 0:
oathSuitInfo[suit]['count'] += 1
else:
oathSuitInfo[suit]['point'] += partOath.Point
if partOath is None:
continue
for suit in partOath.suit:
oath_suit_item = oathSuitInfo.setdefault(suit, {'point': 0, 'count': 0})
if partOath.Point == 0:
oath_suit_item['count'] += 1
else:
oath_suit_item['point'] += partOath.Point
max_point_suit = max((suit for suit in suitInfo if suitInfo[suit]['point'] > 0), key=lambda suit: suitInfo[suit]['point'], default=None)
max_point_oath_suit = max((suit for suit in oathSuitInfo if oathSuitInfo[suit]['point'] > 0), key=lambda suit: oathSuitInfo[suit]['point'], default=None)
zero_point_suits = [suit for suit in suitInfo if suitInfo[suit]['point'] == 0]
@@ -140,17 +151,19 @@ class CalcEquipMixin(CharacterBase):
oathSuitList += equs.get_oath_suit_info(suit, oathSuitInfo[suit]['point'], 0)
if len(oathSuitList) == 0:
continue
oath_suit_by_suit_id = {item.suitId: item for item in oathSuitList}
for suit in suitList:
i = suit.id
func = equs.funs.execture(f'suit_{i}')
suit = next((x for x in equs.suits if str(x.id) == str(i)), None)
suit = equs.suit_id_dict.get(str(i), None)
if suit is None:
continue
# 誓约和套装进行匹配
# 如果存在誓约和套装是同一个套装
# 则直接不执行原套装效果,执行誓约套装增强的效果
oathEffect = next((x for x in oathSuitList if x.suitId == suit.suitId), None)
if suit is not None:
filtered_dict = {k: v for k, v in suit.__dict__.items() if k[0].isupper()}
self.SetStatus(**filtered_dict)
oathEffect = oath_suit_by_suit_id.get(suit.suitId, None)
filtered_dict = {k: v for k, v in suit.__dict__.items() if k[0].isupper()}
self.SetStatus(**filtered_dict)
if func is not None and oathEffect is None:
# print(f'套装 {suit.name} 生效')
func(self)
@@ -160,15 +173,15 @@ class CalcEquipMixin(CharacterBase):
self.max_point = 0 if res['suit'] is None else res.get('suit', {}).get('point', 0)
try:
self.oath_max_point = oathSuitInfo.get(max_point_oath_suit, {}).get('point', 0)
except:
except Exception:
self.oath_max_point = 0
self.oathSuitInfo = []
self.oathSkillInfo = []
# 当套装点数达到太初时,誓约技能生效
if self.max_point >= 2550:
oathSuit = next((x for x in oathSuitList if x.suitId == max_point_oath_suit), None)
oathSuit = oath_suit_by_suit_id.get(max_point_oath_suit, None)
if oathSuit is not None:
skills = list(filter(lambda x: x.suitId == oathSuit.suitId, oathSuit.skills))
skills = [x for x in oathSuit.skills if x.suitId == oathSuit.suitId]
skill = next((x for x in oathSuit.skills if str(x.skillId) == str(self.charOathSkillId)), None)
# 誓约套装效果生效
filtered_dict = {k: v for k, v in oathSuit.__dict__.items() if k[0].isupper()}
@@ -214,11 +227,11 @@ class CalcEquipMixin(CharacterBase):
"""计算装备基础效果、附魔"""
effects = get_equipment(self.equVersion).funs
# for detail in [(item.equInfo, item.fusionInfo, item.enchant, item.emblem_0, item.emblem_1) for item in filter(lambda x: x.equInfo is not None, self.charEquipInfo.values())]:
for detail in [(item.equInfo, item.enchant) for item in filter(lambda x: x.equInfo is not None, self.charEquipInfo.values())]:
equ = detail[0]
for item in self.charEquipInfo.values():
equ = item.equInfo
if equ is None or equ.itemType == '副武器':
continue
enchat = detail[1]
enchat = item.enchant
fun = effects.execture(f'equ_{equ.id}')
if fun is None:
continue
@@ -316,20 +329,20 @@ class CalcEquipMixin(CharacterBase):
def calc_basic(self):
"""计算基础属性:防具精通、增幅、强化等"""
char_equip_info = self.charEquipInfo
for part in ['上衣', '头肩', '下装', '腰带', '鞋']:
cur = self.charEquipInfo[part]
cur = char_equip_info[part]
if cur.equInfo is None:
continue
equ = cur.equInfo
reinforce = self.charEquipInfo[part].reinforce
reinforce = cur.reinforce
if equ is None:
continue
for key in self.防具精通属性:
value = 精通计算(115, equ.rarity, reinforce, equ.itemDetailType, self.防具类型, self.buffer, key)
key = get_key_by_value(key)
setattr(self, key, getattr(self, key) + value)
for part in self.charEquipInfo.keys():
cur = self.charEquipInfo[part]
for part, cur in char_equip_info.items():
if cur.equInfo is None:
continue
if cur.reinforceType == 1:
+14 -8
View File
@@ -1,18 +1,21 @@
import importlib
from database.models import EmblemData, OathData, OathSuitData, OathSuitSkillData, PrimerData, Session, EquData, StoneData, SuitData, EnchantData, JadeData
from collections.abc import Sequence
from functools import cache
from sqlalchemy.orm import Session
from database.models import EmblemData, OathData, OathSuitData, OathSuitSkillData, PrimerData, EquData, SuitData, EnchantData, JadeData
from database.connect import get_db_engine as get_engine
def parse_to_number_list(info: str, default: list[float] = [0]) -> list[float]:
return default if not info else [float(i) for i in info.split(',')]
def parse_to_number_list(info: str, default: Sequence[float] = (0,)) -> list[float]:
return list(default) if not info else [float(i) for i in info.split(',')]
def parse_to_string_list(info: str, default: list[str] = ['']) -> list[str]:
return default if not info else [i for i in info.split(',')]
def parse_to_string_list(info: str, default: Sequence[str] = ('',)) -> list[str]:
return list(default) if not info else [i for i in info.split(',')]
def parse_to_int_list(info: str, default: list[int] = [0]) -> list[int]:
return default if not info else [int(i) for i in info.split(',')]
def parse_to_int_list(info: str, default: Sequence[int] = (0,)) -> list[int]:
return list(default) if not info else [int(i) for i in info.split(',')]
class Equ:
@@ -89,6 +92,7 @@ class Equipments:
self.emblems = []
self.suits: list[Suit] = []
self.suit_dict: dict[str, Suit] = {}
self.suit_id_dict: dict[str, Suit] = {}
self.oath_suits: list[OathSuit] = []
self.oath_suit_dict: dict[str, OathSuit] = {}
self.init_equs()
@@ -99,7 +103,6 @@ class Equipments:
self.init_jades()
self.init_oaths()
self.init_oath_suits()
self.engine.dispose()
def init_equs(self):
"""从数据库中获取所有装备信息"""
@@ -166,6 +169,7 @@ class Equipments:
suit_obj = Suit(**suit)
self.suits.append(suit_obj)
self.suit_dict.setdefault(str(suit['suitId']), []).append(suit_obj)
self.suit_id_dict[str(suit_obj.id)] = suit_obj
pass
pass
@@ -279,6 +283,7 @@ class Equipments:
funs = importlib.import_module('core.equipment.version_0')
return funs
@cache
def get_suit_info(self, suitId: str | int, point: int = 0, count: int = 0) -> list[Suit]:
"""根据套装点数返回对应适用的套装属性\n
新套装只需要传入suitID和point即可,count默认为0\n
@@ -295,6 +300,7 @@ class Equipments:
result[suit.count] = suit
return list(result.values())
@cache
def get_oath_suit_info(self, suitId: str | int, point: int = 0, count: int = 0) -> list['OathSuit']:
"""根据套装点数返回对应适用的誓约套装属性\n
新套装只需要传入suitID和point即可,count默认为0\n
+1 -1
View File
@@ -39,7 +39,7 @@ class CharacterInfo(enum.Enum):
AtkI = '独立攻击', '/ui/UI_ProfileIcon_008.png', lambda x: round(x, 0)
"""独立攻击力"""
ElementDB = '攻击属性', '/ui/UI_ProfileIcon_009.png', lambda x: f'火({int(x['火'])})/冰({int(x['冰'])})/光({int(x['光'])})/暗({int(x['暗'])})'
ElementDB = '攻击属性', '/ui/UI_ProfileIcon_009.png', lambda x: f"火({int(x['火'])})/冰({int(x['冰'])})/光({int(x['光'])})/暗({int(x['暗'])})"
"""攻击属性"""
SkillAttack = '技能伤害', '/ui/UI_ProfileIcon_047.png', lambda x: f'{format(x * 100 - 100, ".1f")}%'
+16 -6
View File
@@ -32,12 +32,15 @@ class CharacterEquipInfo:
precision: float
"""秘宝精度"""
def __init__(self, info={}, equVerison=0, part='') -> None:
def __init__(self, info=None, equVerison=0, part='', equipments=None) -> None:
if info is None:
info = {}
# info['fusion'] = info.get('fusion', None)
info['precision'] = info.get('precision', 0)
# info['weaponFusion'] = info.get('weaponFusion', None)
self.__dict__.update(info)
equ = get_equipment(equVerison).equ_dict.get(self.id, None)
equipments = equipments or get_equipment(equVerison)
equ = equipments.equ_dict.get(self.id, None)
# fusion = get_equipment(equVerison).stone_dict.get(self.fusion, None)
if equ is not None and (equ.itemType == part or equ.itemDetailType == part or (equ.itemType == '武器' and part == '副武器')):
self.equInfo = equ.adapt(self.adaptation)
@@ -60,10 +63,13 @@ class CharacterOathInfo:
oathInfo: Union['Oath', None]
"""誓约信息"""
def __init__(self, info={}, equVerison=0, position='') -> None:
def __init__(self, info=None, equVerison=0, position='', equipments=None) -> None:
if info is None:
info = {}
self.__dict__.update(info)
self.id = str(self.id)
oath = get_equipment(equVerison).oath_dict.get(self.id, None)
equipments = equipments or get_equipment(equVerison)
oath = equipments.oath_dict.get(self.id, None)
if oath is not None and position in oath.position:
self.oathInfo = oath.adapt(self.adaptation)
self.adaptation = min(self.adaptation, self.oathInfo.max_adaptation)
@@ -79,7 +85,9 @@ class CharacterEmblemInfo:
lv: int
"""星徽等级"""
def __init__(self, info={}) -> None:
def __init__(self, info=None) -> None:
if info is None:
info = {}
self.__dict__.update(info)
@@ -89,7 +97,9 @@ class CharacterWeaponInfo(CharacterEquipInfo):
upgradeDetail: dict
"""贴膜详情"""
def __init__(self, info={}) -> None:
def __init__(self, info=None) -> None:
if info is None:
info = {}
self.__dict__.update(info)
+82 -43
View File
@@ -1,50 +1,77 @@
from copy import deepcopy
from copy import copy
from collections.abc import Callable
from functools import cache
import json
import re
from typing import Literal, TYPE_CHECKING
from typing import Any, Literal, TYPE_CHECKING
from .formula import 武器冷却惩罚
from database.connect import get_redis
from database.connect import BACKEND_DIR, get_redis_client
from api.core.Redis import get_redis_info
if TYPE_CHECKING:
from core.basic.character import Character
characterLv = 115 + 5
OPENAPI_DIR = BACKEND_DIR / 'openapi'
def _identity(value: Any) -> Any:
return value
@cache
def get_data(prefix: str, key: int | str, func = lambda x: x):
redis = next(get_redis())
def _get_skill_data_suffixes(skill_class: type) -> tuple[str, ...]:
return tuple(key.replace('data', '') for key in dir(skill_class) if key.startswith('data') and not key.startswith('plus'))
@cache
def _get_skill_damage_suffixes(skill_class: type) -> tuple[str, ...]:
return tuple(key.replace('data', '') for key in dir(skill_class) if key.startswith('data') and not key.startswith('dataplus'))
@cache
def _get_skill_dataplus_suffixes(skill_class: type) -> tuple[str, ...]:
return tuple(key.replace('dataplus', '') for key in dir(skill_class) if key.startswith('dataplus'))
@cache
def get_data(prefix: str, key: int | str, func: Callable[[Any], Any] = _identity):
prefix_parts = prefix.split('/')
job = prefix_parts[0]
jobGrow = prefix_parts[1]
skill = prefix_parts[-1]
def get_custom_cn():
with open('./openapi/custom_cn.json', encoding='utf-8') as f:
with (OPENAPI_DIR / 'custom_cn.json').open(encoding='utf-8') as f:
custom_cn = json.load(f)
return custom_cn
def get_skill_info():
# This function should retrieve the skill info based on job and jobGrow
# For now, we return a placeholder dictionary
with open(f'./openapi/data/{prefix}.json', encoding='utf-8') as f:
with (OPENAPI_DIR / 'data' / f'{prefix}.json').open(encoding='utf-8') as f:
skill_data = json.load(f)
custom_cn = get_redis_info(redis, 'dcalc:custom_cn', get_custom_cn, without_gzip=True)
job = prefix.split('/')[0]
jobGrow = prefix.split('/')[1]
skill = prefix.split('/')[-1]
try:
if isinstance(key, int):
data = [0] + list(map(lambda x: x["optionValue"].get("value" + str(key+1), 0), skill_data["levelInfo"]["rows"]))
data = [0] + [row["optionValue"].get("value" + str(key+1), 0) for row in skill_data["levelInfo"]["rows"]]
data = [0 if x is None or x == "-" else x for x in data]
elif key == "vps":
data = [ {"name":x["name"],"desc":x["desc"]} for x in skill_data.get("evolution",[])]
elif key == "custom":
data = next((item.get('custom', 1.0) for item in custom_cn
data = next((item.get('custom', 1.0) for item in custom_cn or []
if item['job'] == job and item['jobGrow'] == jobGrow and item['skillId'] == skill), 1.0)
except Exception as e:
# print(f"get skill {prefix}/{key} data error",e)
except Exception:
# print(f"get skill {prefix}/{key} data error")
data = None
if isinstance(key, int) and not data:
return [0]
if key == 'vps' and data is None:
return []
if key == 'custom' and data is None:
return 1.0
return data
data = get_redis_info(redis, f'dcalc:skill:{prefix}:{key}', get_skill_info, without_gzip=True)
with get_redis_client() as redis:
data = get_redis_info(redis, f'dcalc:skill:{prefix}:{key}', get_skill_info, without_gzip=True)
return func(data)
@@ -174,65 +201,76 @@ class Skill:
self._lv = value
def effect(self, old: int, new: int):
weapon_type = self.char.GetWeaponType()[0]
weapon_options = self.char.武器选项
for assoc in self.associate:
type = assoc.get('type', '*skillDamage')
skills = assoc.get('skills', '*')
data = assoc.get('data', [0] * self.maxLv)
ratio = assoc.get('ratio', 100)
weapon = assoc.get('weapon', self.char.武器选项)
weapon = assoc.get('weapon', weapon_options)
exceptSkills = assoc.get('exceptSkills', [])
if type[0] not in ['*', '+', '=', '$']:
if self.precondition() and (self.char.GetWeaponType()[0] in weapon or len(weapon) == len(self.char.武器选项)):
if self.precondition() and (weapon_type in weapon or len(weapon) == len(weapon_options)):
getattr(self, type)(old, new, data, skills, exceptSkills, ratio, weapon)
continue
if self.precondition():
self.apply_association(type, old, new, data, skills, exceptSkills, ratio, weapon)
self.apply_association(type, old, new, data, skills, exceptSkills, ratio, weapon, weapon_type, weapon_options)
def precondition(self):
"""effect的前置条件"""
return True
def apply_association(self, type, old, new, data, skills, exceptSkills, ratio=100, weapon=[]):
def apply_association(self, type, old, new, data, skills, exceptSkills, ratio=100, weapon=(), weapon_type=None, weapon_options=()):
try:
if (self.char.GetWeaponType()[0] not in weapon) and not (self.char.GetWeaponType()[0] is None and len(weapon) == len(self.char.武器选项)):
if (weapon_type not in weapon) and not (weapon_type is None and len(weapon) == len(weapon_options)):
return
if type.startswith('$*'):
if 'cdReduce' in type:
value = (1 - data[new] / ratio) / (1 - data[old] / ratio)
value = (1 - self.get_data_value(data, new) / ratio) / (1 - self.get_data_value(data, old) / ratio)
else:
value = (1 + data[new] / ratio) / (1 + data[old] / ratio)
eval(f'self.char.SetStatus({type[2:]}={value})')
value = (1 + self.get_data_value(data, new) / ratio) / (1 + self.get_data_value(data, old) / ratio)
self.char.SetStatus(**{type[2:]: value})
elif type.startswith('$+'):
value = data[new] / ratio - data[old] / ratio
eval(f'self.char.SetStatus({type[2:]}={value})')
value = self.get_data_value(data, new) / ratio - self.get_data_value(data, old) / ratio
self.char.SetStatus(**{type[2:]: value})
else:
if skills == '*':
skills = self.char.GetSkillNames('all', True)
exceptSkills = set(exceptSkills)
for name in skills:
if name in exceptSkills:
continue
skill = self.char.GetSkillByName(name)
if skill is not None:
self.update_skill_attribute(skill, type, old, new, data, ratio, weapon)
self.update_skill_attribute(skill, type, old, new, data, ratio, weapon, weapon_type, weapon_options)
except Exception as e:
# print(f"Error applying association {type} for skill {self.name}: {e}")
raise e
def update_skill_attribute(self, skill, type, old, new, data, ratio=100, weapon=[]):
if (self.char.GetWeaponType()[0] not in weapon) and not (self.char.GetWeaponType()[0] is None and len(weapon) == len(self.char.武器选项)):
def update_skill_attribute(self, skill, type, old, new, data, ratio=100, weapon=(), weapon_type=None, weapon_options=()):
if (weapon_type not in weapon) and not (weapon_type is None and len(weapon) == len(weapon_options)):
return
old_value = self.get_data_value(data, old)
new_value = self.get_data_value(data, new)
if type.startswith('*'):
if 'cdReduce' in type or type == 'cd' or 'cdRatio' in type:
setattr(skill, type[1:], getattr(skill, type[1:]) * (1 - data[new] / ratio) / (1 - data[old] / ratio))
setattr(skill, type[1:], getattr(skill, type[1:]) * (1 - new_value / ratio) / (1 - old_value / ratio))
else:
setattr(skill, type[1:], getattr(skill, type[1:]) * (1 + data[new] / ratio) / (1 + data[old] / ratio))
setattr(skill, type[1:], getattr(skill, type[1:]) * (1 + new_value / ratio) / (1 + old_value / ratio))
elif type.startswith('+'):
if type[1:] == 'lv' and self.char.setInfo.get('skills', {}).get(str(skill.id),{}).get('lv',0) == 0:
return
else:
setattr(skill, type[1:], getattr(skill, type[1:]) + data[new] / ratio - data[old] / ratio)
setattr(skill, type[1:], getattr(skill, type[1:]) + new_value / ratio - old_value / ratio)
elif type.startswith('='):
setattr(skill, type[1:], data[new])
setattr(skill, type[1:], new_value)
@staticmethod
def get_data_value(data, index: int):
if 0 <= index < len(data):
return data[index]
return 0
def skillInfo(self, mode: str | None = None):
pass
@@ -252,8 +290,7 @@ class ActiveSkill(Skill):
def __init__(self, char):
super().__init__(char)
keys = [key.replace('data', '') for key in dir(self) if key.startswith('data') and not key.startswith('plus')]
for i in keys:
for i in _get_skill_data_suffixes(self.__class__):
power = getattr(self, f'power{i}', None)
if power is None:
setattr(self, f'power{i}', 1)
@@ -262,7 +299,12 @@ class ActiveSkill(Skill):
setattr(self, f'hit{i}', 0)
def skillInfo(self, mode: str | None = None):
basic = deepcopy(self)
basic = copy(self)
for key, value in self.__dict__.items():
if isinstance(value, list):
setattr(basic, key, value.copy())
elif isinstance(value, dict):
setattr(basic, key, value.copy())
basic.setUP()
if mode is not None:
basic.currentMode = mode
@@ -298,8 +340,7 @@ class ActiveSkill(Skill):
def getSkillData(self, lv: int = 0):
res = 0
keys = [key.replace('data', '') for key in dir(self) if key.startswith('data') and not key.startswith('dataplus')]
for i in keys:
for i in _get_skill_damage_suffixes(self.__class__):
data = getattr(self, f'data{i}', [])
plus = getattr(self, f'plus{i}', 0)
hit = getattr(self, f'hit{i}', 0)
@@ -309,8 +350,7 @@ class ActiveSkill(Skill):
hit = getattr(self, f'hit{i}', 0)
power = getattr(self, f'power{i}', 1)
res += hit * power * (data[lv] + plus)
keys = [key.replace('dataplus', '') for key in dir(self) if key.startswith('dataplus')]
for i in keys:
for i in _get_skill_dataplus_suffixes(self.__class__):
data = getattr(self, f'dataplus{i}', 0)
hit = getattr(self, f'hitplus{i}', 1)
power = getattr(self, f'powerplus{i}', 1)
@@ -397,8 +437,7 @@ class BuffSkill(Skill):
def __init__(self, char):
super().__init__(char)
keys = [key.replace('data', '') for key in dir(self) if key.startswith('data') and not key.startswith('plus')]
for i in keys:
for i in _get_skill_data_suffixes(self.__class__):
power = getattr(self, f'power{i}', None)
if power is None:
setattr(self, f'power{i}', 1)
+3 -5
View File
@@ -1,5 +1,5 @@
# b9cb48777665de22c006fabaf9a560b3
from core.basic.skill import PassiveSkill, ActiveSkill, get_data
from core.basic.skill import PassiveSkill, ActiveSkill, get_data, _get_skill_damage_suffixes, _get_skill_dataplus_suffixes
from core.basic.character import Character
prefix = 'archer/hunter/cn/skillDetail'
@@ -12,8 +12,7 @@ class HunterActiveSkill(ActiveSkill):
# 标记消耗,大于0为消耗,小于0为生成
def getSkillData(self, lv: int = 0):
res = 0
keys = [key.replace('data', '') for key in dir(self) if key.startswith('data') and not key.startswith('dataplus')]
for i in keys:
for i in _get_skill_damage_suffixes(self.__class__):
data = getattr(self, f'data{i}', [])
plus = getattr(self, f'plus{i}', 0)
hit = getattr(self, f'hit{i}', 0)
@@ -24,8 +23,7 @@ class HunterActiveSkill(ActiveSkill):
power = getattr(self, f'power{i}', 1)
cost = getattr(self, f'cost{i}', 0)
res += hit * power * (data[lv] + plus) * ((1 + self.normalRation) if cost <= 0 else (1 + self.markRation * cost))
keys = [key.replace('dataplus', '') for key in dir(self) if key.startswith('dataplus')]
for i in keys:
for i in _get_skill_dataplus_suffixes(self.__class__):
data = getattr(self, f'dataplus{i}', 0)
hit = getattr(self, f'hitplus{i}', 1)
power = getattr(self, f'powerplus{i}', 1)
+3 -5
View File
@@ -1,5 +1,5 @@
# ddc49e9ad1ff72a00b53c6cff5b1e920
from core.basic.skill import PassiveSkill, ActiveSkill, get_data
from core.basic.skill import PassiveSkill, ActiveSkill, get_data, _get_skill_damage_suffixes, _get_skill_dataplus_suffixes
from core.basic.character import Character
prefix = 'thief/rogue/cn/skillDetail'
@@ -14,8 +14,7 @@ class ActiveSkill(ActiveSkill):
def getSkillData(self, lv: int = 0):
res = 0
keys = [key.replace('data', '') for key in dir(self) if key.startswith('data') and not key.startswith('dataplus')]
for i in keys:
for i in _get_skill_damage_suffixes(self.__class__):
data = getattr(self, f'data{i}', [])
plus = getattr(self, f'plus{i}', 0)
if len(data) == 0:
@@ -25,8 +24,7 @@ class ActiveSkill(ActiveSkill):
power = getattr(self, f'power{i}', 1)
group = getattr(self, f'group{i}', 'normal')
res += hit * power * (data[lv] + plus) * (self.endpower if group == 'end' else 1)
keys = [key.replace('dataplus', '') for key in dir(self) if key.startswith('dataplus')]
for i in keys:
for i in _get_skill_dataplus_suffixes(self.__class__):
data = getattr(self, f'dataplus{i}', 0)
hit = getattr(self, f'hitplus{i}', 1)
power = getattr(self, f'powerplus{i}', 1)
-1
View File
@@ -1,4 +1,3 @@
from core.basic.equipment import EquEffect
from core.abstract.character import CharacterProperty
from .register import register
+3 -4
View File
@@ -1,11 +1,10 @@
registry = {}
def register(func):
registry[func.__name__] = func
return func
def execture(name):
if name in registry:
return registry[name]
else:
return None
return registry.get(name, None)
+5 -6
View File
@@ -117,12 +117,11 @@ def trans_to_dcalc_set(detail, alter: AltersDep):
if job != alter.origin:
raise ResponseException('未能匹配到当前职业对应的角色信息,请确认后重试')
basic = get_equipment('0')
basicAvatars = basic.funs.get_dress_list([])
equips = {}
avatar = {}
avatarDisplay = {}
emblems = {}
oaths = {}
basicAvatars = basic.funs.get_dress_list([])
equips = {}
avatar = {}
emblems = {}
oaths = {}
for equ in detail.get('equs', []):
info = {
'id': '0',
+12 -14
View File
@@ -1,6 +1,5 @@
import os
import platform
import re
import platform
import re
host_window = r'C:\Windows\System32\drivers\etc\hosts'
host_mac = r'/etc/hosts'
@@ -14,23 +13,22 @@ def search_host(hostvalue):
host_path = host_mac
else:
host_path = host_window
hostfile = open(host_path, 'r', errors='ignore')
each_line = hostfile.readlines()
hostfile.close()
with open(host_path, errors='ignore') as hostfile:
each_line = hostfile.readlines()
findresult = re.findall(hostvalue, ''.join(each_line))
return findresult
def write_host(hostvalue):
if platform.system().lower() != 'windows':
output = open(host_mac, 'a')
else:
output = open(host_window, 'a')
for insid in hostvalue:
output.write(insid)
output.write('\n')
output.close()
output = open(host_mac, 'a')
else:
output = open(host_window, 'a')
with output:
for insid in hostvalue:
output.write(insid)
output.write('\n')
def host_init():