#!/usr/bin/env node // Development-only catalog reader. It consumes the JSON generated by the // MoonWell-enabled wow.export checkout; wow.export is not a runtime dependency. const fs = require('fs'); const [catalogPath, raceName = 'Blood Elf', sexName = 'female', optionName = 'Earrings'] = process.argv.slice(2); if (!catalogPath) { console.error('Usage: node tools/find_customization_assets.js [race] [sex] [option]'); process.exit(2); } const catalog = JSON.parse(fs.readFileSync(catalogPath, 'utf8')); const race = catalog.races.find(value => value.name.toLowerCase() === raceName.toLowerCase()); const sex = race && race.sexes.find(value => value.name.toLowerCase() === sexName.toLowerCase()); const option = sex && sex.options.find(value => value.name.toLowerCase() === optionName.toLowerCase()); if (!race || !sex || !option) { console.error(`Not found: race=${raceName}, sex=${sexName}, option=${optionName}`); process.exit(1); } console.log(`retailBuild=${catalog.source && catalog.source.build}`); console.log(`raceID=${race.id} chrModelID=${sex.chrModelID} modelFileDataID=${sex.modelFileDataID}`); console.log(`optionID=${option.id} option=${option.name}`); for (const choice of option.choices) { for (const element of choice.elements) { const fields = [ `choiceID=${choice.id}`, `order=${choice.orderIndex}`, `elementID=${element.id}`, `geosetID=${element.geosetID || 0}`, `skinnedModelID=${element.skinnedModelID || 0}`, ]; if (element.material) fields.push(`FileDataID=${element.material.FileDataID || 0}`); if (element.skinnedModel) fields.push(`collectionFileDataID=${element.skinnedModel.collectionFileDataID || 0}`); console.log(fields.join(' ')); } }