feat: 重构卡牌描述渲染系统,实现动态富文本展示
1. 新增SkillDescSet配置商店技能与药水模板,补充6201-6206范围攻击与6502-6511计时强化技能配置 2. 替换原有单/多文本标签为富文本组件,统一使用buildCardDescRich生成描述 3. 简化物品商店与卡牌组件的描述渲染逻辑,移除冗余的getDescription方法 4. 为药水卡片移除硬编码描述,改为从技能模板动态生成,自动高亮数值与持续时间 5. 实现附加概率后缀自动生成,支持暴击/冰冻/击晕/击退概率动态展示
This commit is contained in:
@@ -33,6 +33,7 @@ import { FieldSkillSet, mergeSkillParams, SkillConfig, SkillKind, SkillOverrides
|
||||
import { FieldDescSet, FieldValueFmt, SkillDescSet } from "./SkillDescSet";
|
||||
import { BuffList } from "./BuffSet";
|
||||
import { Attrs } from "./HeroAttrs";
|
||||
import { CardConfig } from "./CardSet";
|
||||
|
||||
/**
|
||||
* 生成器入参窄接口:只约束实际读取的字段。
|
||||
@@ -91,6 +92,9 @@ const RICH_NAME_COLOR = "#2E86C1";
|
||||
/** 技能名「」匹配模式(仅本模块行首/行中技能名片段使用) */
|
||||
const SKILL_NAME_PATTERN = /「([^」]*)」/g;
|
||||
|
||||
/** "持续X秒"匹配模式(卡片描述后处理:把持续时间数值也高亮) */
|
||||
const DURATION_PATTERN = /持续(\d+)秒/g;
|
||||
|
||||
/** 解析目标描述文本(与战斗 SCastSystem 目标选取语义严格一致) */
|
||||
function buildTargetDesc(skill: SkillConfig): string {
|
||||
switch (skill.TGroup) {
|
||||
@@ -374,3 +378,92 @@ export function buildEquipRich(fieldUuids: number[]): string {
|
||||
}
|
||||
return lines.length > 0 ? lines.join("\n") : "无词条";
|
||||
}
|
||||
|
||||
/**
|
||||
* 把"持续X秒"中的 X 也包裹绿色高亮(卡片描述后处理)。
|
||||
* Why: 计时模板 {dur} 不在 \x01\x02 高亮标记内,renderLineRich 仅高亮主数值;
|
||||
* 持续时间对药水/计时 buff 同样关键,这里补充高亮,保证视觉一致。
|
||||
*/
|
||||
function highlightDuration(text: string): string {
|
||||
return text.replace(DURATION_PATTERN, `持续<color=${RICH_VALUE_COLOR}>$1</color>秒`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 结构化行 → 富文本串(技能名蓝色、数值绿色)。
|
||||
* buildEquipRich / buildCardDescRich 共用,保证渲染规则唯一。
|
||||
*/
|
||||
function renderLineRich(line: ISkillLine): string {
|
||||
const prefix = line.prefix.replace(SKILL_NAME_PATTERN, `「<color=${RICH_NAME_COLOR}>$1</color>」`);
|
||||
return line.value
|
||||
? `${prefix}<color=${RICH_VALUE_COLOR}>${line.value}</color>${line.suffix}`
|
||||
: `${prefix}${line.suffix}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* 扫描合并后技能的附加概率字段(crt/frz/stun/bck),非零的拼为高亮后缀。
|
||||
* Why: 模板不再硬编码"有概率击晕"等文案,由实际配置驱动,避免描述与数值漂移。
|
||||
* @returns 形如 ",30%击晕,20%冰冻";全为 0 时返回 ""
|
||||
*/
|
||||
function buildChanceSuffix(skill: SkillConfig): string {
|
||||
const items: string[] = [];
|
||||
const push = (val: number | undefined, label: string) => {
|
||||
if (val && val > 0) items.push(`附加<color=${RICH_VALUE_COLOR}>${val}</color>%${label}`);
|
||||
};
|
||||
push(skill.crt, "暴击");
|
||||
push(skill.frz, "冰冻");
|
||||
push(skill.stun, "击晕");
|
||||
push(skill.bck, "击退");
|
||||
return items.length > 0 ? `,${items.join(",")}` : "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 商店卡片描述富文本(SCardComp / ItemListComp 用,BBCode)。
|
||||
*
|
||||
* Why: 卡片 info 为手写文案,与 SkillSet/BuffList 数值易漂移。
|
||||
* 本函数从 CardConfig.skill + overrides 合并后的实时配置生成描述,
|
||||
* 数值随档位(如高级药水 buff_value)自动同步,数值绿色高亮、技能名蓝色。
|
||||
*
|
||||
* 描述规则:
|
||||
* - 药品/技能卡(card.skill 有效)→ 查 SkillDescSet 模板渲染(计时模式取 BuffList 默认值兜底);
|
||||
* 未入表技能回退 SkillSet.info / card.info,整行不高亮。
|
||||
* - 装备卡(card.field 有效)→ 复用 buildEquipRich 逐词条渲染。
|
||||
* - 触发节奏(t_times/t_inv)融入单行描述:定时触发"每M秒释放一次「技能名」,xxx,共N次";即时触发仅显示效果。
|
||||
*
|
||||
* @param card 卡片配置(SCardSet 技能卡 / ICardSet 药品卡 / EquipSet 装备卡)
|
||||
* @returns 多行富文本串;无可描述内容时回退 card.info
|
||||
*/
|
||||
export function buildCardDescRich(card: CardConfig): string {
|
||||
// 装备卡:逐词条渲染驻场光环
|
||||
if (card.field && card.field.length > 0) {
|
||||
return buildEquipRich(card.field);
|
||||
}
|
||||
|
||||
// 药品/技能卡:合并覆写后按 SkillDescSet 模板渲染
|
||||
const base = card.skill ? SkillSet[card.skill] : undefined;
|
||||
if (base) {
|
||||
const skill = mergeSkillParams(base, card.overrides);
|
||||
const line = buildEffectLine("", skill);
|
||||
// 未入表技能回退链:SkillSet.info → card.info
|
||||
if (!line.value && !SkillDescSet[skill.uuid]) {
|
||||
return String(skill.info || card.info || "");
|
||||
}
|
||||
|
||||
// 触发节奏融入描述:定时触发"每M秒释放一次「技能名」,xxx,共N次";即时触发直接描述
|
||||
const tTimes = card.t_times ?? 1;
|
||||
const tInv = card.t_inv ?? 0;
|
||||
const isInstant = card.is_inst || tInv <= 0;
|
||||
// 附加概率后缀(暴击/冰冻/击晕/击退),由实际配置驱动
|
||||
const suffix = buildChanceSuffix(skill);
|
||||
const rich = highlightDuration(renderLineRich(line)) + suffix;
|
||||
|
||||
if (isInstant) {
|
||||
return rich;
|
||||
}
|
||||
|
||||
const rhythm = `每<color=${RICH_VALUE_COLOR}>${tInv}</color>秒释放一次「<color=${RICH_NAME_COLOR}>${skill.name}</color>」`;
|
||||
const times = `,共<color=${RICH_VALUE_COLOR}>${tTimes}</color>次`;
|
||||
return `${rhythm},${rich}${times}`;
|
||||
}
|
||||
|
||||
return card.info || "";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user