new:进一步完善加点代码导入
This commit is contained in:
+103
-21
@@ -81,7 +81,7 @@ def decode_skill_hash(encoded: str) -> dict:
|
||||
break
|
||||
skills.append(
|
||||
{
|
||||
'skill_index': high[i],
|
||||
'skill_index': high[i] + 0x100 if low[i + 1] else high[i],
|
||||
'level': high[i + 1],
|
||||
'skill_flag': low[i],
|
||||
'level_flag': low[i + 1],
|
||||
@@ -91,7 +91,7 @@ def decode_skill_hash(encoded: str) -> dict:
|
||||
sec2_bytes = data[(1 + num_pairs * 2) * 2 :]
|
||||
evolutions, enhancements, keybinds, remaining = _parse_section2(sec2_bytes)
|
||||
|
||||
return {
|
||||
result = {
|
||||
'header': header,
|
||||
'skills': skills,
|
||||
'evolutions': evolutions,
|
||||
@@ -100,6 +100,10 @@ def decode_skill_hash(encoded: str) -> dict:
|
||||
'section2_remaining': remaining,
|
||||
'raw_size': len(raw),
|
||||
}
|
||||
# 黑暗武士才有技能排列;其他职业保持原有返回结构不变。
|
||||
if header['job_bytes'][0] == 9:
|
||||
result['arrangements'] = _parse_dark_knight_arrangements(remaining)
|
||||
return result
|
||||
|
||||
|
||||
def _parse_header(raw: bytes) -> dict:
|
||||
@@ -141,7 +145,7 @@ def _parse_section2(sec2: bytes):
|
||||
break
|
||||
evolutions.append(
|
||||
{
|
||||
'skill_index': sec2[off],
|
||||
'skill_index': sec2[off] + 0x100 if sec2[off + 1] else sec2[off],
|
||||
'flag': sec2[off + 1],
|
||||
'type': sec2[off + 2] + 1,
|
||||
}
|
||||
@@ -159,7 +163,7 @@ def _parse_section2(sec2: bytes):
|
||||
break
|
||||
enhancements.append(
|
||||
{
|
||||
'skill_index': sec2[off],
|
||||
'skill_index': sec2[off] + 0x100 if sec2[off + 1] else sec2[off],
|
||||
'flag': sec2[off + 1],
|
||||
'type': sec2[off + 2] + 1,
|
||||
}
|
||||
@@ -175,7 +179,7 @@ def _parse_section2(sec2: bytes):
|
||||
for slot in range(key_count):
|
||||
if off + 2 > len(sec2):
|
||||
break
|
||||
idx = sec2[off]
|
||||
idx = sec2[off] + 0x100 if sec2[off + 1] else sec2[off]
|
||||
flag = sec2[off + 1]
|
||||
keybinds.append(
|
||||
{
|
||||
@@ -190,23 +194,61 @@ def _parse_section2(sec2: bytes):
|
||||
return evolutions, enhancements, keybinds, remaining
|
||||
|
||||
|
||||
def _resolve_openapi_skill_id(skill_index: int, level_flag: int, skill_name_map: dict[str, str]) -> int | None:
|
||||
if level_flag:
|
||||
high_skill_id = skill_index + 0x100
|
||||
if str(high_skill_id) in skill_name_map:
|
||||
return high_skill_id
|
||||
def _parse_dark_knight_arrangements(remaining: bytes) -> list[dict]:
|
||||
"""从原始 remaining 前缀中读取黑暗武士技能排列。
|
||||
|
||||
黑暗武士的排列格式为:排列组数(1B),随后每组依次存储
|
||||
排列槽索引(2B)、组内技能数(1B)和对应数量的技能索引(2B)。
|
||||
|
||||
本函数只读取已确认的排列前缀,不解析或截断排列后的未知数据;
|
||||
decode_skill_hash 仍按原格式返回完整的 section2_remaining。
|
||||
"""
|
||||
if not remaining:
|
||||
return []
|
||||
|
||||
arrangement_count = remaining[0]
|
||||
off = 1
|
||||
arrangements = []
|
||||
for _ in range(arrangement_count):
|
||||
if off + 3 > len(remaining):
|
||||
break
|
||||
|
||||
slot_index = remaining[off] + 0x100 if remaining[off + 1] else remaining[off]
|
||||
off += 2
|
||||
skill_count = remaining[off]
|
||||
off += 1
|
||||
if off + skill_count * 2 > len(remaining):
|
||||
break
|
||||
|
||||
skills = []
|
||||
for _ in range(skill_count):
|
||||
skill_index = remaining[off] + 0x100 if remaining[off + 1] else remaining[off]
|
||||
skills.append(skill_index)
|
||||
off += 2
|
||||
|
||||
arrangements.append(
|
||||
{
|
||||
'slot_index': slot_index,
|
||||
'skills': skills,
|
||||
}
|
||||
)
|
||||
|
||||
return arrangements
|
||||
|
||||
|
||||
def _resolve_openapi_skill_id(skill_index: int, skill_name_map: dict[str, str]) -> int | None:
|
||||
if str(skill_index) in skill_name_map:
|
||||
return skill_index
|
||||
return None
|
||||
|
||||
|
||||
def _resolve_section_skill_id(skill_index: int, skill_name_map: dict[str, str]) -> int | None:
|
||||
high_skill_id = skill_index + 0x100
|
||||
if str(high_skill_id) in skill_name_map:
|
||||
return high_skill_id
|
||||
if str(skill_index) in skill_name_map:
|
||||
return skill_index
|
||||
return None
|
||||
# def _resolve_section_skill_id(skill_index: int, skill_name_map: dict[str, str]) -> int | None:
|
||||
# high_skill_id = skill_index + 0x100
|
||||
# if str(high_skill_id) in skill_name_map:
|
||||
# return high_skill_id
|
||||
# if str(skill_index) in skill_name_map:
|
||||
# return skill_index
|
||||
# return None
|
||||
|
||||
|
||||
def get_skill_tree_info(encoded: str) -> dict:
|
||||
@@ -241,7 +283,7 @@ def get_skill_tree_info(encoded: str) -> dict:
|
||||
skillMap = {}
|
||||
for index, i in enumerate(r['skills']):
|
||||
skillIndex = i['skill_index']
|
||||
actualSkillId = _resolve_openapi_skill_id(skillIndex, i.get('level_flag'), skill_name_map)
|
||||
actualSkillId = _resolve_openapi_skill_id(skillIndex, skill_name_map)
|
||||
skillName = skill_name_map.get(str(actualSkillId)) if actualSkillId is not None else None
|
||||
skills = [skill for skill in character.skills if skill.name == skillName] if skillName else []
|
||||
i['actual_skill_id'] = actualSkillId
|
||||
@@ -273,14 +315,14 @@ def get_skill_tree_info(encoded: str) -> dict:
|
||||
}
|
||||
# 处理进化
|
||||
for evo in r['evolutions']:
|
||||
actualSkillId = _resolve_section_skill_id(evo['skill_index'], skill_name_map)
|
||||
actualSkillId = _resolve_openapi_skill_id(evo['skill_index'], skill_name_map)
|
||||
for s in skillMap.get(actualSkillId, []):
|
||||
if getattr(s, 'hasVP', False) and str(s.id) in skillLearn:
|
||||
skillLearn[str(s.id)]['vp'] = evo['type']
|
||||
|
||||
# 处理强化
|
||||
for enh in r['enhancements']:
|
||||
actualSkillId = _resolve_section_skill_id(enh['skill_index'], skill_name_map)
|
||||
actualSkillId = _resolve_openapi_skill_id(enh['skill_index'], skill_name_map)
|
||||
for s in skillMap.get(actualSkillId, []):
|
||||
if getattr(s, 'hasUP', False) and str(s.id) in skillLearn:
|
||||
skillLearn[str(s.id)]['up'] = enh['type']
|
||||
@@ -292,11 +334,51 @@ def get_skill_tree_info(encoded: str) -> dict:
|
||||
'vp': 0,
|
||||
'name': i.name,
|
||||
}
|
||||
shortcuts = []
|
||||
for k in r['keybinds']:
|
||||
actualSkillId = _resolve_openapi_skill_id(k['skill_index'], skill_name_map)
|
||||
if actualSkillId is None:
|
||||
shortcuts.append({
|
||||
'slot': k['slot'],
|
||||
'skill_id': None,
|
||||
'skill_name': None,
|
||||
})
|
||||
continue
|
||||
for s in skillMap.get(actualSkillId, []):
|
||||
if str(s.id) in skillLearn:
|
||||
shortcuts.append({
|
||||
'slot': k['slot'],
|
||||
'skill_id': s.id,
|
||||
'skill_name': s.name,
|
||||
})
|
||||
if s is None:
|
||||
shortcuts.append({
|
||||
'slot': k['slot'],
|
||||
'skill_id': None,
|
||||
'skill_name': None,
|
||||
})
|
||||
combos = []
|
||||
for a in r.get('arrangements', []):
|
||||
combo = {
|
||||
'slot_index': a['slot_index'],
|
||||
'skills': [],
|
||||
}
|
||||
for skillIndex in a['skills']:
|
||||
actualSkillId = _resolve_openapi_skill_id(skillIndex, skill_name_map)
|
||||
for s in skillMap.get(actualSkillId, []):
|
||||
if str(s.id) in skillLearn:
|
||||
combo['skills'].append({
|
||||
'skill_id': s.id,
|
||||
'skill_name': s.name,
|
||||
})
|
||||
combos.append(combo)
|
||||
return {
|
||||
"name": header['name'],
|
||||
"level": header['level'],
|
||||
"job":advInfo,
|
||||
"skills": skillLearn
|
||||
"skills": skillLearn,
|
||||
"shortcuts":shortcuts,
|
||||
"combos":combos,
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user