Files
healer-man/scripts/generate-combat-runtime-catalogs.ts

89 lines
3.1 KiB
TypeScript

import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
import { dirname, resolve } from "node:path";
import { CLASSES, type CoaClassId } from "../src/app/characterCatalog";
import {
COA_ABILITIES_BY_CLASS,
COA_CLASS_RESOURCES,
COA_TRIGGERED_ABILITIES_BY_SPELL_ID,
} from "../src/game/coaAbilityCatalog";
import {
COA_LIVE_SOURCE,
coaClassDefinition,
} from "../src/game/coaLiveCatalog";
import {
TALENT_NODES,
TALENT_TREES,
} from "../src/game/talentCatalog";
function writeJson(path: string, value: unknown): void {
const outputPath = resolve(path);
mkdirSync(dirname(outputPath), { recursive: true });
writeFileSync(outputPath, `${JSON.stringify(value)}\n`, "utf8");
console.log(`Wrote ${outputPath}`);
}
writeJson("src/game/generated/coaAbilityRuntimeCatalog.json", {
schemaVersion: 1,
abilitiesByClass: COA_ABILITIES_BY_CLASS,
resourcesByClass: COA_CLASS_RESOURCES,
triggeredAbilitiesBySpellId: COA_TRIGGERED_ABILITIES_BY_SPELL_ID,
});
const coaBudgetsByClass = Object.fromEntries(CLASSES
.filter((definition) => definition.mode === "conquest")
.map((definition) => {
const classId = definition.id as CoaClassId;
const live = coaClassDefinition(classId);
return [classId, {
maximumAbility: live.maxAbilityEssence,
maximumTalent: live.maxTalentEssence,
}];
}));
const talentSnapshot = {
schemaVersion: 1,
maximumCoaLevel: COA_LIVE_SOURCE.maximumLevel,
coaBudgetsByClass,
trees: TALENT_TREES.map(({ id, classId }) => ({ id, classId })),
nodes: TALENT_NODES.map((node) => ({
id: node.id,
treeId: node.treeId,
index: node.index,
row: node.row,
maxRank: node.maxRank,
name: node.name,
prerequisites: node.prerequisites,
rankDescriptions: node.rankDescriptions,
system: node.system,
abilityEssenceCost: node.abilityEssenceCost,
talentEssenceCost: node.talentEssenceCost,
requiredClassPoints: node.requiredClassPoints,
requiredSpecPoints: node.requiredSpecPoints,
requiredLevel: node.requiredLevel,
isPassive: node.isPassive,
})),
};
if (process.argv.includes("--coa-only")) {
const previous = JSON.parse(readFileSync("src/game/generated/talentRuntimeCatalog.json", "utf8"));
const coaClasses = new Set(CLASSES.filter((definition) => definition.mode === "conquest").map((definition) => definition.id));
const coaTrees = new Set(talentSnapshot.trees.filter((tree) => coaClasses.has(tree.classId)).map((tree) => tree.id));
function replaceCoa<T>(oldRecords: T[], newRecords: T[], isCoa: (record: T) => boolean): T[] {
const result: T[] = [];
let inserted = false;
for (const record of oldRecords) {
if (!isCoa(record)) result.push(record);
else if (!inserted) {
result.push(...newRecords.filter(isCoa));
inserted = true;
}
}
if (!inserted) result.push(...newRecords.filter(isCoa));
return result;
}
talentSnapshot.trees = replaceCoa(previous.trees, talentSnapshot.trees, (tree) => coaClasses.has(tree.classId));
talentSnapshot.nodes = replaceCoa(previous.nodes, talentSnapshot.nodes, (node) => coaTrees.has(node.treeId));
}
writeJson("src/game/generated/talentRuntimeCatalog.json", talentSnapshot);