Add source-backed RoM heirloom reference curves
This commit is contained in:
1 parent
d3cc27a54a
commit
f4a7d33f74
9 files changed
+148524
-8
No files matched your search
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,55 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { classById } from "../app/characterCatalog";
|
||||
import {
|
||||
romHeirloomReference,
|
||||
romSourceReferenceItem,
|
||||
ROM_HEIRLOOM_REFERENCE_CLASSES,
|
||||
ROM_HEIRLOOM_REFERENCE_SLOTS,
|
||||
} from "./romHeirloomReference";
|
||||
|
||||
describe("RoM source-backed heirloom references", () => {
|
||||
it("provides finite native stats and source item IDs at every level from 1 through 79", () => {
|
||||
for (const classId of ROM_HEIRLOOM_REFERENCE_CLASSES) {
|
||||
for (const slot of ROM_HEIRLOOM_REFERENCE_SLOTS) {
|
||||
const first = romHeirloomReference(classId, slot, 1);
|
||||
if (!first) continue;
|
||||
for (let level = 1; level <= 79; level += 1) {
|
||||
const reference = romHeirloomReference(classId, slot, level)!;
|
||||
expect(reference.level).toBe(level);
|
||||
expect(reference.referenceItemIds.length).toBeGreaterThan(0);
|
||||
expect(Object.values(reference.stats).length).toBeGreaterThan(0);
|
||||
for (const value of Object.values(reference.stats)) {
|
||||
expect(Number.isFinite(value)).toBe(true);
|
||||
expect(value).toBeGreaterThanOrEqual(0);
|
||||
}
|
||||
for (const itemId of reference.referenceItemIds) {
|
||||
expect(romSourceReferenceItem(itemId)?.quality).toBe(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it("uses source package suit anchors and a leather reference for the Scout", () => {
|
||||
expect(romHeirloomReference("rom-knight", "chest", 50)?.packageId).toBe(240384);
|
||||
expect(romHeirloomReference("rom-scout", "chest", 60)?.packageId).toBe(240347);
|
||||
expect(romHeirloomReference("rom-priest", "chest", 65)?.packageId).toBe(240313);
|
||||
expect(classById("rom-scout").armor).toBe("leather");
|
||||
const scoutChest = romHeirloomReference("rom-scout", "chest", 65)!;
|
||||
expect(scoutChest.referenceItemIds.some((id) => romSourceReferenceItem(id)?.type === 2)).toBe(true);
|
||||
expect(romHeirloomReference("rom-priest", "off-hand", 65)).toBeNull();
|
||||
expect(romSourceReferenceItem(213416)?.stats).toMatchObject({ magicalWeaponDamage: 1094, wisdom: 56 });
|
||||
expect(romSourceReferenceItem(229164)?.stats).toMatchObject({
|
||||
physicalDefense: 1029,
|
||||
magicalDefense: 1655,
|
||||
health: 273,
|
||||
magicalAttack: 290,
|
||||
});
|
||||
});
|
||||
|
||||
it("clamps queries to the designed 1–79 heirloom interval", () => {
|
||||
expect(romHeirloomReference("rom-mage", "main-hand", -20)?.level).toBe(1);
|
||||
expect(romHeirloomReference("rom-mage", "main-hand", 80)?.level).toBe(79);
|
||||
expect(romHeirloomReference("rom-mage", "off-hand", 40)).toBeNull();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,77 @@
|
||||
import catalog from "./generated/romHeirloomReference.json";
|
||||
|
||||
export const ROM_HEIRLOOM_REFERENCE_CLASSES = [
|
||||
"rom-knight", "rom-priest", "rom-scout", "rom-rogue", "rom-mage",
|
||||
] as const;
|
||||
export type RomHeirloomReferenceClass = (typeof ROM_HEIRLOOM_REFERENCE_CLASSES)[number];
|
||||
|
||||
export const ROM_HEIRLOOM_REFERENCE_SLOTS = [
|
||||
"head", "neck", "shoulder", "back", "chest", "hands", "waist",
|
||||
"legs", "feet", "finger", "trinket", "main-hand", "off-hand", "ranged",
|
||||
] as const;
|
||||
export type RomHeirloomReferenceSlot = (typeof ROM_HEIRLOOM_REFERENCE_SLOTS)[number];
|
||||
|
||||
export interface RomNativeGearStats {
|
||||
readonly strength?: number;
|
||||
readonly stamina?: number;
|
||||
readonly intellect?: number;
|
||||
readonly wisdom?: number;
|
||||
readonly agility?: number;
|
||||
readonly health?: number;
|
||||
readonly mana?: number;
|
||||
readonly healthRecovery?: number;
|
||||
readonly manaRecovery?: number;
|
||||
readonly physicalAttack?: number;
|
||||
readonly physicalDefense?: number;
|
||||
readonly magicalDefense?: number;
|
||||
readonly magicalAttack?: number;
|
||||
readonly physicalHit?: number;
|
||||
readonly magicalHit?: number;
|
||||
readonly dodge?: number;
|
||||
readonly parry?: number;
|
||||
readonly physicalCritical?: number;
|
||||
readonly magicalCritical?: number;
|
||||
readonly weaponDamage?: number;
|
||||
readonly magicalDamage?: number;
|
||||
readonly magicalWeaponDamage?: number;
|
||||
readonly healingPower?: number;
|
||||
}
|
||||
|
||||
export interface RomHeirloomReference {
|
||||
readonly level: number;
|
||||
readonly stats: RomNativeGearStats;
|
||||
readonly referenceItemIds: readonly number[];
|
||||
readonly packageId?: number;
|
||||
readonly speedTenths?: number;
|
||||
}
|
||||
|
||||
interface RomSourceReferenceItem {
|
||||
readonly itemId: number;
|
||||
readonly name: string;
|
||||
readonly level: number;
|
||||
readonly quality: number;
|
||||
readonly sourceCatalog: string;
|
||||
readonly type: number;
|
||||
readonly position: number;
|
||||
readonly suitId: number;
|
||||
readonly stats: RomNativeGearStats;
|
||||
}
|
||||
|
||||
const profiles = catalog.profiles as unknown as Readonly<Record<RomHeirloomReferenceClass, Readonly<Partial<Record<RomHeirloomReferenceSlot, readonly RomHeirloomReference[]>>>>>;
|
||||
const sourceItems = new Map((catalog.sourceItems as readonly RomSourceReferenceItem[]).map((item) => [item.itemId, item]));
|
||||
|
||||
/** Source-backed design values; not yet the combat runtime's equipped item stats. */
|
||||
export function romHeirloomReference(
|
||||
classId: RomHeirloomReferenceClass,
|
||||
slot: RomHeirloomReferenceSlot,
|
||||
level: number,
|
||||
): RomHeirloomReference | null {
|
||||
const curve = profiles[classId]?.[slot];
|
||||
if (!curve) return null;
|
||||
const safeLevel = Math.max(1, Math.min(79, Math.trunc(Number.isFinite(level) ? level : 1)));
|
||||
return curve[safeLevel - 1] ?? null;
|
||||
}
|
||||
|
||||
export function romSourceReferenceItem(itemId: number): RomSourceReferenceItem | null {
|
||||
return sourceItems.get(itemId) ?? null;
|
||||
}
|
||||
Reference in new issue
Block a user