feat(editor): WPRC JSON round-trip closure

Adds --export-wprc-json / --import-wprc-json with the established
readEnumField template factoring int+name dual encoding for
triggerEvent ("onhit"/"oncrit"/"oncast"/"ontakedamage"/"onheal"/
"ondodge"/"onparry"/"onblock"/"onkill").

All 3 presets (weapon/ret/rage) byte-identical binary roundtrip
OK including the rage preset's previously-fixed Berserker Rage
proc rule (sourceSpellId=18499, procEffectSpellId=23691 distinct).

Live-tested self-loop validator a second time: re-introduced the
Berserker Rage source==effect bug via JSON edit (set effect back
to 18499). Validator correctly errored: "sourceSpellId ==
procEffectSpellId=18499 on OnCast trigger — infinite proc loop
(effect re-casts itself)". Confirms the round-trip path
preserves the self-loop guard and that the validator is ready
to catch this class of bug whenever a hand-edit reintroduces it.

CLI flag count 1443 -> 1445.
This commit is contained in:
Kelsi 2026-05-10 05:11:47 -07:00
parent 73d66a04d0
commit e49567da3c
3 changed files with 178 additions and 0 deletions

View file

@ -2695,6 +2695,10 @@ void printUsage(const char* argv0) {
std::printf(" Print WPRC entries (id / sourceSpellId / procEffectSpellId / triggerEvent / procChancePct / ICD ms / max stacks / flags / name)\n");
std::printf(" --validate-wprc <wprc-base> [--json]\n");
std::printf(" Static checks: id+name+sourceSpellId+procEffectSpellId required, triggerEvent 0..8, procChancePct in 1..10000 (basis points; 0 = never fires, > 10000 = > 100%%); CRITICAL: sourceSpellId == procEffectSpellId on OnCast trigger errors (infinite proc loop — effect re-casts itself). Warns on 100%% chance + 0ms ICD on high-frequency event (OnHit/OnCrit/OnTakeDamage) — would spam every swing without rate limiting (performance footgun)\n");
std::printf(" --export-wprc-json <wprc-base> [out.json]\n");
std::printf(" Export binary .wprc to a human-editable JSON sidecar (defaults to <base>.wprc.json; emits triggerEvent as int + name string)\n");
std::printf(" --import-wprc-json <json-path> [out-base]\n");
std::printf(" Import a .wprc.json sidecar back into binary .wprc (triggerEvent int OR \"onhit\"/\"oncrit\"/\"oncast\"/\"ontakedamage\"/\"onheal\"/\"ondodge\"/\"onparry\"/\"onblock\"/\"onkill\" — round-trips proc rule tables byte-identical)\n");
std::printf(" --catalog-pluck <wXXX-file> <id> [--json]\n");
std::printf(" Extract one entry by id from any registered catalog format. Auto-detects magic, dispatches to the per-format --info-* handler internally, then prints just the matching entry. Primary-key field is auto-detected (first *Id field, or first numeric)\n");
std::printf(" --catalog-find <directory> <id> [--magic <WXXX>] [--json]\n");