35 lines
1.6 KiB
JavaScript
35 lines
1.6 KiB
JavaScript
const fs = require('fs');
|
|
|
|
function load(path) {
|
|
return JSON.parse(fs.readFileSync(path, 'utf8'));
|
|
}
|
|
|
|
function dist(a, b) {
|
|
return Math.hypot(a.world.x - b.world.x, a.world.y - b.world.y);
|
|
}
|
|
|
|
function qlo(item) {
|
|
return item.quality & 0xff;
|
|
}
|
|
|
|
function isSpawner(item) {
|
|
return item.shapeDefId === 'shape:1232';
|
|
}
|
|
|
|
for (const [label, path] of [
|
|
['map1', 'k:/ghidra/crusader_map_viewer/map_renderer/.cache/scene-cache/remorse/map-1/9ccaa5dabe08947e/scene.json'],
|
|
['map248', 'k:/ghidra/crusader_map_viewer/map_renderer/.cache/scene-cache/remorse/map-248/b27ea0d8d2a1a391/scene.json']
|
|
]) {
|
|
const scene = load(path);
|
|
const items = scene.items.filter(isSpawner);
|
|
const interesting = items.filter((item) => item.npcPreview?.name === 'Observer' || item.npcPreview?.name === 'RoamingSusan');
|
|
console.log(`\n### ${label} interesting spawners ${interesting.length}`);
|
|
for (const item of interesting) {
|
|
const pairs = items.filter((candidate) => candidate.id !== item.id && candidate.frame !== item.frame && qlo(candidate) === qlo(item) && dist(candidate, item) <= 128);
|
|
const pairText = pairs.map((candidate) => `${candidate.id} src=${candidate.mapSourceIndex} f=${candidate.frame} npc=${candidate.npcNum} ${candidate.npcPreview?.name || '?'} qlo=${qlo(candidate)} d=${dist(candidate, item).toFixed(1)} map=${candidate.mapNum}`).join(' || ');
|
|
console.log(`${item.id} src=${item.mapSourceIndex} f=${item.frame} npc=${item.npcNum} ${item.npcPreview?.name || '?'} qlo=${qlo(item)} map=${item.mapNum} world=${item.world.x},${item.world.y},${item.world.z}`);
|
|
if (pairText) {
|
|
console.log(` pairs: ${pairText}`);
|
|
}
|
|
}
|
|
}
|