Release Healer Man 0.1.59

This commit is contained in:
phenom committed 2026-09-27 10:16:42 -04:00
1 parent 11934a3979
commit ab1434a3b8
44 files changed
+1242 -103

No files matched your search

+40 -10
View File
@@ -4,7 +4,6 @@ import type {
TalentAllocationFailure,
TalentAllocationResult,
} from "./talentCatalog";
import generated from "./generated/talentRuntimeCatalog.json";
export type RuntimeTalentRanks = Readonly<Record<string, number>>;
@@ -42,15 +41,41 @@ interface RuntimeTalentSnapshot {
readonly nodes: readonly RuntimeTalentNode[];
}
const snapshot = generated as unknown as RuntimeTalentSnapshot;
export const RUNTIME_TALENT_TREES: readonly RuntimeTalentTree[] = snapshot.trees;
export const RUNTIME_TALENT_NODES: readonly RuntimeTalentNode[] = snapshot.nodes;
const treeById = Object.freeze(Object.fromEntries(snapshot.trees.map((tree) => [tree.id, tree]))) as Readonly<Record<string, RuntimeTalentTree>>;
const nodeById = Object.freeze(Object.fromEntries(snapshot.nodes.map((node) => [node.id, node]))) as Readonly<Record<string, RuntimeTalentNode>>;
const nodesByTree = Object.freeze(Object.fromEntries(snapshot.trees.map((tree) => [
tree.id,
snapshot.nodes.filter((node) => node.treeId === tree.id).sort((left, right) => left.row - right.row || left.index - right.index),
]))) as Readonly<Record<string, readonly RuntimeTalentNode[]>>;
let snapshot: RuntimeTalentSnapshot = {
schemaVersion: 1,
maximumCoaLevel: 80,
coaBudgetsByClass: {} as RuntimeTalentSnapshot["coaBudgetsByClass"],
trees: [],
nodes: [],
};
export let RUNTIME_TALENT_TREES: readonly RuntimeTalentTree[] = snapshot.trees;
export let RUNTIME_TALENT_NODES: readonly RuntimeTalentNode[] = snapshot.nodes;
let treeById: Readonly<Record<string, RuntimeTalentTree>> = {};
let nodeById: Readonly<Record<string, RuntimeTalentNode>> = {};
let nodesByTree: Readonly<Record<string, readonly RuntimeTalentNode[]>> = {};
let catalogLoad: Promise<void> | null = null;
/** The authored WoW/CoA talent snapshot is unnecessary for a RoM-only session. */
export function preloadRuntimeTalentCatalog(): Promise<void> {
if (catalogLoad) return catalogLoad;
catalogLoad = import("./generated/talentRuntimeCatalog.json").then(({ default: generated }) => {
const loaded = generated as unknown as RuntimeTalentSnapshot;
if (loaded.schemaVersion !== 1) throw new Error("Unsupported runtime talent catalog.");
snapshot = loaded;
RUNTIME_TALENT_TREES = snapshot.trees;
RUNTIME_TALENT_NODES = snapshot.nodes;
treeById = Object.freeze(Object.fromEntries(snapshot.trees.map((tree) => [tree.id, tree])));
nodeById = Object.freeze(Object.fromEntries(snapshot.nodes.map((node) => [node.id, node])));
nodesByTree = Object.freeze(Object.fromEntries(snapshot.trees.map((tree) => [
tree.id,
snapshot.nodes.filter((node) => node.treeId === tree.id).sort((left, right) => left.row - right.row || left.index - right.index),
])));
}).catch((error: unknown) => {
catalogLoad = null;
throw error;
});
return catalogLoad;
}
function isCoaClassId(classId: ClassId): classId is CoaClassId {
return CLASSES.find((definition) => definition.id === classId)?.mode === "conquest";
@@ -104,6 +129,7 @@ export function runtimeTalentPointsForLevel(level: number): number {
function coaBudget(classId: CoaClassId, level: number) {
const definition = snapshot.coaBudgetsByClass[classId];
if (!definition) throw new Error(`Talent catalog for ${classId} was used before it was loaded.`);
const normalizedLevel = Math.min(snapshot.maximumCoaLevel, Math.max(1, clampPlayerLevel(level)));
const grantedPoints = Math.max(0, normalizedLevel - 9);
return {
@@ -285,3 +311,7 @@ export function runtimeResetTalentRanks(ranks: RuntimeTalentRanks = {}, classId?
return !node || treeById[node.treeId]?.classId !== classId;
}));
}
if (import.meta.env.MODE === "test" || import.meta.env.MODE === "shelved") {
await preloadRuntimeTalentCatalog();
}