🚧 build skill parser

This commit is contained in:
Karako 2023-05-02 18:20:27 +08:00
parent f958a2d749
commit 8259775837
No known key found for this signature in database
GPG Key ID: 5920831B0095D4A0
4 changed files with 216 additions and 17 deletions

View File

@ -1,10 +1,10 @@
from typing import TYPE_CHECKING
from model.enums import Association, AvatarQuality, Element, WeaponType
from model.other import ItemCount
from utils.model import BaseModel
if TYPE_CHECKING:
from model.item import Item
from model.avatar._talente import AvatarTalents
__all__ = (
@ -16,7 +16,7 @@ __all__ = (
"AvatarStories",
"Story",
"Seuyu",
"ItemCount",
"AvatarAttribute",
)
@ -102,16 +102,7 @@ class AvatarInfo(BaseModel):
"""故事"""
class ItemCount(BaseModel):
item: "Item"
"""物品"""
count: int
"""数量"""
class AvatarPromote(BaseModel):
required_level: int = 0
"""突破所需等级"""
promote_level: int = 0
"""突破等级"""
max_level: int
@ -119,7 +110,7 @@ class AvatarPromote(BaseModel):
coin: int = 0
"""摩拉"""
items: list[ItemCount] = []
cost_items: list[ItemCount] = []
"""突破所需材料"""
@ -134,6 +125,41 @@ class AvatarConstellation(BaseModel):
"""命座图标"""
class AvatarAttribute(BaseModel):
"""角色属性"""
HP: float
"""生命值"""
Attack: float
"""攻击力"""
Defense: float
"""防御力"""
Critical: float
"""暴击率"""
CriticalDamage: float
"""暴击伤害"""
ChargeEfficiency: float
"""元素充能效率"""
ElementalMastery: float = 0
"""元素精通"""
PhysicalAddHurt: float = 0
"""物理伤害加成"""
PyroAddHurt: float = 0
"""火元素伤害加成"""
HydroAddHurt: float = 0
"""水元素伤害加成"""
AnemoAddHurt: float = 0
"""风元素伤害加成"""
ElectroAddHurt: float = 0
"""雷元素伤害加成"""
DendroAddHurt: float = 0
"""草元素伤害加成"""
CryoAddHurt: float = 0
"""冰元素伤害加成"""
GeoAddHurt: float = 0
"""岩元素伤害加成"""
class Avatar(BaseModel):
"""角色"""
@ -149,9 +175,11 @@ class Avatar(BaseModel):
"""武器类型"""
information: AvatarInfo
"""角色信息"""
promote: AvatarPromote
"""角色突破数据"""
attributes: AvatarAttribute
"""角色基础属性"""
talents: "AvatarTalents"
"""角色天赋信息"""
promotes: list[AvatarPromote]
"""角色突破数据"""
constellations: list[AvatarConstellation]
"""角色命座信息"""

View File

@ -1,6 +1,8 @@
from utils.model import BaseModel
from typing import ClassVar
from model.other import ItemCount
from utils.model import BaseModel
__all__ = (
"Talent",
"CombatTalent",
@ -15,9 +17,26 @@ __all__ = (
"UtilityPassive",
"MiscellaneousPassive",
"AvatarTalents",
"TalentAttribute",
)
class TalentAttribute(BaseModel):
level: int
"""等级"""
param_descriptions: list[str]
"""参数描述"""
param_list: list[float]
"""参数列表"""
break_level: int = 0
"""所需突破等级"""
coin: int = 0
"""摩拉"""
cost_items: list[ItemCount] = []
"""消耗物品"""
class Talent(BaseModel):
name: str
"""天赋名称"""
@ -28,7 +47,7 @@ class Talent(BaseModel):
level: int = 0
"""解锁等级"""
params: list[float] = []
attributes: list[TalentAttribute]
"""数值参数列表"""

8
model/other.py Normal file
View File

@ -0,0 +1,8 @@
from utils.model import BaseModel
class ItemCount(BaseModel):
item_id: int
"""物品ID"""
count: int
"""数量"""

View File

@ -1,11 +1,34 @@
from itertools import chain
from typing import TypeVar
from model.avatar import AvatarBirth, AvatarInfo, AvatarStories, Seuyu, Story
from model.avatar import (
AlternateSprint,
AvatarAttribute,
AvatarBirth,
AvatarInfo,
AvatarPromote,
AvatarStories,
ElementalBurst,
ElementalSkill,
NormalAttack,
Seuyu,
Story,
Talent,
TalentAttribute,
)
from model.enums import Association, AvatarQuality, Element, WeaponType
from model.other import ItemCount
from utils.const import PROJECT_ROOT
from utils.manager import ResourceManager
from utils.typedefs import Lang
try:
import regex as re
except ImportError:
import re
T = TypeVar("T", bound=Talent)
OUT_DIR = PROJECT_ROOT.joinpath("out")
elements = {
@ -29,6 +52,11 @@ async def parse_avatar_data(lang: Lang):
avatar_json_data = manager.fetch("AvatarExcelConfigData")
fetter_info_json_data = manager.fetch("FetterInfoExcelConfigData")
story_json_data = manager.fetch("FetterStoryExcelConfigData")
promote_json_data = manager.fetch("AvatarPromoteExcelConfigData")
skill_depot_json_data = manager.fetch("AvatarSkillDepotExcelConfigData")
skill_json_data = manager.fetch("AvatarSkillExcelConfigData")
proud_skill_json_data = manager.fetch("ProudSkillExcelConfigData")
avatar_list = []
for data in avatar_json_data:
@ -51,6 +79,7 @@ async def parse_avatar_data(lang: Lang):
filter(lambda x: x in data["weaponType"], WeaponType.__members__.values())
)
# 角色信息
title = manager.get_text(info_data["avatarTitleTextMapHash"])
birth = AvatarBirth(
month=info_data["infoBirthMonth"], day=info_data["infoBirthDay"]
@ -113,4 +142,119 @@ async def parse_avatar_data(lang: Lang):
stories=stories,
)
# 角色基础属性
attribute = AvatarAttribute(
HP=data["hpBase"],
Attack=data["attackBase"],
Defense=data["defenseBase"],
Critical=data["critical"],
CriticalDamage=data["criticalHurt"],
ChargeEfficiency=data["chargeEfficiency"],
)
def get_skill_attributes(proud_skill_group_id: int) -> list[TalentAttribute]:
proud_skill_datas = sorted(
filter(
lambda x: x["proudSkillGroupId"] == proud_skill_group_id,
proud_skill_json_data,
),
key=lambda x: x["level"],
)
result: list[TalentAttribute] = []
for proud_skill_data in proud_skill_datas:
param_descriptions = list(
filter(
lambda x: x is not None,
map(
lambda x: manager.get_text(x),
proud_skill_data["paramDescList"],
),
)
)
param_num = len(param_descriptions)
for param_description in param_descriptions:
param_num = max(
param_num,
*map(int, re.findall(r"param(\d*)\:", param_description)),
)
result.append(
TalentAttribute(
level=proud_skill_data["level"],
param_descriptions=param_descriptions,
param_list=proud_skill_data["paramList"][:param_num],
break_level=proud_skill_data.get("breakLevel", 0),
coin=proud_skill_data.get("coinCost", 0),
cost_items=list(
map(
lambda x: ItemCount(
item_id=x["id"],
count=x["count"],
),
filter(lambda x: x, proud_skill_data["costItems"]),
)
),
)
)
return result
def parse_skill(skill_id: int, skill_cls: type[T]) -> T:
skill_data = next(filter(lambda x: x["id"] == skill_id, skill_json_data))
_name = manager.get_text(skill_data["nameTextMapHash"])
_description = manager.get_text(skill_data["descTextMapHash"])
icon = skill_data["skillIcon"]
cooldown = (
skill_data.get("cdTime", 0)
if "cooldown" in skill_cls.__fields__.keys()
else None
)
attributes = get_skill_attributes(skill_data["proudSkillGroupId"])
return skill_cls(
**{
i[0]: i[1]
for i in zip(
["name", "description", "icon", "cooldown", "attributes"],
[_name, _description, icon, cooldown, attributes],
)
if i is not None
}
)
# 天赋
skill_depot_data = next(
filter(lambda x: x["id"] == data["skillDepotId"], skill_depot_json_data)
)
skill_ids = list(filter(lambda x: x != 0, skill_depot_data["skills"]))
# 普通攻击
normal_attack = parse_skill(skill_ids[0], NormalAttack)
# 元素战技
elemental_skill = parse_skill(skill_ids[1], ElementalSkill)
# 冲刺技能
if len(skill_ids) == 3:
alternate_sprint = parse_skill(skill_ids[2], AlternateSprint)
# 元素爆发
burst_skill = parse_skill(skill_depot_data["energySkill"], ElementalBurst)
breakpoint()
# 角色突破数据
promote_id = data["avatarPromoteId"]
promote_datas = sorted(
filter(lambda x: x["avatarPromoteId"] == promote_id, promote_json_data),
key=lambda x: x.get("promoteLevel", 0),
)
promotes = []
for promote_data in promote_datas:
items = []
for item_data in promote_data["costItems"]:
if item_data:
items.append(
ItemCount(item_id=item_data["id"], count=item_data["count"])
)
promotes.append(
AvatarPromote(
promote_level=promote_data.get("promoteLevel", 0),
max_level=promote_data["unlockMaxLevel"],
coin=promote_data.get("scoinCost", 0),
cost_items=items,
)
)
breakpoint()