feat(editor): add WTRN JSON round-trip authoring workflow

Closes the WTRN open-format loop with --export-wtrn-json /
--import-wtrn-json, mirroring the JSON pairs added for
every other novel binary format. All 16 binary formats
added since WOL now have full JSON round-trip authoring.

Each NPC round-trips:
  • npcId, kindMask (dual int + kindList string array),
    greeting
  • spells[]: spellId / cost / requiredSkill+rank / minLevel
  • items[]:  itemId / stockCount / restockSec /
              extendedCost / moneyCostCopper

The stockCount field has special handling — the sentinel
0xFFFFFFFF value emits as the string "unlimited" instead of
the raw integer, since 4294967295 reads as a magic-number
typo in hand-edit JSON. The importer accepts either form.

Verified byte-identical round-trip on the starter preset
(innkeeper 4001 with 1 spell + 3 items, exercising both
unlimited-stock and finite-stock-with-restock cases).

Adds 2 flags (553 documented total now).
This commit is contained in:
Kelsi 2026-05-09 16:14:50 -07:00
parent d2ca3ea22b
commit c3f7286d4a
3 changed files with 188 additions and 0 deletions

View file

@ -1017,6 +1017,10 @@ void printUsage(const char* argv0) {
std::printf(" Print WTRN entries (npc / kind / spells with skill+level reqs / items with stock + restock)\n");
std::printf(" --validate-wtrn <wtrn-base> [--json]\n");
std::printf(" Static checks: npcId>0+unique, kindMask>0, Trainer needs spells, Vendor needs items, no orphan offers\n");
std::printf(" --export-wtrn-json <wtrn-base> [out.json]\n");
std::printf(" Export binary .wtrn to a human-editable JSON sidecar (defaults to <base>.wtrn.json)\n");
std::printf(" --import-wtrn-json <json-path> [out-base]\n");
std::printf(" Import a .wtrn.json sidecar back into binary .wtrn (accepts kindMask int OR kindList string array)\n");
std::printf(" --gen-weather-temperate <wow-base> [zoneName]\n");
std::printf(" Emit .wow weather schedule: clear-dominant + occasional rain + fog (forest / grassland)\n");
std::printf(" --gen-weather-arctic <wow-base> [zoneName]\n");