Release Healer Man 0.1.7

This commit is contained in:
phenom committed 2026-08-22 15:53:43 -04:00
1 parent b12fb84859
commit eca6b5db9b
99 files changed
+1931 -150

No files matched your search

+93
View File
@@ -0,0 +1,93 @@
import type { ClassId } from "../app/characterCatalog";
export interface TalentUiTree {
readonly id: string;
readonly classId: ClassId;
readonly name: string;
readonly icon: string;
readonly background: string;
readonly description: string;
readonly system?: "classic" | "coa";
}
export interface TalentUiNode {
readonly id: string;
readonly treeId: string;
readonly index: number;
readonly prerequisiteId: string | null;
readonly prerequisiteRank: number | null;
readonly prerequisites: readonly {
readonly talentId: string;
readonly requiredRank: number;
}[];
readonly column: number;
readonly row: number;
readonly icon: string;
readonly maxRank: number;
readonly name: string;
readonly description: string;
readonly rankDescriptions: readonly string[];
readonly system?: "classic" | "coa";
readonly entryType?: "Ability" | "Talent";
readonly abilityEssenceCost?: number;
readonly talentEssenceCost?: number;
readonly requiredClassPoints?: number;
readonly requiredSpecPoints?: number;
readonly requiredLevel?: number;
readonly isPassive?: boolean;
}
export interface TalentUiCatalog {
readonly schemaVersion: 1;
readonly classId: ClassId;
readonly trees: readonly TalentUiTree[];
readonly nodes: readonly TalentUiNode[];
}
interface TalentUiCatalogModule {
readonly default: TalentUiCatalog;
}
const shardLoaders = import.meta.glob<TalentUiCatalogModule>("./generated/talentUi/*.json");
const loadCache = new Map<ClassId, Promise<TalentUiCatalog>>();
export function loadTalentUiCatalog(classId: ClassId): Promise<TalentUiCatalog> {
const cached = loadCache.get(classId);
if (cached) return cached;
const key = `./generated/talentUi/${classId}.json`;
const loader = shardLoaders[key];
if (!loader) return Promise.reject(new Error(`No talent UI catalog exists for ${classId}.`));
const pending = loader().then((module) => {
if (module.default.schemaVersion !== 1 || module.default.classId !== classId) {
throw new Error(`Talent UI catalog ${classId} has incompatible metadata.`);
}
return module.default;
}).catch((error: unknown) => {
loadCache.delete(classId);
throw error;
});
loadCache.set(classId, pending);
return pending;
}
export function talentUiDescriptionForRank(node: TalentUiNode, rank: number): string {
const normalizedRank = Math.min(
node.maxRank,
Math.max(1, Math.trunc(Number.isFinite(rank) ? rank : 1)),
);
return node.rankDescriptions[normalizedRank - 1] ?? node.description;
}
export function talentUiTreeById(catalog: TalentUiCatalog, treeId: string): TalentUiTree | null {
return catalog.trees.find((tree) => tree.id === treeId) ?? null;
}
export function talentUiNodeById(catalog: TalentUiCatalog, nodeId: string): TalentUiNode | null {
return catalog.nodes.find((node) => node.id === nodeId) ?? null;
}
export function talentUiNodesForTree(catalog: TalentUiCatalog, treeId: string): readonly TalentUiNode[] {
return catalog.nodes
.filter((node) => node.treeId === treeId)
.sort((left, right) => left.row - right.row || left.index - right.index);
}