Files
healer-man/src/game/azerothCoreReference.test.ts
T
2026-09-17 09:13:15 -04:00

153 lines
5.3 KiB
TypeScript

import { describe, expect, it } from "vitest";
import referenceData from "./generated/azerothCoreReference.json";
import sourceLock from "./generated/azerothCoreSourceLock.json";
import worldAiData from "./generated/azerothCoreWorldAi.json";
import baseStatsData from "./generated/wow335BaseStats.json";
import {
creatureRuntimeBaseStats,
creatureTemplateReference,
standardWowDungeonCreatureHealth,
} from "./azerothCoreReference";
interface PlayerClassRow {
readonly attributes: readonly number[];
readonly resources: readonly number[];
}
interface ReferenceShape {
readonly source: {
readonly branch: string;
readonly commit: string;
readonly dirty: boolean;
};
readonly player: {
readonly classStats: Readonly<Record<string, PlayerClassRow>>;
readonly raceOffsets: Readonly<Record<string, readonly number[]>>;
readonly attributes: Readonly<Record<string, readonly (readonly number[] | null)[]>>;
readonly resources: Readonly<Record<string, readonly (readonly number[] | null)[]>>;
readonly xpForLevel: readonly number[];
};
}
const REFERENCE = referenceData as unknown as ReferenceShape;
describe("pinned AzerothCore reference", () => {
it("locks the pinned AzerothCore snapshot and every consumed SQL file by SHA-256", () => {
expect(REFERENCE.source).toMatchObject({
branch: "master",
commit: "4d9d1d4b5723e819c5c390f6ca1177283dbfb8e3",
dirty: false,
});
expect(sourceLock.files.length).toBeGreaterThanOrEqual(18);
expect(sourceLock.source.dirtyStateWarning).toBeNull();
expect(sourceLock.schemas).toEqual({
normalizedReference: 2,
normalizedWorldAi: 1,
sourceLock: 1,
dungeonSnapshot: 2,
playerBaseStats: 2,
});
for (const file of sourceLock.files) {
expect(file.file).not.toMatch(/[\\/]/);
expect(file.sha256).toMatch(/^[a-f0-9]{64}$/);
expect(file.byteLength).toBeGreaterThan(0);
}
});
it("normalizes creature spells, SmartAI, and encounter metadata for offline builds", () => {
expect(worldAiData.schemaVersion).toBe(1);
expect(worldAiData.smartScriptsByEntry["598"]).toContainEqual(expect.objectContaining({
action_param1: 6016,
action_type: 11,
event_type: 0,
target_type: 2,
}));
expect(worldAiData.creatureSpellsByEntry["598"]).toContainEqual({
index: 0,
spellId: 6016,
verifiedBuild: 12340,
});
expect(worldAiData.encountersByMap["43"].map((encounter) => encounter.name)).toEqual(
expect.arrayContaining([
"Lady Anacondra",
"Lord Serpentis",
"Mutanus the Devourer",
]),
);
});
it("verifies every valid race/class/level primary-stat row and resource row", () => {
expect(baseStatsData.attributes).toEqual(REFERENCE.player.attributes);
expect(baseStatsData.resources).toEqual(REFERENCE.player.resources);
for (const [raceClass, rows] of Object.entries(REFERENCE.player.attributes)) {
const [race, characterClass] = raceClass.split(":");
const offsets = REFERENCE.player.raceOffsets[race];
expect(offsets, raceClass).toHaveLength(5);
expect(rows, raceClass).toHaveLength(80);
rows.forEach((attributes, index) => {
const classRow = REFERENCE.player.classStats[`${characterClass}:${index + 1}`];
if (!classRow) {
expect(attributes, `${raceClass}:${index + 1}`).toBeNull();
return;
}
expect(attributes, `${raceClass}:${index + 1}`).toEqual(
classRow.attributes.map((value, attributeIndex) => value + offsets[attributeIndex]),
);
expect(
REFERENCE.player.resources[characterClass]?.[index],
`${characterClass}:${index + 1}`,
).toEqual(classRow.resources);
});
}
});
it("ships every exact level threshold through level 79", () => {
expect(REFERENCE.player.xpForLevel).toHaveLength(79);
expect(REFERENCE.player.xpForLevel.slice(0, 5)).toEqual([400, 900, 1_400, 2_100, 2_800]);
expect(REFERENCE.player.xpForLevel[78]).toBe(1_670_800);
expect(REFERENCE.player.xpForLevel.every((value) => Number.isInteger(value) && value > 0))
.toBe(true);
});
it("derives representative normal, elite, and boss stats at multiple levels", () => {
expect(standardWowDungeonCreatureHealth(5)).toBe(306);
expect(creatureRuntimeBaseStats(385, 5)).toMatchObject({
health: 102,
armor: 111,
attackPower: 18,
averageAttackDamage: 28,
});
expect(creatureRuntimeBaseStats(385, 20)).toMatchObject({
health: 484,
armor: 836,
attackPower: 70,
averageAttackDamage: 157,
});
expect(creatureRuntimeBaseStats(1720, 25)).toMatchObject({
health: 2_097,
armor: 1_008,
averageAttackDamage: 71,
});
expect(creatureRuntimeBaseStats(1720, 40)).toMatchObject({
health: 4_572,
armor: 1_938,
averageAttackDamage: 111,
});
expect(creatureRuntimeBaseStats(10162, 60)).toMatchObject({
health: 280_830,
mana: 243_400,
armor: 3_748,
averageAttackDamage: 394,
});
expect(creatureRuntimeBaseStats(10162, 63)).toMatchObject({
health: 306_475,
mana: 262_000,
armor: 4_637,
averageAttackDamage: 416,
});
expect(creatureTemplateReference(1720)?.rank).toBe(2);
expect(creatureTemplateReference(10162)?.rank).toBe(3);
});
});