feat(hero): 优化英雄详情页技能展示逻辑
1. 新增带等级和升级预览的技能描述渲染函数 2. 为技能档位添加专属命名,支持按触发语境显示技能名 3. 给所有技能档位补充技能等级标注,优化面板展示 4. 新增200个游戏技能名称配置文件
This commit is contained in:
@@ -28,7 +28,7 @@
|
||||
* - SkillDescSet:结构化描述模板
|
||||
* - FieldSkillSet(驻场技能)、BuffList(计时 buff 默认值兜底)、Attrs(属性枚举)
|
||||
*/
|
||||
import { SkillTriggerName, SkillTriggerType, TriggerGrouped, LvTriggerEntry, LvFieldEntry, LvReviveEntry, LvBonusEntry, resolveTriggerByLv, resolveFieldByLv, resolveReviveByLv } from "./heroSet";
|
||||
import { SkillTriggerName, SkillTriggerType, TriggerGrouped, LvTriggerEntry, LvFieldEntry, LvReviveEntry, LvBonusEntry, resolveTriggerByLv, resolveFieldByLv, resolveReviveByLv, getTriggerSkillName } from "./heroSet";
|
||||
import { FieldSkillSet, mergeSkillParams, SkillConfig, SkillKind, SkillOverrides, SkillSet, TGroup } from "./SkillSet";
|
||||
import { FieldDescSet, FieldValueFmt, SkillDescSet } from "./SkillDescSet";
|
||||
import { BuffList } from "./BuffSet";
|
||||
@@ -347,7 +347,8 @@ function buildSkillLines(source: ISkillDescSource, showName: boolean = true, sho
|
||||
if (!base) continue;
|
||||
const skill = mergeSkillParams(base, item.overrides);
|
||||
const trigger = needCount ? `${name}×${item.t_num}` : name;
|
||||
const nameSeg = showName ? `「${base.name}」 ` : "";
|
||||
// 触发语境专属名称(如 atked.6301=不屈壁垒),未配置回退通用名
|
||||
const nameSeg = showName ? `「${getTriggerSkillName(key, item.s_uuid)}」 ` : "";
|
||||
lines.push(buildEffectLine(`${trigger}:${nameSeg}`, skill));
|
||||
}
|
||||
continue;
|
||||
@@ -360,7 +361,7 @@ function buildSkillLines(source: ISkillDescSource, showName: boolean = true, sho
|
||||
const base = SkillSet[Number(sKey)];
|
||||
if (!base) continue;
|
||||
const sorted = [...entries].sort((a, b) => a.lv - b.lv);
|
||||
const nameSeg = showName ? `「${base.name}」 ` : "";
|
||||
const nameSeg = showName ? `「${getTriggerSkillName(key, Number(sKey))}」 ` : "";
|
||||
const headOf = (e: LvTriggerEntry) => `Lv${e.lv}: ${needCount ? `${name}×${e.t_num}` : name} ${nameSeg}`;
|
||||
|
||||
// 取当前等级生效档(≤lv 的最大档)
|
||||
@@ -504,6 +505,92 @@ export function buildEquipRich(fieldUuids: number[], showName: boolean = false):
|
||||
return lines.length > 0 ? lines.join("\n") : "无词条";
|
||||
}
|
||||
|
||||
/**
|
||||
* 英雄信息弹窗技能描述富文本(HeroMoreCom 用)。
|
||||
*
|
||||
* 格式:
|
||||
* 「技能名」 Lv.当前技能等级:当前档技能效果
|
||||
* 升级提示:Lv.当前 → Lv.下一级:下一级技能效果(金色,仅有更高档时出现)
|
||||
*
|
||||
* 数据源为运行时 HeroAttrsComp(lv 取当前英雄等级),逐触发类型逐技能渲染。
|
||||
* 技能等级取 LvTriggerEntry.s_lv,未标注时按档位序号(1/2/3...)兜底。
|
||||
*
|
||||
* @param source 英雄运行时数据源(含 lv 与触发技能分组)
|
||||
* @returns 多行富文本串,\n 分隔
|
||||
*/
|
||||
export function buildSkillDescMoreRich(source: ISkillDescSource): string {
|
||||
const lv = Math.max(1, source.lv ?? 1);
|
||||
const lines: string[] = [];
|
||||
|
||||
// 单条效果 → 富文本(技能名蓝色、数值绿色高亮、持续秒数高亮)
|
||||
const effectRich = (line: ISkillLine): string => {
|
||||
const prefix = line.prefix.replace(SKILL_NAME_PATTERN, `「<color=${RICH_NAME_COLOR}>$1</color>」`);
|
||||
const text = line.value
|
||||
? `${prefix}<color=${RICH_VALUE_COLOR}>${line.value}</color>${line.suffix}`
|
||||
: `${prefix}${line.suffix}`;
|
||||
return highlightDuration(text);
|
||||
};
|
||||
|
||||
for (const key of TRIGGER_KEYS) {
|
||||
const grouped = source[key] as TriggerGrouped | undefined;
|
||||
if (!grouped) continue;
|
||||
const trigName = SkillTriggerName[key] ?? key;
|
||||
const needCount = key === SkillTriggerType.Atking || key === SkillTriggerType.Atked;
|
||||
|
||||
for (const sKey in grouped) {
|
||||
const entries = grouped[sKey];
|
||||
if (!entries?.length) continue;
|
||||
const sUuid = Number(sKey);
|
||||
const base = SkillSet[sUuid];
|
||||
if (!base) continue;
|
||||
const sorted = [...entries].sort((a, b) => a.lv - b.lv);
|
||||
// 技能名走触发语境专属命名(如 atked.6301=不屈壁垒)
|
||||
const skillName = getTriggerSkillName(key, sUuid);
|
||||
|
||||
// 当前生效档(≤lv 最大档),未激活则用最低档
|
||||
let activeIdx = -1;
|
||||
for (let i = 0; i < sorted.length; i++) {
|
||||
if (sorted[i].lv <= lv) activeIdx = i;
|
||||
}
|
||||
const curIdx = activeIdx >= 0 ? activeIdx : 0;
|
||||
const cur = sorted[curIdx];
|
||||
const curSLv = cur.s_lv ?? (curIdx + 1);
|
||||
const curTrig = needCount ? `${trigName}×${cur.t_num}` : trigName;
|
||||
const curHead = `「${skillName}」 Lv.${curSLv}: ${curTrig},`;
|
||||
lines.push(effectRich(buildEffectLine(curHead, mergeSkillParams(base, cur.overrides))));
|
||||
|
||||
// 升级提示:存在更高档时,金色预览下一档
|
||||
if (curIdx + 1 < sorted.length) {
|
||||
const next = sorted[curIdx + 1];
|
||||
const nextSLv = next.s_lv ?? (curIdx + 2);
|
||||
const nextTrig = needCount ? `${trigName}×${next.t_num}` : trigName;
|
||||
const nextLine = buildEffectLine(`${nextTrig},`, mergeSkillParams(base, next.overrides));
|
||||
const nextText = `${nextLine.prefix}${nextLine.value}${nextLine.suffix}`;
|
||||
lines.push(`<color=${RICH_UPGRADE_COLOR}>升级 Lv.${curSLv}→Lv.${nextSLv}: ${nextText}</color>`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 驻场光环(field)
|
||||
const fieldEntries = source[SkillTriggerType.Field] as LvFieldEntry[] | undefined;
|
||||
if (fieldEntries?.length) {
|
||||
const tpl = SkillTriggerName[SkillTriggerType.Field] ?? "光环";
|
||||
for (const uuid of resolveFieldByLv(fieldEntries, lv)) {
|
||||
const line = buildFieldLine(`${tpl}: `, uuid, true);
|
||||
if (line) lines.push(effectRich(line));
|
||||
}
|
||||
}
|
||||
|
||||
// 复活(revive)
|
||||
const revive = resolveReviveByLv(source[SkillTriggerType.Revive] as LvReviveEntry[] | undefined, lv);
|
||||
if (revive) {
|
||||
const reviveName = getTriggerSkillName(SkillTriggerType.Revive, revive.s_uuid);
|
||||
lines.push(`「<color=${RICH_NAME_COLOR}>${reviveName}</color>」: 死亡后以<color=${RICH_VALUE_COLOR}>${Math.round(revive.upr * 100)}%</color>血量复活<color=${RICH_VALUE_COLOR}>${revive.r_num}</color>次`);
|
||||
}
|
||||
|
||||
return lines.join("\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* 把"持续X秒"中的 X 也包裹绿色高亮(卡片描述后处理)。
|
||||
* Why: 计时模板 {dur} 不在 \x01\x02 高亮标记内,renderLineRich 仅高亮主数值;
|
||||
@@ -513,6 +600,9 @@ function highlightDuration(text: string): string {
|
||||
return text.replace(DURATION_PATTERN, `持续<color=${RICH_VALUE_COLOR}>$1</color>秒`);
|
||||
}
|
||||
|
||||
/** 富文本升级提示色(金色,标识"升级后"的下一档预览,与未激活灰区分) */
|
||||
const RICH_UPGRADE_COLOR = "#E8A33D";
|
||||
|
||||
/**
|
||||
* 结构化行 → 富文本串(技能名蓝色、数值绿色)。
|
||||
* buildEquipRich / buildCardDescRich / buildSkillDescRich 共用,保证渲染规则唯一。
|
||||
|
||||
Reference in New Issue
Block a user