forked from phenom/healer-man
39 lines
1.3 KiB
TypeScript
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);
|
|
}
|