feat(editor): add WSPS (Spell Proc Trigger) open catalog format

Open replacement for AzerothCore's spell_proc_event SQL table
plus the per-spell proc fields embedded in Spell.dbc. Defines
when a "trigger" spell fires in response to other spell/combat
events: Windfury Weapon procs on melee attack, Clearcasting on
damaging cast, Judgement of Wisdom on melee hit, etc.

Each entry says "when an event matching procFlags fires from a
spell matching procFromSpellId (0 = any), at procChance
probability with at most one trigger per internalCooldownMs
window, fire triggerSpellId". The procPpm field provides an
alternative procs-per-minute formula (when non-zero, supersedes
procChance and scales with weapon speed for melee procs — the
canonical WoW behavior for weapon imbues).

13-bit procFlags bitfield covers the standard event taxonomy:
DealtMeleeAutoAttack / DealtMeleeSpell / TakenMeleeAutoAttack /
TakenMeleeSpell / DealtRangedAutoAttack / DealtRangedSpell /
DealtSpell / DealtSpellHeal / TakenSpell / OnKill / OnDeath /
OnCastFinished / Critical (the last is a modifier — fires only
on crit-tagged events).

Cross-references back to WSPL (triggerSpellId references the
spell that fires; procFromSpellId optionally restricts to a
specific source spell).

Three preset emitters: --gen-sps (4 weapon-imbue procs with
canonical PPM rates and ICDs), --gen-sps-aura (4 aura-tied
procs across multiple proc-flag combinations), --gen-sps-talent
(4 talent procs including charge-consuming Clearcasting and
Nightfall variants).

Validation enforces id+name+triggerSpellId+procFlags presence,
no duplicate ids; warns on:
  - procChance outside [0..1] (engine clamps)
  - procPpm < 0 (invalid PPM rate)
  - both procChance > 0 AND procPpm > 0 set (engine prefers PPM
    so procChance is silently ignored)
  - both procChance=0 AND procPpm=0 (proc never fires)

Wired through the cross-format table; WSPS appears automatically
in all 18 cross-format utilities. Format count 88 -> 89; CLI
flag count 1041 -> 1046.
This commit is contained in:
Kelsi 2026-05-09 23:32:25 -07:00
parent 28becba00e
commit 16ebcdda44
10 changed files with 714 additions and 0 deletions

View file

@ -1999,6 +1999,16 @@ void printUsage(const char* argv0) {
std::printf(" Export binary .wtbr to a human-editable JSON sidecar (defaults to <base>.wtbr.json)\n");
std::printf(" --import-wtbr-json <json-path> [out-base]\n");
std::printf(" Import a .wtbr.json sidecar back into binary .wtbr (accepts rewardKind/requiredFactionStanding int OR name)\n");
std::printf(" --gen-sps <wsps-base> [name]\n");
std::printf(" Emit .wsps 4 weapon-imbue procs (Windfury 20PPM+3sICD / Frostbrand 9PPM / Flametongue 15PPM / Mana Oil 4PPM+5sICD) on DealtMeleeAutoAttack\n");
std::printf(" --gen-sps-aura <wsps-base> [name]\n");
std::printf(" Emit .wsps 4 aura-tied procs (Blessing of Wisdom mana / Molten Armor reflect / Earth Shield heal / Judgement of Wisdom)\n");
std::printf(" --gen-sps-talent <wsps-base> [name]\n");
std::printf(" Emit .wsps 4 talent procs (Clearcasting / Omen of Clarity / Seal of Righteousness / Nightfall) with charge-consuming variants\n");
std::printf(" --info-wsps <wsps-base> [--json]\n");
std::printf(" Print WSPS entries (id / triggerSpellId / fromSpellId / chance%% / PPM / ICD / charges / proc flags)\n");
std::printf(" --validate-wsps <wsps-base> [--json]\n");
std::printf(" Static checks: id+name+triggerSpellId+procFlags required, no duplicate ids; warns on chance outside [0,1], procPpm<0, both chance+ppm set (PPM wins), neither set (never fires)\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");