feat(editor): add WPCR (Pet Care & Action) — 111th open format

Novel replacement for the implicit pet-management action
rules vanilla WoW scattered across spell_template
(Revive Pet / Mend Pet / Feed Pet / Dismiss Pet
definitions), npc_text (stable master gossip), and
per-class trainer SQL. Each entry binds one pet
management action to its dispatching spell, gold cost,
reagent requirement, cast time, cooldown, and pet/NPC
pre-conditions.

Eleven actionKind enum values cover the full pet
management surface: Revive / Mend / Feed / Dismiss /
Tame / BeastLore / Stable / Untrain / Rename / Abandon
(Hunter), plus Summon (Warlock minion conjures). The
classFilter field uses WCHC class-bit conventions
(4=Hunter, 256=Warlock) so a single WPCR catalog can
cover both class systems.

Three preset emitters: makeHunterCare (5 Hunter pet
care actions), makeStableActions (4 stable-master
gold-cost actions), makeWarlockMinions (4 Warlock minion
summons with shared 10s cooldown + Soul Shard reagent).

Validator's most novel checks are PER-KIND constraints:
Tame and Summon require requiresPet=0 (you can't tame
or summon while another pet is active) — these are
ERRORS, not warnings, since the action would simply
fail at runtime. Stable kind without requiresStableNPC
warns (stable-slot purchases are normally gated to
stable-master conversation). Tame kind without cooldown
warns (canonical 15s anti-macro-spam cooldown). The
TameBeast preset originally omitted this cooldown — the
validator caught and flagged it during smoke-test, fix
applied before commit.

Format count 110 -> 111. CLI flag count 1199 -> 1204.
This commit is contained in:
Kelsi 2026-05-10 02:10:54 -07:00
parent cbc4991305
commit cebf821205
10 changed files with 764 additions and 0 deletions

View file

@ -2307,6 +2307,16 @@ void printUsage(const char* argv0) {
std::printf(" Export binary .wmnl to a human-editable JSON sidecar (defaults to <base>.wmnl.json; minZ/maxZ as floats, all string fields as plain strings)\n");
std::printf(" --import-wmnl-json <json-path> [out-base]\n");
std::printf(" Import a .wmnl.json sidecar back into binary .wmnl (no enums to coerce — pure positional/textual data; minZ/maxZ float-precise round-trip)\n");
std::printf(" --gen-pcr <wpcr-base> [name]\n");
std::printf(" Emit .wpcr 5 Hunter pet care actions (Revive Pet / Mend Pet / Feed Pet / Dismiss Pet / Tame Beast)\n");
std::printf(" --gen-pcr-stable <wpcr-base> [name]\n");
std::printf(" Emit .wpcr 4 stable-master actions (Stable Slot Purchase 500g / Untrain Pet 1g+ramp / Rename Pet / Abandon Pet permanent)\n");
std::printf(" --gen-pcr-warlock <wpcr-base> [name]\n");
std::printf(" Emit .wpcr 4 Warlock minion summons (Imp 6.5s / Voidwalker 10s / Succubus 10s / Felhunter 10s, all 1 Soul Shard)\n");
std::printf(" --info-wpcr <wpcr-base> [--json]\n");
std::printf(" Print WPCR entries (id / spellId / classFilter / actionKind / happiness / pet-required / stable-NPC required / cost copper / reagent / cast ms / name)\n");
std::printf(" --validate-wpcr <wpcr-base> [--json]\n");
std::printf(" Static checks: id+name+classFilter required, actionKind 0..10, no duplicate actionIds, per-kind constraints (Tame and Summon REQUIRE no active pet, requiresPet must be 0); warns on happinessRestore outside +/-25, Stable kind without requiresStableNPC, Tame kind without cooldown (canonically 15 sec)\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");