refactor: 重构复活机制,将复活逻辑整合到dead触发组

1.  新增SkillOverrides的revive_hp和revive_count配置项,替代原独立复活字段
2.  移除所有revive相关的旧配置、解析函数和UI展示逻辑
3.  调整战斗逻辑,从dead触发组的overrides中读取复活配置
4.  更新文档说明,统一复活机制的配置方式
5.  清理冗余的导入和类型定义
This commit is contained in:
panFD
2026-09-03 22:28:38 +08:00
parent 87f771edd1
commit b0038e74c8
12 changed files with 120 additions and 131 deletions

View File

@@ -25,8 +25,8 @@
*/
import {
HeroInfo, heroInfo, SkillTriggerType, SkillTriggerName, HSkillInfo, LvTriggerEntry,
TriggerGrouped, resolveSkillOverrides, resolveTriggerByLv, resolveFieldByLv, resolveReviveByLv,
getGroupedTriggerName, getFieldSkillName, getReviveSkillName,
TriggerGrouped, resolveSkillOverrides, resolveTriggerByLv, resolveFieldByLv,
getGroupedTriggerName, getFieldSkillName,
} from "./config/heroSet";
import { SkillSet, mergeSkillParams, SkillConfig, SkillKind, TGroup, FieldSkillSet } from "./config/SkillSet";
import { BuffList } from "./config/BuffSet";
@@ -219,12 +219,16 @@ export function buildHeroSkillDesc(heroUuid: number, showName: boolean = true, s
lines.push(`${nameSeg(getFieldSkillName(hero, entry.uuid))}${desc.verb}${valueRich(val)}`);
}
// ---- 复活(revive):次数复刻战斗公式 r_num + floor((lv-1)*upr) ----
const revive = resolveReviveByLv(hero.revive, lv);
if (revive) {
const count = revive.r_num + Math.floor((lv - 1) * revive.upr);
const hpPct = SkillSet[revive.s_uuid]?.ap ?? 0;
lines.push(`${nameSeg(getReviveSkillName(hero, revive.s_uuid))}每回合可复活${valueRich(count)}次, 死亡后以${valueRich(`${Math.round(hpPct)}%`)}生命原地重生`);
// ---- 复活(已纳入 dead 触发组):从 dead 配置提取 revive_hp / revive_count ----
for (const item of resolveTriggerByLv(hero.dead, lv)) {
const reviveHp = item.overrides?.revive_hp;
const reviveCount = item.overrides?.revive_count ?? 0;
if (reviveHp === undefined || reviveCount <= 0) continue;
const base = SkillSet[item.s_uuid];
if (!base) continue;
const skill = mergeSkillParams(base, item.overrides);
const text = `每回合可复活${valueRich(reviveCount)}次, 死亡后以${valueRich(`${Math.round(reviveHp)}%`)}生命原地重生`;
lines.push(`${nameSeg(getGroupedTriggerName(hero.dead!, item.s_uuid))}${SkillTriggerName[SkillTriggerType.Dead]}, ${text}`);
}
return lines.join("\n");
@@ -392,32 +396,40 @@ function collectFieldTierLines(hero: heroInfo, fieldUuid: number): HeroSkillTier
}
/**
* 收集复活技能分档行(hero.revive 各英雄等级档,无 s_lv 概念,按档位序号编号)。
* slv1 给完整效果(复活次数 + 重生血量);slv2+ 给复活次数变化。
* 收集复活技能分档行(已纳入 dead 触发组,从 dead[skillUuid] 提取 revive_hp / revive_count)。
* slv1 给完整效果(复活次数 + 重生血量);slv2+ 给复活次数/血量变化。
* 档位配置了 desc 时直接采用。
*/
function collectReviveTierLines(hero: heroInfo, sUuid: number): HeroSkillTierLine[] {
const matched = (hero.revive ?? [])
.filter(e => e.s_uuid === sUuid)
const entries = hero.dead?.[sUuid];
if (!entries?.length) return [];
// 筛选带复活参数的档位,按 lv 升序
const matched = entries
.filter(e => e.overrides?.revive_hp !== undefined && (e.overrides?.revive_count ?? 0) > 0)
.sort((a, b) => a.lv - b.lv);
if (matched.length === 0) return [];
const lines: HeroSkillTierLine[] = [];
let prevCount: number | undefined;
let prevHp: number | undefined;
matched.forEach((e, i) => {
// 复活次数复刻战斗公式:r_num + floor((英雄等级-1)*upr)
const count = e.r_num + Math.floor((e.lv - 1) * e.upr);
const hpPct = Math.round(SkillSet[e.s_uuid]?.ap ?? 0);
const count = e.overrides!.revive_count!;
const hpPct = Math.round(e.overrides!.revive_hp!);
if (e.desc) {
lines.push({ sLv: i + 1, heroLv: e.lv, text: e.desc });
} else if (i === 0) {
lines.push({ sLv: 1, heroLv: e.lv, text: `每回合可复活${valueRich(count)}次, 死亡后以${valueRich(`${hpPct}%`)}生命原地重生` });
} else if (prevCount !== undefined && count !== prevCount) {
lines.push({ sLv: i + 1, heroLv: e.lv, text: `复活次数${valueRich(prevCount)}次提升至${valueRich(count)}次` });
} else if (prevCount !== undefined && (count !== prevCount || hpPct !== prevHp)) {
const parts: string[] = [];
if (count !== prevCount) parts.push(`复活次数${valueRich(prevCount)}次提升至${valueRich(count)}次`);
if (hpPct !== prevHp) parts.push(`回血比例${valueRich(prevHp)}%提升至${valueRich(hpPct)}%`);
lines.push({ sLv: i + 1, heroLv: e.lv, text: parts.join(",") });
} else {
lines.push({ sLv: i + 1, heroLv: e.lv, text: "无变化" });
}
prevCount = count;
prevHp = hpPct;
});
return lines;
}
@@ -487,7 +499,7 @@ function buildTierLines(tiers: ISkillTierInfo[], triggerLabel: string): HeroSkil
* 1. hero.skills[skillUuid] —— 普攻/大招
* 2. 5 类触发技能组 —— call/dead/fstart/atking/atked
* 3. hero.field —— 驻场光环词条(FieldSkillSet uuid)
* 4. hero.revive —— 复活技能(SkillSet uuid)
* 4. hero.dead 中的复活技能 —— 已纳入 dead 触发组(revive_hp / revive_count)
* 均未命中返回 []。
*
* Why: 同一底座技能可能被多个英雄以不同 overrides 引用,必须以英雄语境取档;
@@ -503,9 +515,8 @@ export function buildHeroSkillTierLines(heroUuid: number, skillUuid: number, slo
const hero = HeroInfo[heroUuid];
if (!hero) return [];
// 槽位指定:光环/复活结构特殊直接生成行;触发组走统一档位结构
// 槽位指定:光环结构特殊直接生成行;触发组走统一档位结构(复活已纳入 dead)
if (slot === SkillTriggerType.Field) return collectFieldTierLines(hero, skillUuid);
if (slot === SkillTriggerType.Revive) return collectReviveTierLines(hero, skillUuid);
if (slot !== undefined) {
const hit = collectTriggerTiers(hero, slot, skillUuid);
return hit ? buildTierLines(hit.tiers, hit.label) : [];
@@ -530,12 +541,11 @@ export function buildHeroSkillTierLines(heroUuid: number, skillUuid: number, slo
}
}
// 光环/复活路径(无 ISkillTierInfo 中间结构,直接生成 HeroSkillTierLine)
// 光环路径(无 ISkillTierInfo 中间结构,直接生成 HeroSkillTierLine)
if (tiers.length === 0) {
const fieldLines = collectFieldTierLines(hero, skillUuid);
if (fieldLines.length > 0) return fieldLines;
const reviveLines = collectReviveTierLines(hero, skillUuid);
if (reviveLines.length > 0) return reviveLines;
// 复活已纳入 dead 触发组,通过 dead 路径处理
return [];
}
@@ -580,9 +590,9 @@ function resolveTriggerSkillName(hero: heroInfo, skillUuid: number): string {
if (hero.field?.some(e => e.uuids.some(u => u.uuid === skillUuid))) {
return getFieldSkillName(hero, skillUuid);
}
// 复活技能:名称取英雄语境(LvReviveEntry.name 优先,回退固定称谓)
if (hero.revive?.some(e => e.s_uuid === skillUuid)) {
return getReviveSkillName(hero, skillUuid);
// 复活技能:名称取英雄语境(dead 组名,回退底座名)
if (hero.dead?.[skillUuid]?.length) {
return getGroupedTriggerName(hero.dead, skillUuid);
}
return SkillSet[skillUuid]?.name ?? "";
}