You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
AdLike2048/assets/script/battle/skill/SkillEntryParse.ts

89 lines
3.4 KiB

/** 词条字符串解析(无业务依赖,供 Loadout / Applier 共用,避免循环引用) */
/** 解析词条.base_attr:「类型,值」或「类型,值;类型,值」 */
export function parseEntryBaseAttr(raw: string): Array<{ type: number; value: number }> {
if (!raw) return [];
const out: Array<{ type: number; value: number }> = [];
for (const seg of raw.split(';')) {
const part = seg.trim();
if (!part) continue;
const [typeStr, valueStr] = part.split(',');
const type = Number(typeStr);
const value = Number(valueStr);
if (!Number.isFinite(type) || !Number.isFinite(value)) continue;
out.push({ type, value });
}
return out;
}
/** 解析 base_para:「代号,值[,值...]」多段用 ; */
export function parseEntryBasePara(raw: string): Array<{ code: number; values: number[] }> {
if (!raw) return [];
const out: Array<{ code: number; values: number[] }> = [];
for (const seg of raw.split(';')) {
const part = seg.trim();
if (!part) continue;
const nums = part.split(',').map(Number);
if (!nums.length || !Number.isFinite(nums[0])) continue;
out.push({ code: nums[0], values: nums.slice(1) });
}
return out;
}
/**
* 解析 Skill.skill_change:修改 base_atk.skill 逗号分隔参数(1-based 下标)。
*
* 格式:`第N个参数,增加类型,增加数值`;多段用 `;` 分隔。
* 只修改已有下标上的数值,不追加新参数。
*
* 增加类型(op,配表注释):
* - 1 增加数值:cur = cur + value
* - 2 万分比增加:cur = cur × (1 + value/10000)
* - 3 减少数值:cur = cur - value
* - 4 万分比减少:cur = cur / (1 + value/10000)
*
* 同参数位、同 op 的多条修改先汇总 value,再按 1→2→3→4 顺序各算一次(每次基于上一步的 cur,非替换回基线)。
*/
export function parseSkillChange(raw: string): Array<{ index: number; op: number; value: number }> {
if (!raw) return [];
const out: Array<{ index: number; op: number; value: number }> = [];
for (const seg of raw.split(';')) {
const part = seg.trim();
if (!part) continue;
const [i, op, v] = part.split(',').map(Number);
if (!Number.isFinite(i) || !Number.isFinite(op) || !Number.isFinite(v)) continue;
out.push({ index: i, op, value: v });
}
return out;
}
/** 在 base_atk.skill 基线 parts 上应用 skill_change(不扩展数组长度) */
export function applySkillChangesToParts(
baseParts: readonly number[],
changes: ReadonlyArray<{ index: number; op: number; value: number }>,
): number[] {
const parts = [...baseParts];
if (!changes.length) return parts;
const byIndex = new Map<number, Map<number, number>>();
for (const ch of changes) {
let ops = byIndex.get(ch.index);
if (!ops) {
ops = new Map();
byIndex.set(ch.index, ops);
}
ops.set(ch.op, (ops.get(ch.op) ?? 0) + ch.value);
}
for (const [index, ops] of byIndex) {
const i = index - 1;
if (i < 0 || i >= parts.length) continue;
let cur = baseParts[i];
if (ops.has(1)) cur += ops.get(1)!;
if (ops.has(2)) cur *= 1 + ops.get(2)! / 10000;
if (ops.has(3)) cur -= ops.get(3)!;
if (ops.has(4)) cur /= 1 + ops.get(4)! / 10000;
parts[i] = cur;
}
return parts;
}