refactor(field): 重构驻场光环数据结构,分离元数据与数值

1.  新增FieldEntry类型,将驻场词条的uuid与生效数值分离
2.  重构FieldSkillSet,移除各档位重复配置,仅保留基础元数据
3.  更新所有使用驻场词条的业务代码,适配新的数据结构
4.  修复数值渲染逻辑,使用词条携带的实际数值而非配置固化值
This commit is contained in:
panFD
2026-08-11 22:36:28 +08:00
parent e328892679
commit 450a8b81e5
13 changed files with 196 additions and 228 deletions

View File

@@ -258,14 +258,8 @@ export const TriggerSkillNameSet: Record<string, Record<number, string>> = {
export function getTriggerSkillName(type: SkillTriggerType, s_uuid: number): string {
const group = TriggerSkillNameSet[type];
if (group) {
// 直接命中
const direct = group[s_uuid];
if (direct) return direct;
// 驻场光环 +/++ 档(如 7202/7402回退到基础档命名7002
if (type === SkillTriggerType.Field) {
const base = group[7000 + (s_uuid % 100)];
if (base) return base;
}
}
// 驻场光环 uuid 存于 FieldSkillSet触发技能存于 SkillSet分别兜底
if (type === SkillTriggerType.Field) {
@@ -337,11 +331,20 @@ export interface LvTriggerEntry {
export type TriggerGrouped = Record<number /*s_uuid*/, LvTriggerEntry[]>;
/**
* 驻场光环按等级解锁:运行时取 ≤英雄等级 的最大 lv 档的 uuids。
* 驻场光环词条uuid 指向 FieldSkillSet 底座(类型/图标/名称元数据),
* value 为该词条实际生效数值(由配置处按档位指定,不再随 uuid 分档)。
*/
export interface FieldEntry {
uuid: number;
value: number;
}
/**
* 驻场光环按等级解锁:运行时取 ≤英雄等级 的最大 lv 档的词条列表。
*/
export interface LvFieldEntry {
lv: number;
uuids: number[];
uuids: FieldEntry[];
}
/**
@@ -430,9 +433,9 @@ export const HeroInfo: Record<number, heroInfo> = {
uuid: 5005, name: "战歌法师", path: "hm2", fac: FacSet.HERO, card_lv: 1, lv: 1, type: HType.Long, grow_type: HGrowType.Mage, hp: 143, ap: 40,
skills: { 6013: { uuid: 6013, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Mid3].cd, ccd: 0 } },
field: [
{ lv: 1, uuids: [7002] },
{ lv: 3, uuids: [7202] },
{ lv: 5, uuids: [7402] },
{ lv: 1, uuids: [{ uuid: 7002, value: 0.1 }] },
{ lv: 3, uuids: [{ uuid: 7002, value: 0.2 }] },
{ lv: 5, uuids: [{ uuid: 7002, value: 0.3 }] },
],
info: "",
},
@@ -496,9 +499,9 @@ export const HeroInfo: Record<number, heroInfo> = {
uuid: 5105, name: "风怒先知", path: "hm1", fac: FacSet.HERO, card_lv: 2, lv: 1, type: HType.Long, grow_type: HGrowType.Mage, hp: 287, ap: 80,
skills: { 6013: { uuid: 6013, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Mid2].cd, ccd: 0 } },
field: [
{ lv: 1, uuids: [7006] },
{ lv: 3, uuids: [7206] },
{ lv: 5, uuids: [7406] },
{ lv: 1, uuids: [{ uuid: 7006, value: 0.1 }] },
{ lv: 3, uuids: [{ uuid: 7006, value: 0.2 }] },
{ lv: 5, uuids: [{ uuid: 7006, value: 0.3 }] },
],
info: "",
},
@@ -575,9 +578,9 @@ export const HeroInfo: Record<number, heroInfo> = {
uuid: 5205, name: "精准术士", path: "hm3", fac: FacSet.HERO, card_lv: 3, lv: 1, type: HType.Long, grow_type: HGrowType.Mage, hp: 430, ap: 120,
skills: { 6013: { uuid: 6013, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Mid2].cd, ccd: 0 } },
field: [
{ lv: 1, uuids: [7004] },
{ lv: 3, uuids: [7204] },
{ lv: 5, uuids: [7404] },
{ lv: 1, uuids: [{ uuid: 7004, value: 0.1 }] },
{ lv: 3, uuids: [{ uuid: 7004, value: 0.2 }] },
{ lv: 5, uuids: [{ uuid: 7004, value: 0.3 }] },
],
info: "",
},
@@ -651,9 +654,9 @@ export const HeroInfo: Record<number, heroInfo> = {
uuid: 5305, name: "领域贤者", path: "hm2", fac: FacSet.HERO, card_lv: 4, lv: 1, type: HType.Long, grow_type: HGrowType.Mage, hp: 573, ap: 160,
skills: { 6013: { uuid: 6013, lv: 1, cd: AtkSpeedSet[AtkSpeedLv.Mid2].cd, ccd: 0 } },
field: [
{ lv: 1, uuids: [7005, 7006] },
{ lv: 3, uuids: [7205, 7206] },
{ lv: 5, uuids: [7405, 7406] },
{ lv: 1, uuids: [{ uuid: 7005, value: 0.2 }, { uuid: 7006, value: 0.1 }] },
{ lv: 3, uuids: [{ uuid: 7005, value: 0.4 }, { uuid: 7006, value: 0.2 }] },
{ lv: 5, uuids: [{ uuid: 7005, value: 0.6 }, { uuid: 7006, value: 0.3 }] },
],
info: "",
},
@@ -690,9 +693,9 @@ export const HeroInfo: Record<number, heroInfo> = {
],
},
field: [
{ lv: 1, uuids: [7006] },
{ lv: 3, uuids: [7206] },
{ lv: 5, uuids: [7406] },
{ lv: 1, uuids: [{ uuid: 7006, value: 0.1 }] },
{ lv: 3, uuids: [{ uuid: 7006, value: 0.2 }] },
{ lv: 5, uuids: [{ uuid: 7006, value: 0.3 }] },
],
info: "",
},
@@ -754,9 +757,9 @@ export const HeroInfo: Record<number, heroInfo> = {
],
},
field: [
{ lv: 1, uuids: [7007] },
{ lv: 3, uuids: [7207] },
{ lv: 5, uuids: [7407] },
{ lv: 1, uuids: [{ uuid: 7007, value: 0.1 }] },
{ lv: 3, uuids: [{ uuid: 7007, value: 0.2 }] },
{ lv: 5, uuids: [{ uuid: 7007, value: 0.3 }] },
],
info: "",
},
@@ -898,8 +901,8 @@ export function resolveTriggerByLv(grouped: TriggerGrouped | undefined, lv: numb
return result;
}
/** 解析驻场光环在目标等级下的有效 uuid 列表(取 ≤lv 的最大档) */
export function resolveFieldByLv(field: LvFieldEntry[] | undefined, lv: number): number[] {
/** 解析驻场光环在目标等级下的有效词条列表(取 ≤lv 的最大档) */
export function resolveFieldByLv(field: LvFieldEntry[] | undefined, lv: number): FieldEntry[] {
if (!field || field.length === 0) return [];
let pick: LvFieldEntry | undefined;
for (const e of field) {
@@ -1184,35 +1187,35 @@ function calcTriggerPowerDetailed(
return { total, items };
}
/** 计算驻场光环技能在时间窗内的总价值 */
function calcFieldSkillValue(field: FieldSkillConfig, hpEff: number, apEff: number, cd: number, scopeMul: number, seconds: number): number {
/** 计算驻场光环技能在时间窗内的总价值value 由词条携带fs 提供类型元数据) */
function calcFieldSkillValue(fs: FieldSkillConfig, value: number, hpEff: number, apEff: number, cd: number, scopeMul: number, seconds: number): number {
const weights = HERO_POWER_WEIGHTS;
const dps = apEff / cd;
switch (field.type) {
switch (fs.type) {
case FieldSkillType.HeroAtk:
return field.value * dps * scopeMul * weights.W_DPS_PER_SEC * seconds;
return value * dps * scopeMul * weights.W_DPS_PER_SEC * seconds;
case FieldSkillType.HeroHp:
return field.value * hpEff * scopeMul * weights.W_HP;
return value * hpEff * scopeMul * weights.W_HP;
case FieldSkillType.HeroSpeed:
return field.value * dps * scopeMul * weights.W_DPS_PER_SEC * seconds;
return value * dps * scopeMul * weights.W_DPS_PER_SEC * seconds;
case FieldSkillType.HeroCrit:
return field.value * dps * scopeMul * 0.5 * weights.W_DPS_PER_SEC * seconds;
return value * dps * scopeMul * 0.5 * weights.W_DPS_PER_SEC * seconds;
case FieldSkillType.HeroCritDamage:
return field.value * dps * scopeMul * 0.05 * weights.W_DPS_PER_SEC * seconds;
return value * dps * scopeMul * 0.05 * weights.W_DPS_PER_SEC * seconds;
case FieldSkillType.HeroStun:
case FieldSkillType.HeroWindFury:
case FieldSkillType.HeroPuncture:
case FieldSkillType.HeroPunctureDmg:
return field.value * scopeMul * weights.W_control * 100;
return value * scopeMul * weights.W_control * 100;
default:
return field.value * scopeMul * weights.W_control * 10;
return value * scopeMul * weights.W_control * 10;
}
}
/** 计算驻场光环的详细价值 */
function calcFieldPowerDetailed(fieldUuids: number[] | undefined, hero: heroInfo, targetLv: number, seconds: number): { total: number, items: FieldSkillEval[] } {
if (!fieldUuids || fieldUuids.length === 0) return { total: 0, items: [] };
function calcFieldPowerDetailed(entries: FieldEntry[] | undefined, hero: heroInfo, targetLv: number, seconds: number): { total: number, items: FieldSkillEval[] } {
if (!entries || entries.length === 0) return { total: 0, items: [] };
const weights = HERO_POWER_WEIGHTS;
const { hp: hpEff, ap: apEff } = getEffectiveStats(hero, targetLv);
const cd = getAttackCd(hero);
@@ -1220,12 +1223,12 @@ function calcFieldPowerDetailed(fieldUuids: number[] | undefined, hero: heroInfo
let total = 0;
const items: FieldSkillEval[] = [];
for (const uuid of fieldUuids) {
const field = FieldSkillSet[uuid];
if (!field) continue;
const value = calcFieldSkillValue(field, hpEff, apEff, cd, scopeMul, seconds) * weights.W_field_alive;
for (const entry of entries) {
const fs = FieldSkillSet[entry.uuid];
if (!fs) continue;
const value = calcFieldSkillValue(fs, entry.value, hpEff, apEff, cd, scopeMul, seconds) * weights.W_field_alive;
total += value;
items.push({ uuid, name: field.name, value });
items.push({ uuid: entry.uuid, name: fs.name, value });
}
return { total, items };
}
@@ -1269,8 +1272,8 @@ export function calcHeroPowerDetailed(hero: heroInfo, targetLv: number = 1, seco
const fstart = hero.fstart ? calcTriggerPowerDetailed(resolveTriggerByLv(hero.fstart, targetLv), hero, targetLv, SkillTriggerType.FStart, seconds) : { total: 0, items: [] as TriggerSkillEval[] };
const fend = hero.fend ? calcTriggerPowerDetailed(resolveTriggerByLv(hero.fend, targetLv), hero, targetLv, SkillTriggerType.FEnd, seconds) : { total: 0, items: [] as TriggerSkillEval[] };
const dead = hero.dead ? calcTriggerPowerDetailed(resolveTriggerByLv(hero.dead, targetLv), hero, targetLv, SkillTriggerType.Dead, seconds) : { total: 0, items: [] as TriggerSkillEval[] };
const fieldUuids = resolveFieldByLv(hero.field, targetLv);
const field = fieldUuids.length > 0 ? calcFieldPowerDetailed(fieldUuids, hero, targetLv, seconds) : { total: 0, items: [] as FieldSkillEval[] };
const fieldEntries = resolveFieldByLv(hero.field, targetLv);
const field = fieldEntries.length > 0 ? calcFieldPowerDetailed(fieldEntries, hero, targetLv, seconds) : { total: 0, items: [] as FieldSkillEval[] };
let reviveValue = 0;
const revive = resolveReviveByLv(hero.revive, targetLv);