44 lines
1.8 KiB
JavaScript
44 lines
1.8 KiB
JavaScript
#!/usr/bin/env node
|
|
import { createHash } from "node:crypto";
|
|
import { readFile, writeFile } from "node:fs/promises";
|
|
import path from "node:path";
|
|
import { projectRoot, readJson, sourceRootFor } from "./lib/recipe.mjs";
|
|
|
|
const recipe = await readJson(path.join(projectRoot, "scripts/runewaker-pipeline/recipes/raksha-temple-population.json"));
|
|
const source = path.join(sourceRootFor(recipe), recipe.source.resourceRoot ?? "Resource", "data/npcobject.db");
|
|
const bytes = await readFile(source);
|
|
const dataStart = 140;
|
|
const count = bytes.readInt32LE(132);
|
|
const recordSize = 2_224;
|
|
const raceOffset = 176;
|
|
if (count <= 0 || dataStart + count * recordSize > bytes.length) throw new Error("Unexpected NPCObjectDB layout");
|
|
const knownIds = [];
|
|
const undeadIds = [];
|
|
const demonIds = [];
|
|
for (let index = 0; index < count; index += 1) {
|
|
const row = dataStart + index * recordSize;
|
|
if (bytes.readInt32LE(row + 4) !== 1) throw new Error(`Unexpected NPC object type at row ${index}`);
|
|
const id = bytes.readInt32LE(row);
|
|
if (id <= 0) continue;
|
|
knownIds.push(id);
|
|
const race = bytes.readInt32LE(row + raceOffset);
|
|
// ObjectStruct.h Race_ENUM names value 5 Undead. The source Demon Soldier
|
|
// and Demon Bodo NPC records use value 12.
|
|
if (race === 5) undeadIds.push(id);
|
|
if (race === 12) demonIds.push(id);
|
|
}
|
|
const sorted = (ids) => [...new Set(ids)].sort((left, right) => left - right);
|
|
const output = {
|
|
schemaVersion: 1,
|
|
sourceSha256: createHash("sha256").update(bytes).digest("hex"),
|
|
raceOffset,
|
|
knownIds: sorted(knownIds),
|
|
undeadIds: sorted(undeadIds),
|
|
demonIds: sorted(demonIds),
|
|
};
|
|
await writeFile(
|
|
path.join(projectRoot, "src/game/generated/romCreatureFamilies.json"),
|
|
`${JSON.stringify(output)}\n`,
|
|
);
|
|
console.log(`Exported ${output.knownIds.length} NPC families (${output.undeadIds.length} undead, ${output.demonIds.length} demon).`);
|