import { describe, expect, it } from "vitest"; import { resolveRomNativeNpcEquipment, romNativeNpcEquipmentRecord, } from "./romNativeNpcEquipment"; describe("native RoM NPC source equipment", () => { it("preserves the five weighted Barren Caves choices and resolves their exact item rows", () => { const sources = [101_459, 101_460, 101_461].map((npcId) => romNativeNpcEquipmentRecord(npcId)); expect(sources.every(Boolean)).toBe(true); expect(sources[0]?.mainHandCandidates.map((candidate) => candidate.sourceItemId)).toEqual([ 210_056, 210_056, 210_056, 210_056, 210_056, ]); expect(sources[1]?.mainHandCandidates.map((candidate) => candidate.sourceItemId)).toEqual([ 210_061, 210_061, 210_061, 210_061, 210_061, ]); expect(sources[2]?.offHandCandidates.map((candidate) => candidate.sourceItemId)).toEqual([ 210_666, 210_666, 210_666, 210_666, 210_666, ]); for (const source of sources) { expect(source?.mainHandCandidates.map((candidate) => candidate.selectionWeightPercent)).toEqual([20, 20, 20, 20, 20]); expect(source?.offHandCandidates.map((candidate) => candidate.selectionWeightPercent)).toEqual([20, 20, 20, 20, 20]); } const caveGuard = resolveRomNativeNpcEquipment(101_459, { selectionSeed: "actor-cave-1" }); const caveArcher = resolveRomNativeNpcEquipment(101_460, { selectionSeed: "actor-cave-1" }); const caveWarden = resolveRomNativeNpcEquipment(101_461, { selectionSeed: "actor-cave-1" }); expect(caveGuard.status).toBe("supported"); expect(caveArcher.status).toBe("supported"); expect(caveWarden.status).toBe("supported"); if (caveGuard.status !== "supported" || caveArcher.status !== "supported" || caveWarden.status !== "supported") return; expect(caveGuard.value.mainHand).toMatchObject({ sourceItemId: 210_056, sourceCatalog: "weaponobject.db", durable: 70, refineLevel: 0, attackRange: 20, attackSpeed: 20, eqTypeValuePairs: Array.from({ length: 10 }, (_, slot) => ({ slot, eqType: 0, value: 0 })), dropAbilityIdRatePairs: Array.from({ length: 6 }, (_, slot) => ({ slot, attributeId: 0, rate: 0 })), }); expect(caveArcher.value.mainHand).toMatchObject({ sourceItemId: 210_061, durable: 55, attackSpeed: 20 }); expect(caveWarden.value.offHand).toMatchObject({ sourceItemId: 210_666, durable: 1426, gearPosition: 2, attackSpeed: 20 }); expect(caveGuard.value.wornItems[0]).toMatchObject({ fieldQuality: 100, fieldDurability: 10_000, fieldPowerQuality: 10, durabilityPowerRate: 1.2, wearPower: 1.2 }); expect(caveWarden.value.wornItems[0]).toMatchObject({ slot: "offHand", durabilityPowerRate: 0.2, wearPower: 0.2 }); }); it("selects deterministically from source weights without averaging or discarding candidate slots", () => { const source = romNativeNpcEquipmentRecord(100_052); expect(source?.mainHandCandidates.map((candidate) => candidate.sourceItemId)).toEqual([ 210_059, 0, 210_059, 0, 210_059, ]); expect(source?.mainHandCandidates.map((candidate) => candidate.selectionWeightPercent)).toEqual([20, 20, 20, 20, 20]); const first = resolveRomNativeNpcEquipment(100_052, { selectionSeed: "same-actor" }); const repeated = resolveRomNativeNpcEquipment(100_052, { selectionSeed: "same-actor" }); expect(first.status).toBe("supported"); expect(repeated.status).toBe("supported"); if (first.status !== "supported" || repeated.status !== "supported") return; expect(first.value.selectedCandidateIndices).toEqual(repeated.value.selectedCandidateIndices); expect(first.value.selectedCandidateIndices.mainHand).toBeGreaterThanOrEqual(0); expect(first.value.selectedCandidateIndices.mainHand).toBeLessThan(5); const selected = resolveRomNativeNpcEquipment(100_052, { mainHandCandidateIndex: 0, offHandCandidateIndex: 1, selectionSeed: "ignored-where-index-is-explicit", }); expect(selected.status).toBe("supported"); if (selected.status !== "supported") return; expect(selected.value.mainHand?.sourceItemId).toBe(210_059); expect(selected.value.offHand).toBeNull(); expect(selected.value.selectedCandidateIndices).toEqual({ mainHand: 0, offHand: 1 }); }); it("resolves fixed BowEQ rows as source metadata while retaining exact ability pairs", () => { const source = romNativeNpcEquipmentRecord(102_425); expect(source?.bowEquipmentId).toBe(212_011); const result = resolveRomNativeNpcEquipment(102_425, { mainHandCandidateIndex: 0, offHandCandidateIndex: 0, }); expect(result.status).toBe("supported"); if (result.status !== "supported") return; expect(result.value.bow).toMatchObject({ sourceItemId: 212_011, sourceCatalog: "weaponobject.db", eqTypeValuePairs: expect.arrayContaining([ { slot: 0, eqType: 25, value: 19 }, { slot: 1, eqType: 191, value: 7 }, ]), }); }); });