Files
healer-man/src/game/partyTalentRuntime.ts
T
2026-08-22 15:53:43 -04:00

39 lines
1.3 KiB
TypeScript

import type { ClassId } from "../app/characterCatalog";
import generated from "./generated/partyTalentRuntimePlans.json";
type TalentRanks = Readonly<Record<string, number>>;
interface PartyTalentRuntimeSnapshot {
readonly schemaVersion: 1;
readonly plans: Readonly<Record<string, readonly string[]>>;
}
const snapshot = generated as PartyTalentRuntimeSnapshot;
function planKey(classId: ClassId, specialization: string): string {
return `${classId}:${specialization}`;
}
export function runtimePartyTalentPlan(
classId: ClassId,
specialization: string,
): readonly string[] {
const plan = snapshot.plans[planKey(classId, specialization)];
if (!plan) throw new Error(`Unsupported party specialization: ${classId}:${specialization}`);
return plan;
}
/** Runtime-only projection of the catalog-validated 71-point party plans. */
export function runtimePartyTalentRanksForLevel(
classId: ClassId,
specialization: string,
level: number,
): TalentRanks {
const plan = runtimePartyTalentPlan(classId, specialization);
const safeLevel = Number.isFinite(level) ? Math.max(1, Math.min(80, Math.trunc(level))) : 1;
const points = Math.max(0, safeLevel - 9);
const ranks: Record<string, number> = {};
for (const nodeId of plan.slice(0, points)) ranks[nodeId] = (ranks[nodeId] ?? 0) + 1;
return Object.freeze(ranks);
}