Commit graph

79 commits

Author SHA1 Message Date
Kelsi
fa8719009b feat(editor): add WCDF (Creature Difficulty) open catalog format
Open replacement for Blizzard's CreatureDifficulty.dbc. Maps a
base creature entry to its difficulty variants:
Normal-10 / Normal-25 / Heroic-10 / Heroic-25 in WotLK raid
format. Each variant is itself a separate WCRT creature entry
with its own stats, abilities, and loot.

When a 25-man party engages an instance, the engine looks up the
encounter base creature's difficultyId, reads the normal25Id
field, and spawns that variant instead. This is how Lord
Marrowgar in 25-Heroic ICC has 30M HP and hits for 80k while the
same encounter in 10-Normal has 5M HP and hits for 25k — same
spawn point, different WCRT entries.

5-man dungeons typically use only normal10Id + heroic10Id (the
25-man fields stay 0 — engine falls through to the 10-man
variant when 25-man is queried). World bosses don't scale at
all (all 4 variant fields stay 0, engine falls back to the base
entry).

Cross-references back to WCRT — every non-zero variant id field
points at a WCRT.creatureId entry; the base creature itself
lives in WCRT too.

Three preset emitters: --gen-cdf (4 example bosses with full
4-variant routing), --gen-cdf-wotlk-raid (4 ICC-style raid
bosses Marrowgar/Deathwhisper/Saurfang/LK with all 4 difficulty
variants), --gen-cdf-fiveman (4 5-man dungeon bosses with only
Normal+Heroic 10-man set). resolveVariant(id, mode) is the
engine helper.

Validation enforces id+name+baseCreatureId presence,
spawnGroupKind 0..5, no duplicate ids; warns on:
  - WorldBoss kind with non-zero variant ids (world bosses don't scale)
  - duplicate baseCreatureId across routes (only first honored)
  - all-self-reference non-WorldBoss (creature doesn't actually scale)
  - Boss with n25 but not n10 (raid sequencing typo — n10 always
    comes with n25)

Wired through the cross-format table; WCDF appears automatically
in all 11 cross-format utilities. Format count 74 -> 75; CLI flag
count 936 -> 941.
2026-05-09 22:10:09 -07:00
Kelsi
48c770f5ea feat(editor): add WGFS (Glyph Slot) open catalog format
Open replacement for Blizzard's GlyphSlot.dbc. Defines the
per-class glyph slot layout: which slots a class has (Major /
Minor / Prime), in which display order they appear in the
spellbook UI, and at which character level each slot becomes
available for use.

Distinct from WGLY (GlyphProperties) which defines the individual
glyphs themselves. WGLY says "Glyph of Polymorph exists, costs 1
inscription dust, modifies Polymorph"; WGFS says "the slot that
holds Glyph of Polymorph is the second Major Glyph Slot, unlocks
at level 25, and only Mages have it".

Layout grew across expansions, captured by the three presets:
  - --gen-gfs       — 6 slots: 3 Major + 3 Minor all-class
                       baseline (25/50/75 each)
  - --gen-gfs-wotlk — 6 slots: 3 Major (15/30/50) + 3 Minor
                       (15/50/70) matching WotLK 3.3.5a
  - --gen-gfs-cata  — 9 slots: 3 Prime + 3 Major + 3 Minor
                       matching Cataclysm

Cross-references back to WGLY (glyphs reference slotKind to
constrain which glyph fits which slot) and WCHC (requiredClassMask
uses the same bit layout as WCHC class IDs).

Validation enforces id+name+classMask presence (classMask=0 means
no class can use the slot — usually a config bug), slotKind 0..2,
no duplicate ids; warns on minLevelToUnlock>80 (would never
unlock at WotLK cap), displayOrder>4 (UI typically shows 3-4),
and (kind+order) collisions for overlapping classMask (two slots
claiming the same UI position would render on top of each other).
isUnlockedFor(id, classBit, level) is the engine helper.

Wired through the cross-format table; WGFS appears automatically
in all 11 cross-format utilities. Format count 73 -> 74; CLI flag
count 929 -> 934.
2026-05-09 22:05:05 -07:00
Kelsi
88effe39cd feat(editor): add WSPC (Spell Power Cost) — completes spell-bucket five-pack
Open replacement for the per-spell power-cost fields in Spell.dbc
plus SpellPowerCost-related side tables. Defines categorical
power-cost buckets that spells reference (LowMana 5% / MediumMana
15% / HighMana 30% of caster max mana; fixed Rage-30 /
Energy-40 / Runic-30 / etc), so spells share cost metadata across
ranks instead of embedding per-rank cost numbers.

Completes the small lookup-bucket five-pack:
  WSRG — range bucket
  WSCT — cast time bucket
  WSDR — duration bucket
  WSCD — cooldown bucket
  WSPC — power cost bucket   (this catalog)

Five small integer ids per spell (range / cast / dur / cd / cost)
replace the dozens of duplicate per-rank fields that Blizzard's
Spell.dbc carries. Editing one bucket here retunes every spell
that references it — change LowMana from 5% to 4% and every
rank-1 bolt across every caster class becomes cheaper.

Cost can be flat (baseCost), per-level scaled (perLevelCost), or
percentage-of-max-power (percentOfBase) — the engine sums
whichever fields are non-zero. resolveCost(id, level, maxPower)
does the math. Twelve power types covering every WoW resource
(Mana / Rage / Focus / Energy / Happiness / Runic Power / Runes /
Soul Shards / Holy Power / Eclipse / Health / NoCost).

Three preset emitters: --gen-spc (4 baseline mana tiers),
--gen-spc-rage (4 fixed warrior rage costs including stance-locked
Whirlwind), --gen-spc-mixed (5 cross-class costs covering every
non-mana power type with refund-on-miss flag for energy).

Validation enforces id+name presence, powerType 0..11, no
duplicate ids; warns on percentOfBase outside [0,1] (would
overflow), NoCost type with non-zero cost fields, and non-NoCost
types with no cost set (would cast for free — easy bug to ship).

Wired through the cross-format table; WSPC appears automatically
in all 11 cross-format utilities. Format count 72 -> 73; CLI flag
count 922 -> 927.
2026-05-09 22:00:55 -07:00
Kelsi
74be3f6135 feat(editor): add --magic-fix to auto-rename files to canonical extension
Natural follow-up to --audit-tree: when that utility flags
ext-mismatch or magic-no-ext issues, --magic-fix proposes (and
optionally applies) the renames that resolve them. Walks a
directory recursively, reads each file's 4-byte magic, looks it
up in the format table, and renames to the canonical extension
when the current extension doesn't match (or is absent).

Defaults to dry-run for safety — prints the proposed renames so
they can be reviewed first; pass --apply to commit them. Refuses
to clobber existing files: when the target path already exists
(e.g. foo.wsct + foo.wsrg both with WSRG magic), the rename is
flagged as a collision and skipped, leaving both files in place
for manual resolution. Returns exit 1 if any proposals exist (in
dry-run) or any collisions are skipped (in apply), so it composes
into shell pipelines.

JSON sidecar via --json. Suggested workflow:
  --audit-tree dir          # find what's broken
  --magic-fix dir           # preview the auto-fixes
  --magic-fix dir --apply   # commit them
  --audit-tree dir          # confirm clean

CLI flag count 921 -> 922.
2026-05-09 21:57:26 -07:00
Kelsi
12faffeb87 feat(editor): add WCEF (Creature Family) open catalog format
Open replacement for CreatureFamily.dbc plus the per-creature
family fields in Creature.dbc. Defines the family categorization
that pet-able beasts share (Bear / Cat / Wolf / Boar / Crab /
Raptor / Devilsaur / etc), each with its own pet talent tree
(Ferocity / Tenacity / Cunning), food preferences as a bitmask
(Meat / Fish / Bread / Cheese / Fruit / Fungus / Raw), the skill
line that family-specific abilities reference, and the minimum
hunter level required to tame it.

Used by the hunter pet system to decide which talent tree a tamed
pet uses, validate that a hunter can tame a creature, match
feeding-table food items to pet preferences, and gate exotic-beast
families behind the Beast Master 51-point talent.

Cross-references back to WCRT (creature.familyId points here) and
WSPL (family-specific abilities reference WSPL spellId via the
skillLine field).

Three preset emitters: --gen-cef (5 baseline families covering
both major talent trees), --gen-cef-ferocity (4 DPS-tree pets
with bleed/howl/armor-shred mechanics), --gen-cef-exotic (4
exotic Beast Master families requiring 51-point talent).

Validation enforces id+name presence, familyKind 0..5, talent
tree 0..3, no duplicate ids, and warns on:
  - NotPet families with a non-None talent tree (irrelevant)
  - Exotic families with minLevelForTame > 80 (level-cap unreachable)
  - Beast/Exotic families with no food types set (pet would starve)

Wired through the cross-format table; WCEF appears automatically
in all 10 cross-format utilities. Format count 71 -> 72; CLI flag
count 914 -> 919.
2026-05-09 21:54:00 -07:00
Kelsi
493db026dd feat(editor): add WSCD (Spell Cooldown Category) open catalog format
Open replacement for SpellCooldown.dbc plus the per-spell
category-cooldown fields in Spell.dbc. Defines the shared-cooldown
buckets that related spells reference: casting one spell triggers
a cooldown on every other spell in the same bucket. Mage Polymorph
variants (Sheep / Pig / Turtle / Cat) all share one bucket so
morphing a target locks all variants at once. Healing potions and
mana potions share the SharedWithItems bucket so consuming one
locks the other.

Distinct from WSDR (which times how long an aura stays on a
target) — WSCD times how long before a spell can be cast again.
The global cooldown (GCD) is itself just one bucket of this kind,
flagged with OnGCDStart so the engine triggers it at cast start
rather than cast finish.

Three preset emitters: --gen-cdb (4 baseline buckets including
GCD), --gen-cdb-class (5 mage-specific class cooldowns including
the Polymorph family), --gen-cdb-items (5 item cooldowns
including the heal/mana potion shared bucket and the 60min
Hearthstone family). Validation enforces id+name presence,
bucketKind 0..4, no duplicate ids, and warns on Global without
OnGCDStart (engine wouldn't trigger on cast start) and Spell
kind with SharedWithItems (contradictory).

categoryFlags is a bitfield (AffectedByHaste / SharedWithItems /
OnGCDStart / IgnoresCooldownReduction); --info-wscd decodes the
bits to label list. Wired through the cross-format table; WSCD
appears automatically in all 9 cross-format utilities. Format
count 70 -> 71; CLI flag count 907 -> 912.
2026-05-09 21:49:13 -07:00
Kelsi
824b6ebf53 feat(editor): add --audit-tree to flag corrupted/misnamed Wowee files
Walks a directory recursively and groups problems by category:
too-small (file under 16 bytes — can't hold a header),
unknown-magic (.w* file whose magic is not in the format table),
ext-mismatch (extension says one format but the magic says
another — usually from a renamed file), magic-no-ext (file with
recognized Wowee magic but no .w* extension), and header-trunc
(magic matches but the rest of the header is truncated). Returns
exit 1 if any issue is found, so it composes into shell pipelines
and CI checks. JSON sidecar via --json.

Catches the kinds of breakage that --summary-dir silently rolls
into the "unrecognized" bucket — a renamed .wsrg file masquerading
as .wsct shows up cleanly here but would otherwise be invisible.
Like every cross-format utility this reuses cli_format_table.cpp,
so new formats are audited automatically. CLI flag count
906 -> 907.
2026-05-09 21:45:54 -07:00
Kelsi
98f899cf7c feat(editor): add WSDR (Spell Duration Index) — completes WSRG/WSCT/WSDR triplet
Open replacement for SpellDuration.dbc plus per-spell duration
fields in Spell.dbc. Defines the categorical duration buckets
that auras / DoTs / HoTs / buffs reference (5s / 30s / 5min / 1hr
/ UntilCancelled / UntilDeath).

Together with WSRG (range) and WSCT (cast time), this completes a
small triplet of spell-metadata catalogs: instead of every
Frostbolt rank embedding its own range, cast time, and
chill-debuff duration as duplicate fields, each spell holds three
small integer ids that resolve through these three tables. The
engine retunes thousands of spells at once by editing one bucket.

Duration scales with caster level via perLevelMs (a rank-1 Renew
at 9s grows to 12s at lvl 60), then is clamped to maxDurationMs.
Negative baseDurationMs is the canonical sentinel for "no timer"
(UntilCancelled / UntilDeath); resolveAtLevel returns -1 for
those so HUD code can render the indefinite-duration glyph.

Three preset emitters: --gen-sdr (5 baseline tiers from instant
to one-hour), --gen-sdr-buffs (4 long-duration buffs including
UntilDeath), --gen-sdr-dot (4 tick-based DoT/HoT buckets at 3s
ticks). Validation enforces base>0 for Timed/TickBased, base<0
for permanent kinds, max>=base, durationKind 0..4, no duplicate
ids, and warns on Instant+nonzero base.

Wired through the cross-format table; WSDR appears automatically
in all 9 cross-format utilities. Format count 69 -> 70; CLI flag
count 899 -> 904.
2026-05-09 21:41:55 -07:00
Kelsi
8dcbd08a16 feat(editor): add WSCT (Spell Cast Time Index) open catalog format
Companion to WSRG: open replacement for SpellCastTimes.dbc plus
the per-spell castTime fields in Spell.dbc. Defines categorical
cast-time buckets (Instant 0ms / FastCast 1s / MediumCast 1.5s /
LongCast 3s) that thousands of spells reference instead of each
embedding their own ms count. Together WSRG and WSCT let the
spell engine resolve "Frostbolt's range bucket = id 3" and
"Frostbolt's cast time bucket = id 5" with two table reads
instead of duplicating per-rank data.

Cast time can scale with character level via perLevelMs (a rank-1
spell at 1000ms can grow to 2200ms at lvl 60), then the bucket
result is clamped to [minCastMs, maxCastMs] before haste is
applied. resolveAtLevel() does the math for engine consumers.

Three preset emitters: --gen-sct (4 baseline buckets),
--gen-sct-channel (3 channeled-spell durations), --gen-sct-ramp
(4 level-scaled buckets with non-zero perLevelMs). Validation
catches negative baseCastMs, min>max, duplicate ids, warns on
Instant kind with non-zero base (cast bar would still show), and
errors on Channel kind with zero base (would tick once and end).

Wired through the cross-format table; WSCT appears automatically
in all 9 cross-format utilities. Format count 68 -> 69; CLI flag
count 892 -> 897.
2026-05-09 21:37:42 -07:00
Kelsi
ede2d9918a feat(editor): add WSRG (Spell Range Index) open catalog format
Open replacement for Blizzard's SpellRange.dbc plus the per-spell
range-bucket fields in Spell.dbc. Defines the categorical range
buckets that spells reference instead of carrying their own min/max
yards (every Frostbolt shares one 30y bucket; every Heal shares
one 40y friendly bucket). Each entry carries separate min/max for
hostile vs friendly targets so heals can reach further on allies
than nukes do on enemies, plus an icon color for HUD range
indicators.

Three preset emitters: --gen-srg (3 baseline buckets:
Self/Melee/Spell), --gen-srg-ranged (5 ranged spell buckets:
Short/Medium/Long/VeryLong/Unlimited), --gen-srg-friendly (3
friendly-only buckets where hostile range is 0). --info-wsrg and
--validate-wsrg round out the per-format surface; validation
catches negative ranges, min>max, duplicate ids, out-of-range
rangeKind, and warns on Self+nonzero range or Melee>8y.

Wired through the cross-format table so WSRG appears automatically
in --list-formats, --info-magic, --diff-headers, --summary-dir,
--rename-by-magic, --catalog-grep, --tree-summary-md, and
--touch-tree. Format count 67 -> 68; CLI flag count 885 -> 890.
2026-05-09 21:33:17 -07:00
Kelsi
99a952299b feat(editor): add --diff-headers cross-file header comparison
Compares two .w* files at the standard catalog header level:
4-byte magic, version, catalog name, entry count, total file
bytes. Useful for confirming a JSON round-trip didn't drift,
checking whether two preset emissions produced equivalent
output, or quickly diagnosing when a content snapshot has
silently shifted (entry count up means content was added,
file bytes up but everything else same means entry payloads
got fatter).

Output uses = / ≠ markers per field so visual scanning is
fast. Three diagnostic summary cases: identical headers (and
same bytes — possibly byte-equal, run cmp(1) to confirm),
same shape but bytes differ (entry payloads diverged), and
different formats entirely (files are unrelated).

Returns exit 1 if any field differs, so the flag composes
into shell pipelines (`if diff-headers a.wcms b.wcms; then ...`).
World/asset formats stop after magic since their layouts
diverge from the standard catalog header.

Supports --json variant for tooling integration.
2026-05-09 21:27:26 -07:00
Kelsi
23ba7ed6a0 feat(pipeline): add WQSO (Wowee Quest Sort) catalog
67th open format — replaces QuestSort.dbc plus the quest-log
categorization fields in QuestInfo.dbc. Defines the
categories that quests fall into for the quest-log UI:
class quests (Warrior trial, etc), profession quests, daily
quests, holiday events, reputation grinds, dungeon /
heroic / raid quests, repeatables, PvP, tournament.

12 sort kinds (General / ClassQuest / Profession / Daily /
Holiday / Reputation / Dungeon / Raid / Heroic / Repeatable
/ PvP / Tournament). Each WQT (quest) entry can reference
a sortId here to be grouped under the right header in the
quest log. Sorts can be class-restricted (Warrior quests
only show for warriors), profession-restricted, or
faction-reputation-gated.

Cross-references with prior formats — targetClassMask uses
WCHC.classId bit positions (matches WGLY/WSET/WGTP
convention), targetProfessionId points at WTSK.profession
enum, targetFactionId points at WFAC.factionId.

CLI: --gen-qso (3 generic sorts — General catch-all, Daily
reset, Repeatable non-daily), --gen-qso-class (10 class-
specific sorts with proper bit masks for Warrior 0x02
through Druid 0x800), --gen-qso-profession (8 profession
sorts with WTSK profession enum cross-refs), --info-wqso,
--validate-wqso with --json variants. Validator catches
id+name+displayName required, kind 0..11, ClassQuest with
classMask=0 (not actually class-restricted), Profession
with profId=0 + non-Blacksmithing-name (likely typo since
0=Blacksmithing in WTSK), and Reputation with factionId=0
(no faction to grind).

Format graph: 66 → 67 binary formats. CLI flag count: 877
→ 882.
2026-05-09 21:23:38 -07:00
Kelsi
1ca665150b feat(pipeline): add WUMV (Wowee Unit Movement Type) catalog
66th open format — replaces UnitMovement.dbc plus the
movement-modifier portions of CreatureModelData.dbc. Defines
movement speed types (walk / run / swim / flight / fly /
pitch) with their canonical baseline speeds in yards-per-
second, plus the temp speed buffs that stack on top
(Sprint, Aspect of the Cheetah, Travel Form).

12 movement categories cover the canonical surface (Walk /
Run / Backward / Swim / SwimBack / Turn / Flight /
FlightBack / Pitch / Fly / FlyBack / TempBuff). baseSpeed
is yards/second for baseline categories and ignored for
TempBuff entries (which use baseMultiplier instead).
maxMultiplier caps stacking — Sprint capped at 1.4 means
Sprint + Aspect of Cheetah doesn't exceed 1.4× run speed.
stackingPriority resolves conflicts when multiple buffs
of equal multiplier compete (higher wins).

CLI: --gen-umv (4 baseline at canonical WoW vanilla speeds:
Walk 2.5y/s, Run 7.0y/s, Swim 4.7y/s, Turn π rad/s),
--gen-umv-flight (5 flight entries — ground-rail Flight
7y/s, free Fly 14y/s, Pitch 1.5 rad/s, backward variants
at slower 4.5y/s), --gen-umv-buffs (5 temp speed buffs
matching real WoW spell auras with proper durations and
stacking priorities), --info-wumv, --validate-wumv with
--json variants. Validator catches id+name required,
category 0..11, baseMultiplier > 0 (otherwise unit freezes
in place), maxMultiplier >= baseMultiplier (cap below
floor would clamp the base down), baseline categories
need baseSpeed > 0, and Run < 3.0y/s warning (canonical
is 7.0y/s).

Format graph: 65 → 66 binary formats. CLI flag count: 870
→ 875.
2026-05-09 21:18:03 -07:00
Kelsi
5865421b00 feat(pipeline): add WCRR (Wowee Combat Rating Conversion) catalog
65th open format — replaces gtCombatRatings.dbc plus the
per-level rating-to-percentage tables in gtRegenHPPerSpt.dbc
and related stat-curve DBCs. Defines per-rating-type
conversion factors at canonical level breakpoints (1 / 60
/ 70 / 80) — the runtime linearly interpolates between
breakpoints for intermediate levels.

pointsAtLevelN is "how many rating points equal 1% of the
benefit at that level." Higher level = more rating needed
for the same %. Standard WoW WotLK example: 14 crit rating
= 1% crit at L60, but 45.91 = 1% at L80.

5 rating kinds (Combat / Defense / Spell / Resilience /
Other) classify what stat resolver category each rating
belongs to.

CLI: --gen-crr (3 essential combat ratings — Hit/Crit/Haste
at canonical WoW WotLK conversion values), --gen-crr-defensive
(4 defensive — Defense/Dodge/Parry/Block with diminishing-
returns soft-cap percentages), --gen-crr-spell (3 spell —
SpellPower direct 1:1, SpellPenetration flat, MP5 mana
regen), --info-wcrr, --validate-wcrr with --json variants.
Validator catches id+name required, kind 0..4, all
pointsAtLN > 0 (otherwise stat resolver would div-by-zero),
maxBenefitPercent > 0 (rating would never grant any
benefit), and non-monotonic conversion curve warning
(rating cost typically ascends with level for non-flat
ratings like SpellPower).

Format graph: 64 → 65 binary formats. CLI flag count: 861
→ 868.
2026-05-09 21:11:26 -07:00
Kelsi
d547de61f5 feat(pipeline): add WSUF (Wowee Item Random Suffix) catalog
64th open format — replaces ItemRandomProperties.dbc +
ItemRandomSuffix.dbc plus the AzerothCore-style suffix-roll
tables. Defines random "of the X" suffixes that roll on
green and blue items at world drop ("Sturdy Cloth Cap of
the Bear" = base item + STR + STA suffix).

5 suffix categories (Generic / Elemental / Defensive /
PvPSuffix / Crafted), per-suffix item-quality bracket gating
(only blue+ items can roll PvPSuffix), restricted-slot mask
that limits which equipment slots a suffix can apply to (15
slot bits matching WCEQ slot enum), and up to 5 stat bonus
slots per suffix matching WoW canonical max.

statValuePoints isn't an absolute number — it's a scaling
base that the runtime multiplies by an item-level
coefficient to compute the final per-item bonus, so "of the
Bear" gives proportionally more strength on a level-60 item
than on a level-20 item.

Cross-references with prior formats — statKind values match
WIT.statType enum (STR=4, AGI=3, INT=5, SPI=6, STA=7) so
item generators roll consistent stats with base items.

CLI: --gen-suf (3 generic stat triads — Bear STR+STA, Eagle
INT+SPI, Tiger STR+AGI), --gen-suf-magical (4 elemental
spell-power suffixes restricted to caster-eligible slots),
--gen-suf-pvp (3 PvPSuffix entries with resilience + offensive
stats, blue+ quality only), --info-wsuf, --validate-wsuf with
--json variants. Validator catches id+name required, category
0..4, quality range valid (0..7 covers heirloom), itemQuality
floor<=ceiling, stat-kind/value pairing (kind=0 with value!=0
is a typo, vice versa), and no-stats warning (suffix renames
item without changing it).

Format graph: 63 → 64 binary formats. CLI flag count: 854
→ 861.
2026-05-09 21:05:49 -07:00
Kelsi
07137acc89 feat(pipeline): add WLDS (Wowee Loading Screen) catalog
63rd open format — replaces LoadingScreens.dbc plus the
per-zone background-image tables. Defines the loading-screen
images shown when the client crosses into a new map /
instance, with optional level-bracket gating and expansion
gating (TBC art only shown if expansion installed).

When multiple screens match the player's current map + level
+ expansion, displayWeight selects randomly between them — a
zone with 3 weighted variants gets a different image roughly
proportional to weight.

4 expansion gates (Classic / TBC / WotLK / TurtleWoW),
isAnimated flag for screens with subtle animation,
isWideAspect flag for 16:9 raid intro art (vs 4:3 standard).

Cross-references with prior formats — mapId points at
WMS.map.mapId (which map triggers this loading screen);
mapId=0 is the catch-all sentinel for screens shown when
no map-specific screen matches.

CLI: --gen-lds (3 base screens — Elwynn level 1-30, Orgrimmar,
GenericFallback level 31-80 catch-all), --gen-lds-instances
(5 WotLK dungeon screens with mapId+expansion cross-refs:
Halls of Lightning/Stone, Utgarde Pinnacle, Violet Hold,
Old Kingdom), --gen-lds-raid (3 raid intro screens —
Naxxramas/Ulduar/ToC at isWideAspect=1 with weight=3),
--info-wlds, --validate-wlds with --json variants. Validator
catches id+name+texture required, expansion 0..3, level range
valid, weight=0 (in pool but never picked), and the practical
catch-all overlap warning when multiple mapId=0 screens share
overlapping level brackets (random pick becomes
non-deterministic).

Format graph: 62 → 63 binary formats. CLI flag count: 847
→ 854.
2026-05-09 20:59:25 -07:00
Kelsi
ad603c0c44 feat(pipeline): add WRUN (Wowee DK Rune Cost) catalog
62nd open format — replaces RuneCost.dbc plus the DK-specific
portions of ChrPowerType. Defines per-spell rune costs (Blood
/ Frost / Unholy) and runic-power generation / consumption
for the Death Knight class.

4 spell tree branches (BloodTree / FrostTree / UnholyTree /
Generic) classify which spec uses each rune cost. Each entry
binds a spell to its rune cost (how many of each rune kind
the spell consumes), an optional anyDeathConvertCost (extra
Death-rune-acceptable cost for procced abilities), and a
runicPowerCost (negative = generator, positive = spender).

Cross-references with prior formats — spellId points at
WSPL.spellId (the spell that uses this rune cost).

CLI: --gen-rune (3 baseline DK abilities — Death Strike
1F+1U + 20RP gen, Frost Strike pure 40 RP spender, Heart
Strike 1B + 10RP gen), --gen-rune-blood (4 blood-tree DK
abilities — Heart Strike, Death and Decay AoE, Vampiric
Blood tank cooldown, Rune Tap self-heal), --gen-rune-frost
(4 frost-tree — Frost Strike, Howling Blast AoE, Obliterate
finisher, Icy Touch ranged opener applying Frost Fever),
--info-wrun, --validate-wrun with --json variants. Validator
catches id+name+spellId required, branch 0..3, no rune cost
> 2 (DK only has 2 of each rune type so a higher cost can
never be paid), runicPowerCost > 100 (DK RP cap), no-cost
warning (spell consumes nothing — verify it's a
passive/stance/form), and high-RP-generator warning (> 25
RP per cast is unusual).

Format graph: 61 → 62 binary formats. CLI flag count: 840
→ 847.
2026-05-09 20:52:19 -07:00
Kelsi
1c3470d1d7 feat(pipeline): add WBNK (Wowee Bag / Bank Slot) catalog
61st open format — replaces ItemBag.dbc plus the bank-storage
and special-purpose container tables. Defines every slot the
player has access to: equipped bags, bank bags, keyring, soul
shard bag, quiver, reagent bag, hunter pet stable.

8 bag kinds (Inventory / Bank / Keyring / Quiver / SoulShard /
Stable / Reagent / Wallet) cover the canonical container
surface. Each entry has a fixed capacity (or 0 = variable,
size set by equipped bag), a display order in the inventory
UI, an unlock state with optional gold cost (bank bags ramp
through 10s / 1g / 10g / 25g / 50g / 100g matching canonical
WoW prices), and an accepts-bag-subclass mask gating which
container kinds may be equipped (generic / herb / enchanting
/ engineer / gem / mining / leather / inscription / quiver /
ammo pouch).

Cross-references with prior formats — fixedBagItemId points
at WIT.itemId for the bag item that always occupies a fixed
slot (0 = player-equipable variable slot).

CLI: --gen-bnk (5 inventory slots — 16-slot fixed main
backpack + 4 player-equippable bag slots accepting generic
containers + herb + enchanting bags), --gen-bnk-bank (8 bank
bag slots with the canonical WoW unlock cost ramp),
--gen-bnk-special (4 special-purpose: 32-slot Keyring fixed,
warlock SoulShardBag, hunter ArrowQuiver, hunter
HuntersStable for 5 pets), --info-wbnk, --validate-wbnk with
--json variants. Validator catches id+name required, kind
0..7, locked-with-zero-cost (slot can never be unlocked),
fixed-slot-with-non-zero-mask (equippable bag would be
ignored), variable slot with empty mask (no bag can fit),
and ambiguous (bagKind, displayOrder) tuples (UI sort would
flicker).

Format graph: 60 → 61 binary formats. CLI flag count: 833
→ 840.
2026-05-09 20:46:06 -07:00
Kelsi
e9997ed218 feat(pipeline): add WPVP (Wowee PvP Honor / Rank) — 60th open format
60th open format milestone — replaces the AzerothCore-style
PvP rank tables plus the vanilla honor-rank reward chains.
Defines PvP progression rungs: vanilla honor ranks (Private
through Grand Marshal / High Warlord), arena rating brackets
(Combatant / Challenger / Rival / Duelist / Gladiator), and
battleground rated tiers.

5 rank kinds (VanillaHonor / ArenaRating / BattlegroundRated /
WorldPvP / ConquestPoint) cover the canonical PvP progression
surface. Each entry carries an alliance-specific name and a
horde-specific name (Grand Marshal = High Warlord; arena tiers
share the same name on both factions), an honor or rating
threshold, and optional gear cross-refs (chest, gloves,
shoulders) into WIT.

Cross-references with prior formats — titleId points at
WTTL.titleId (the unlock title), chest/gloves/shoulders point
at WIT.itemId for the matching PvP set, bracketBgId points at
WBGD.bgId for battleground-bracket gating.

CLI: --gen-pvp (3 vanilla entry tiers Rank2-4 with alliance
vs horde alternate names), --gen-pvp-alliance (9 vanilla
ranks 6-14 with WTTL+WIT cross-refs and ramping honor
thresholds 50k → 260k), --gen-pvp-arena (5 arena rating
brackets 1500/1750/2000/2200/2400 with 10/20/40/80/160 emblem
rewards), --info-wpvp, --validate-wpvp with --json variants.
Validator catches id+name required, kind 0..4, level range
valid, faction-name pairing (one set without the other is a
typo), threshold monotonicity within a rankKind, arena rating
below 1500 floor, and VanillaHonor with minHonor=0 baseline
warning.

Format graph: 59 → 60 binary formats (milestone). CLI flag
count: 826 → 833.
2026-05-09 20:41:09 -07:00
Kelsi
243d7f4416 feat(pipeline): add WCHF (Wowee Character Customization Feature) catalog
59th open format — replaces CharHairGeosets.dbc +
CharFacialHairStyles.dbc plus the variation portions of
CharSections.dbc. Defines per-(race, sex) customization
options the character creation screen exposes: skin colors,
face variations, hair styles, hair colors, facial hair
(beards / mustaches), and race-specific markings (Tauren
horns, Draenei tendrils, Blood Elf ears).

9 feature kinds (SkinColor / FaceVariation / HairStyle /
HairColor / FacialHair / FacialColor / EarStyle / Horns /
Markings) cover the full canonical customization surface.
Each entry is one selectable carousel choice for one
(race, sex, kind) tuple — variationIndex disambiguates.
expansionGate enum gates Blood Elf / Draenei (TBC) and DK
features (WotLK) behind the right expansion unlock.

Cross-references with prior formats — raceId points at
WCHC.race.raceId. requiresExpansion bit positions match
the WLFG expansion enum (Classic=0, TBC=1, WotLK=2,
Turtle=3) for consistency.

CLI: --gen-chf (5 Human Male starter — skin / face / 2
hair styles / facial hair), --gen-chf-bloodelf (8 Blood
Elf Female hair styles, requiresExpansion=TBC — the
iconic TBC race feature), --gen-chf-tauren (6 Tauren Male
features using race-specific Horns kind + 3 facial hair
variations), --info-wchf, --validate-wchf with --json
variants. Validator catches id+name+raceId+texturePath
required, kind 0..8 / sex 0..1 / expansion 0..3, and the
critical (race, sex, kind, variation) tuple-uniqueness
check — duplicates would shadow each other in the create-
character carousel.

Format graph: 58 → 59 binary formats. CLI flag count: 819
→ 826.
2026-05-09 20:35:21 -07:00
Kelsi
a81e69c78d feat(pipeline): add WMAC (Wowee Macro / Slash Command) catalog
58th open format — novel format with no direct DBC equivalent.
WoW historically stored player macros client-side in the user
profile and system slash commands as hardcoded engine handlers;
WMAC unifies both into a single structured catalog so default
macros, system slash commands, and shipped player presets can
be authored, validated, and shipped as content alongside the
rest of the open-format graph.

5 macro kinds (SystemSlash for engine /sit /dance handlers,
DefaultMacro for shipped presets, PlayerTemplate for user
templates, GuildMacro for guild-shared, SharedMacro for
account-wide). Multi-line macro bodies are stored verbatim
with literal '\n' separators — the client parses /cast /
/target / /run lines at runtime.

Cross-references with prior formats — requiredClassMask uses
WCHC.classId bit positions (Warrior=0x02, etc, same as WGLY/
WSET/WGTP).

CLI: --gen-mac (3 system slash — /sit, /dance, /target with
[@mouseover] modifier), --gen-mac-combat (4 warrior combat
templates — heroic strike spam, charge/intercept stance dance,
intercept stance switch, victory rush+bloodthirst fallback —
each with default key bindings), --gen-mac-utility (3 universal
utility — /follow target, mass /inv with %targetN tokens,
/releasecorpse via RepopMe()), --info-wmac, --validate-wmac
with --json variants. Validator catches id+name+body required,
kind 0..4, body within maxLength cap, body starting with '/'
or '#' (slash command or showtooltip annotation), and
SystemSlash + classMask warning (slash commands are class-
agnostic — restricting them to a class makes no sense).

Format graph: 57 → 58 binary formats. CLI flag count: 814
→ 819.
2026-05-09 20:30:17 -07:00
Kelsi
34c7021e5c feat(editor): add --catalog-grep search-by-name across content tree
Recursively walks a directory, parses the standard catalog
header (magic + version + name + entryCount) of every
recognized catalog format, and reports files whose internal
catalog NAME field matches a pattern. Useful when you've
got a content bundle and need to find "where is the catalog
named WintergraspUI?" or "list every Starter* preset in
this directory" without per-format parsing.

Case-insensitive substring match by default (--case-sensitive
opts in to literal match). Returns exit 1 when no match —
designed for shell composition (`if catalog-grep ... ; then ...`).
World/asset formats (.wom/.wob/.whm/.wot/.wow) are skipped
since they don't follow the catalog-header layout.

Supports --json variant for tooling integration. Reuses
cli_format_table.cpp so any new catalog format is searchable
automatically.
2026-05-09 20:27:16 -07:00
Kelsi
385cdd7dc9 feat(pipeline): add WLFG (Wowee Looking-for-Group) catalog
57th open format — replaces LFGDungeons.dbc plus the
AzerothCore-style dungeon-finder reward tables. Defines the
dungeons / raids that the Dungeon Finder / Raid Browser
presents to players, with their level brackets, group-size
requirements, role requirements (tank / heal / DPS), and
queue-completion rewards.

4 difficulty levels (Normal / Heroic / Mythic / Hardmode —
the latter for Ulduar-style toggleable boss difficulty),
4 expansion gates (Classic / TBC / WotLK / TurtleWoW), and
3 role-requirement bits (Tank / Heal / DPS — typically all
three for queue-formed groups).

Cross-references with prior formats — mapId points at
WMS.mapId (the instance map), queueRewardItemId points at
WIT.itemId (the random reward bag), firstClearAchievement
points at WACH.achievementId.

CLI: --gen-lfg (3 classic 5-mans Ragefire/Wailing/Deadmines
with real WoW mapIds + level brackets), --gen-lfg-heroic
(5 WotLK 80-level heroic 5-mans with emblem rewards +
real first-clear achievement IDs from Halls of Lightning
through Old Kingdom), --gen-lfg-raid (3 raid entries —
Naxx-25, Ulduar-25 Hardmode, ToC-25 Mythic), --info-wlfg,
--validate-wlfg with --json variants. Validator catches
id+name+mapId required, difficulty 0..3, expansion 0..3,
minLevel<=maxLevel, recommended-level outside range
warning, unusual groupSize warning (5/10/25/40 are
canonical), and zero role mask (queue can't form a
balanced group).

Format graph: 56 → 57 binary formats. CLI flag count: 804
→ 811.
2026-05-09 20:24:21 -07:00
Kelsi
a664027f5f feat(pipeline): add WSCH (Wowee Spell School) catalog
56th open format — replaces SpellSchools.dbc plus the
Resistances.dbc resistance-cap tables. Defines damage
schools spells use: Physical, Holy, Fire, Nature, Frost,
Shadow, Arcane, plus combined / hybrid schools that count
as multiple types simultaneously (Spellfire, Spellshadow,
Spellfrost — relevant for resistance-bypass mechanics).

7 canonical schools with single-bit IDs (1, 2, 4, 8, 16,
32, 64) so combinedSchoolMask values line up directly with
the spell engine's school-bit enum. Hybrid schools use
high-bit IDs (0x80000001+) and their combinedSchoolMask
references the canonical bits they qualify as. Each school
carries visual identity (color tint, icon), gameplay rules
(canBeImmune / canBeAbsorbed / canBeReflected / canCrit),
resistance cap at max level, and cast / impact sound IDs.

Cross-references with prior formats — castSoundId and
impactSoundId point at WSND.soundId; combinedSchoolMask
is a bitmask of OTHER WSCH.schoolId values within the same
catalog.

CLI: --gen-sch (3 base — Physical / Fire / Holy showing
non-resistable Holy + non-reflectable Physical), --gen-sch-
magical (6 canonical magical schools with proper colors
+ 365 max-level resistance caps), --gen-sch-combined (3
hybrids — Spellfire / Spellshadow / Spellfrost with
multi-bit combinedSchoolMask), --info-wsch, --validate-wsch
with --json variants. Validator catches id+name required,
reflected-without-absorbed warning (reflected damage
should be absorbable), self-referential combinedSchoolMask
(school qualifying as itself), and combined-mask references
to bits not defined in the same catalog (resolved at runtime
across catalogs).

Format graph: 55 → 56 binary formats. CLI flag count: 798
→ 804.
2026-05-09 20:19:34 -07:00
Kelsi
23bb97651c feat(editor): add --tree-summary-md content inventory generator
Walks a directory recursively, identifies every Wowee
open-format file by 4-byte magic, parses the standard
catalog header, and emits a Markdown report. Useful for
content-bundle distributions to ship with a README of
what's inside, and for change-log generation when
diffing two content snapshots manually.

The report has three sections: a summary table (total
files / recognized / bytes), a per-format breakdown
(magic / ext / file count / total entries / description),
and a per-file detail table (path / magic / version /
catalog name / entries / bytes). Output to stdout if no
out path is given, otherwise written to a file.

Reuses cli_format_table.cpp so any new format added in
the future appears automatically without touching this
tool.
2026-05-09 20:16:27 -07:00
Kelsi
1c6faa2891 feat(pipeline): add WKBD (Wowee Keybinding) catalog
55th open format — replaces KeyBinding.dbc plus the
AzerothCore-style default-keybind SQL data. Defines the key
bindings shipped with the game: movement (W/A/S/D),
targeting (Tab), action bars (1-9, 0, -, =), UI panels
(C/I/B/P/N/L), chat (Enter), camera (Insert/Delete).

Each binding has an internal action name (SCREAMING_SNAKE
convention — "MOVE_FORWARD"), a primary key, an optional
alternate key, a category for the keybindings UI grouping,
and a flag indicating whether the user can override it.
Hardcoded engine bindings (alt-F4, ESC) set
isUserOverridable=0 so the rebind dialog can't accidentally
break them.

9 categories (Movement / Combat / Targeting / Camera /
UIPanels / Chat / Macro / Bar / Other) for the rebind
dialog grouping.

CLI: --gen-kbd (3 essential WASD/Tab/C bindings), --gen-kbd-
movement (8 movement: WASD + arrow alternates + jump +
autorun), --gen-kbd-ui (10 UI panel bindings covering all
the standard interface windows), --info-wkbd, --validate-wkbd
with --json variants. Validator catches id+actionName+
defaultKey required, category 0..8, alternateKey ==
defaultKey (no point in alt), action-name lowercase warning
(should be SCREAMING_SNAKE), duplicate primary keys (would
silently shadow earlier binding), and duplicate action names.

Format graph: 54 → 55 binary formats. CLI flag count: 791
→ 796.
2026-05-09 20:13:37 -07:00
Kelsi
c0920a2047 feat(pipeline): add WSMC (Wowee Spell Mechanic) catalog
54th open format — replaces SpellMechanic.dbc plus the
AzerothCore-style diminishing-returns (DR) tables. Defines
crowd-control mechanic categories that spells reference:
Stun, Silence, Polymorph, Sleep, Fear, Root, Snare, Slow,
Knockback, etc. Each mechanic carries gameplay metadata
(breaks-on-damage, can-be-dispelled, default duration, max
stacks) plus DR category and dispel type.

8 DR categories (DRNone / DRStun / DRDisorient / DRSilence
/ DRRoot / DRPolymorph / DRControlled / DRMisc) — the
runtime uses these to gate repeated CC on the same target.
7 dispel types (DispelNone / Magic / Curse / Disease /
Poison / Enrage / Stealth) bind which dispel spells can
remove the mechanic. conflictsMask is a bitmask of OTHER
mechanic IDs — only one mechanic from a conflict-group can
apply to a target simultaneously.

Cross-references with prior formats — mechanicId is
referenced by WSPL.spellId entries that apply this CC; this
catalog is referenced from spell tags rather than referencing
out.

CLI: --gen-smc (3 baseline Stun/Silence/Snare), --gen-smc-
hard (5 hard-CC: Stun/Polymorph/Sleep/Fear/Knockback with
conflictsMask wiring), --gen-smc-roots (4 movement-impair:
Root/Snare/Slow stacking 5x/GroundPin breaks-on-damage),
--info-wsmc, --validate-wsmc with --json variants. Validator
catches id+name required, DR category 0..7, dispel type
0..6, maxStacks=0 (mechanic could never apply),
canBeDispelled+DispelNone inconsistency, and self-conflict
bit set in conflictsMask (mechanic blocking itself).

Format graph: 53 → 54 binary formats. CLI flag count: 784
→ 789.
2026-05-09 20:09:44 -07:00
Kelsi
f98157b5a5 feat(pipeline): add WCMP (Wowee Companion Pet) catalog
53rd open format — replaces the companion-pet portions of
CreatureFamily.dbc plus the AzerothCore-style critter / vanity-
pet SQL data. Distinct from WPET (which covers hunter combat
pets and warlock minions); WCMP covers non-combat "vanity" pets
that follow the player around for cosmetic reasons —
Mechanical Squirrel, Mini Diablo, Panda Cub, dragon hatchlings.

8 companion kinds (Critter, Mechanical, DragonHatchling,
Demonic, Spectral, Elemental, Plush, UndeadCritter), 4
rarity tiers (Common / Uncommon / Rare / Epic), and 3
faction restrictions (AnyFaction / AllianceOnly / HordeOnly).

Cross-references with prior formats — creatureId points at
WCRT.creatureId (the rendered model), learnSpellId at
WSPL.spellId (the spell that summons the pet), itemId at
WIT.itemId (the item that teaches the spell), and
idleSoundId at WSND.soundId (idle ambient noise).

CLI: --gen-cmp (3 common vendor pets), --gen-cmp-rare (4
promo / collector pets at Epic rarity — Mini Diablo,
Panda Cub, Zergling, Murky), --gen-cmp-faction (3 faction-
restricted Alliance Lion Cub / Horde Mottled Boar /
neutral Argent Squire), --info-wcmp, --validate-wcmp with
--json variants. Validator catches id+name+creatureId+
learnSpellId required, kind 0..7 / rarity 0..3 / faction
0..2 range, and Epic-rarity-no-itemId warning (most promo
pets need a redemption-code item).

Format graph: 52 → 53 binary formats. CLI flag count: 777
→ 782.
2026-05-09 20:05:06 -07:00
Kelsi
383d8d730a feat(pipeline): add WGTP (Wowee Game Tips) catalog
52nd open format — replaces GameTips.dbc plus loading-screen
tutorial hint tables. Defines the rotating tips shown during
world loads, the contextual tutorial hints that fire on first
gameplay events (first quest accept, first death, first
dungeon entry), and the persistent tooltip-help strings that
explain UI elements.

4 display kinds (LoadingScreen / Tutorial / TooltipHelp /
Hint), 7 audience-filter bits (Alliance / Horde / NewPlayer /
Hardcore / PvE / PvP / Roleplay) for pool selection, level
range gating (minLevel + maxLevel), displayWeight for
relative frequency within the pool, optional WPCN condition
cross-ref for further gating, and class-mask restriction
matching WCHC bit positions.

Cross-references with prior formats — conditionId points at
WPCN.conditionId for advanced gating; requiredClassMask uses
the same WCHC.classId bit layout as WGLY/WSET.

CLI: --gen-tips (3 generic loading-screen tips), --gen-tips-
new-player (5 onboarding Tutorial-kind tips for level 1-15,
weighted higher for new players), --gen-tips-advanced (4
endgame tips for level 70+ covering raid mechanics / arena /
daily professions / dungeon finder), --info-wgtp,
--validate-wgtp with --json variants. Validator catches
id/name/text required, kind 0..3, audienceFilter=0 (tip
never shown), invalid level range, displayWeight=0 (in pool
but never picked) warning, and brevity check (>280 chars)
on Tutorial / Hint kinds that need to fit on screen.

Format graph: 51 → 52 binary formats. CLI flag count: 770
→ 775.
2026-05-09 20:00:56 -07:00
Kelsi
5fe461cca8 feat(editor): add --touch-tree CI integrity check
Recursively walks a directory, identifies every recognized .w*
file by 4-byte magic, and parses the standard catalog header
(magic + version + length-prefixed name + entryCount) to
confirm the file isn't truncated, corrupted, or otherwise
malformed at the header level. Reports per-file PASS/FAIL +
extension-mismatch warnings (when a file's actual extension
doesn't match what its magic says it should be).

Exits 1 on any FAIL — designed as a CI gate that runs after
content build to catch truncations / write-failures /
disk-full mid-emit. World/asset formats (WOM/WOB/WHM/WOT/WOW)
are recognized by magic but the catalog-header probe is
skipped since their layouts differ.

Implausibility caps: catalog-name length > 1MB or
entryCount > 1M trigger failure as likely corruption signals.
--quiet hides the per-file PASS/FAIL list (summary line only);
--json variant for tooling integration.
2026-05-09 19:58:01 -07:00
Kelsi
42bc024bd3 feat(pipeline): add WSET (Wowee Item Set / Tier Bonus) catalog
51st open format — replaces ItemSet.dbc + ItemSetSpell.dbc
plus the AzerothCore-style item_set_spell SQL data. Closes
the tier-bonus gap left by WIT (which describes individual
items but not the set bonuses they grant when worn together).

Each entry binds up to 8 piece item IDs to up to 4 bonus
thresholds — at N pieces worn, the matching bonus spell
activates as an aura. Standard 2/4/6/8-piece tier set pattern
is the canonical case; 5-piece PvP sets with 2/4 bonuses are
also supported.

Cross-references with prior formats — itemIds[] point at
WIT.itemId, bonusSpellIds[] point at WSPL.spellId, and
requiredSkillId points at WSKL.skillId. requiredClassMask
is a 32-bit field (uint32_t) so bit positions match WCHC's
classId enum directly — Druid (bit 11 = 0x800) and Mage
(bit 8 = 0x100) wouldn't fit in a uint8_t.

CLI: --gen-itset (2 raid sets — Battlegear of Wrath +
Stormrage Raiment, real WoW item/spell IDs), --gen-itset-tier
(4 tier-1 progression sets covering plate / cloth / leather /
holy plate), --gen-itset-pvp (3 PvP gladiator 5-piece sets
with honor-rank skill thresholds), --info-wset, --validate-wset
with --json variants. Validator catches id+name+pieceCount
required, pieceCount/bonusCount within array bounds, piece-
slot drift (0 IDs within count or non-0 IDs past count),
bonus thresholds strictly ascending, no bonus threshold
exceeding pieceCount (would never trigger), and spellId=0
in any populated bonus slot.

Format graph: 50 → 51 binary formats. CLI flag count: 762
→ 767.
2026-05-09 19:54:36 -07:00
Kelsi
71d504822b feat(pipeline): add WCEQ (Wowee Creature Equipment) — 50th open format
Replaces the AzerothCore-style creature_equip_template SQL
tables plus the visible-weapon / shield / ranged-slot data
that was traditionally embedded in creature templates. Closes
a long-standing gap in the creature subsystem: until now WCRT
defined a creature's stats, WSPN placed it in the world, and
WLOT defined what it drops — but nothing defined what items
it visibly equips.

Each entry binds a creatureId to up to three equipped items
(main hand / off hand / ranged) plus the visual kit that
fires when the main-hand weapon is brandished. equipFlags
bits encode hidden / dual-wield / shield-offhand /
thrown-ranged / 2H polearm to drive the renderer's
attachment-point selection.

Cross-references with prior formats — creatureId points at
WCRT.creatureId, mainHandItemId / offHandItemId / rangedItemId
all point at WIT.itemId, and mainHandVisualId points at
WSVK.visualKitId so brandished weapons can play their
signature glow / aura.

CLI: --gen-ceq (3 generic guard/hunter/rogue starters),
--gen-ceq-bosses (4 iconic loadouts incl. Frostmourne and
Illidan's warglaives, with WSVK visual cross-refs),
--gen-ceq-ranged (3 ranged-only rifle/bow/crossbow loadouts),
--info-wceq, --validate-wceq with --json variants. Validator
catches id=0/duplicates, missing creatureId, all-empty-slots
warning, kFlagDualWield without both hand items, kFlagShield
without offhand item, mutually-exclusive dual-wield + shield,
and 2H polearm with offhand item filled.

Format graph milestone: 50 distinct binary formats. CLI flag
count: 754 → 760.
2026-05-09 19:48:13 -07:00
Kelsi
33a7b4b3cf feat(pipeline): add WTSK (Wowee Trade Skill / Recipe) catalog
New open format — replaces SkillLineAbility.dbc plus the
recipe portions of SkillLine.dbc plus the AzerothCore
trade_skill SQL tables. Closes the crafting gap left by WSKL
(which carries skill lines but not the recipes that bind to
them).

14 professions (Blacksmithing, Tailoring, Engineering,
Alchemy, Enchanting, Leatherworking, Jewelcrafting,
Inscription, Mining, Skinning, Herbalism, Cooking, FirstAid,
Fishing). Each recipe has 4 skill-up bracket thresholds
(orange / yellow / green / gray) for skill-up probability,
a craft spell cross-ref (WSPL), produced item cross-ref
(WIT) with min/max quantity range, an optional tool item,
and up to 4 reagent slots (itemId + count).

Cross-references with prior formats — craftSpellId points at
WSPL.spellId, producedItemId / toolItemId / reagent[].itemId
all point at WIT.itemId, and skillId points at WSKL.skillId.

CLI: --gen-tsk (3-recipe entry-tier starter), --gen-tsk-
blacksmithing (5-recipe progression rough sharpening through
truesilver champion), --gen-tsk-alchemy (5-recipe progression
minor healing through flask of titans), --info-wtsk,
--validate-wtsk with --json variants. Validator catches
id=0/duplicates, profession out of range, missing craft spell
or produced item, monotonic-bracket check (must be orange <=
yellow <= green <= gray), reagent itemId-without-count
mismatch, and free-recipe warning (no reagents and no tool).

Format graph now exposes 49 distinct binary formats. CLI
flag count: 747 → 752.
2026-05-09 19:41:49 -07:00
Kelsi
b983ef6d48 feat(pipeline): add WPCN (Wowee Player Condition) catalog
49th open format — replaces PlayerCondition.dbc plus the
AzerothCore-style condition resolver. Defines reusable
boolean checks that other catalogs reference by conditionId
to gate gossip options, vendor items, quest availability,
achievement criteria, spell trainer offerings.

16 condition kinds (Always, Race, Class, Level, Zone, Map,
Reputation, AchievementWon, QuestComplete, QuestActive,
SpellKnown, ItemEquipped, Faction, InCombat, Mounted,
Resting), 8 comparison ops (==, !=, >, >=, <, <=, in-set,
not-in-set), and 4 chain ops (none, and, or, not) — chain
multiple conditions via chainNextId to express arbitrary
boolean trees.

Cross-references with prior formats — targetIdA is
polymorphic by conditionKind: resolves to WCHC raceId/classId,
WMS areaId/mapId, WFAC factionId, WACH achievementId, WQT
questId, WSPL spellId, or WIT itemId. chainNextId resolves
within the same WPCN catalog.

CLI: --gen-pcn (3 single-check starters), --gen-pcn-quest-gates
(4 cross-format quest gates with real WQT/WFAC/WACH/WMS IDs),
--gen-pcn-composite (3 leaves + 3 chained roots showing AND/
OR/NOT). Validator catches id=0/duplicates, kind/op out of
range, chain self-loop (infinite recursion), chainOp set
without chainNextId (dangling chain), chainNextId set without
chainOp (dead pointer warning), and unresolved chainNextId
references.
2026-05-09 19:36:56 -07:00
Kelsi
d332229a79 feat(pipeline): add WWUI (Wowee World-State UI) catalog
48th open format — replaces WorldStateUI.dbc plus the
AzerothCore-style world_state SQL data. Defines on-screen UI
elements that surface server-side world-state variables: BG
scoreboards (flag captures, base controls), Wintergrasp tank
counters, Eye of the Storm flag-carrier indicator, dungeon
boss progress, world-event collection trackers.

Each entry binds a server-side variableIndex to a UI panel
kind (counter / timer / flag-icon / progress-bar / two-sided
score / custom) gated by mapId+areaId, with optional
alwaysVisible and hideWhenZero flags and a chosen panel
position (top / bottom / top-left / top-right / center).

Cross-references with prior formats — mapId points at
WMS.mapId and areaId points at WMS.areaId.

CLI: --gen-wsui (3-entry BG scoreboard starter for WSG/AB/
EotS), --gen-wsui-wintergrasp (4-entry full Wintergrasp UI),
--gen-wsui-dungeon (3-entry boss/keys/treasure hunt UI),
--info-wwui, --validate-wwui with --json variants. Validator
catches id=0/duplicates, kind/position out of range,
variableIndex=0 warning, alwaysVisible+hideWhenZero conflict
warning, and (mapId, variableIndex) collision warning when
two entries would read the same server slot on the same map.

Also extends --list-formats and --info-magic with WWUI.
2026-05-09 19:32:15 -07:00
Kelsi
4b928274b8 feat(editor): add --rename-by-magic extension recovery flag
Reads the 4-byte magic of a file, looks it up in the shared
format table, and renames the file to use the correct .w*
extension. Useful when files have lost their extensions
(downloaded as 'data.bin', extracted from a tarball with
mangled metadata, or copied via a tool that strips suffixes).

Safe by default — refuses to overwrite an existing target;
pass --force to allow overwrite. --dry-run prints the planned
move without touching the filesystem. Files that already have
the correct extension are a no-op. Unrecognized magic exits
1 with the bytes printed for diagnostic context.

Reuses cli_format_table.cpp so any future format addition is
picked up automatically.
2026-05-09 19:29:18 -07:00
Kelsi
824a6c8cab feat(editor): add --summary-dir bulk content inventory
Recursively walks a directory, identifies every file by 4-byte
magic, and reports per-format file count, total entries, and
bytes. Useful for content audits ("how many cinematics did
this asset bundle ship?") and for tracking migration progress
("what fraction of zones still lack a holiday catalog?").

Also extracts the format-magic table out of cli_info_magic.cpp
into a shared cli_format_table.{hpp,cpp} so --info-magic and
--summary-dir reuse the same source of truth — adding a new
format now updates one row in one file instead of two. Both
flags use the standard catalog header (magic + version + name
+ entryCount) for catalog formats; asset/world formats are
counted but report 0 entries since their headers differ.

Supports --json variant for tooling integration.
2026-05-09 19:27:48 -07:00
Kelsi
beca69352a feat(pipeline): add WSVK (Wowee Spell Visual Kit) catalog
47th open format — replaces SpellVisualKit.dbc +
SpellVisualEffectName.dbc plus the AzerothCore-style spell
visual SQL data. Defines per-spell visual presentations:
cast-bar effect model, projectile model + travel speed +
arc gravity, impact effect model, hand effect on the caster,
and the animations + sounds that fire at cast / channel /
impact time.

Cross-references with prior formats — castAnimId / impactAnimId
/ precastAnimId point at WANI.animationId, castSoundId /
impactSoundId point at WSND.soundId. Spell catalogs (WSPL)
will reference visualKitId here to bind "what mechanically
happens" to "what plays visually."

CLI: --gen-svk (3-kit Frostbolt/Fireball/HealingTouch starter
showing projectile + AoE + heal patterns), --gen-svk-combat
(5 melee/ranged with WANI animation refs), --gen-svk-utility
(4 portal/hearth/mount/resurrect with no projectile),
--info-wsvk, --validate-wsvk with --json variants. Validator
catches id=0/duplicates, missing name, negative speeds/radii,
projectile-model + speed coherence (model without speed =
never travels; speed without model = invisible), and a
no-effect catch-all (no models + no anims + no sounds).
2026-05-09 19:23:36 -07:00
Kelsi
dadf72307c feat(pipeline): add WANI (Wowee Animation) catalog
46th open format — replaces AnimationData.dbc plus the
hard-coded animation-id tables in M2 model loaders. Defines
named animations (Stand, Walk, Run, Cast, Death, MountIdle,
Fly, ...) with fallback chains, behavior tier (default /
mounted / sitting / aerial / swimming), and weapon-flag
bitmasks that select the correct animation variant when the
model wields 1H / 2H / dual / bow / rifle / wand / etc.

Cross-references with prior formats — fallbackId resolves
within the same WANI catalog (graceful degradation when the
requested animation is absent: Run falls back to Walk,
Attack2H falls back to Attack1H).

10 weapon-flag constants + 6 behavior flags (Looped,
BlendableCycle, Interruptable, MovementSync, OneShot,
PreserveAtEnd). 5 behavior tiers. CLI: --gen-animations
(5 essentials), --gen-animations-combat (8 weapon-typed
attacks + parry + channel), --gen-animations-movement (6
locomotion anims with tier transitions). Validator catches
id-uniqueness, fallback-self-loop, looped-without-duration,
mutually-exclusive Looped+OneShot flags, weaponFlags=0
warning, and unresolved fallback warnings.

Also extends --list-formats and --info-magic with WANI.
2026-05-09 19:19:13 -07:00
Kelsi
cdfb55c477 feat(editor): add --info-magic auto-detect inspector
Reads the first 4 bytes of any file, looks the magic up in
the format table, and reports: format name, file extension,
category, plus the standard catalog header fields (version,
catalog name, entry count) for any of the 33 catalog formats
that share the magic+version+name+entryCount layout.

Also suggests the matching --info-* flag so users who receive
.w* files without context can route to the right inspector
in one step. World/asset formats (WOM/WOB/WHM/WOT/WOW) are
recognized by magic but the catalog-style header probe is
skipped (their layouts differ).

Returns exit 1 + 'unrecognized' message on non-Wowee files.
Supports --json variant for tooling integration.
2026-05-09 19:16:26 -07:00
Kelsi
56ff41799f feat(editor): add --list-formats catalog discoverability flag
New top-level CLI flag prints a table of every novel open
format the project ships: 4-char binary magic, file extension,
category label, the proprietary file(s) it replaces, and a
one-line description. 44 formats total covering 5 world/asset
foundations (.wom / .wob / .whm / .wot / .wow) and 39 catalog
DBC/SQL replacements.

Also exposes formats not previously surfaced via --gen-* flags
(WFAC factions, WLCK locks, WSKL skills, WOLA outdoor light,
WOWA weather, WMPX world map) — these are loaded directly by
the engine. Supports --json variant for tooling integration.
2026-05-09 19:14:55 -07:00
Kelsi
fb07b276f2 feat(pipeline): add WLIQ (Wowee Liquid Type) catalog
45th open format — replaces LiquidType.dbc plus the
AzerothCore-style terrain liquid descriptor data. Defines
liquid materials used by terrain MCNK liquid layers, WMO
interior pools, and procedurally generated fluid bodies in
custom zones. Each liquid pairs a render material (shader +
texture array + flow vectors + fog color) with gameplay data
(damage spell, raw DPS, ambient + splash audio cross-refs).

Cross-references with prior formats — ambientSoundId and
splashSoundId point at WSND.soundId, damageSpellId points at
WSPL.spellId.

10 liquid kinds (Water / Magma / Slime / OceanSalt / FelFire /
HolyLight / TarOil / AcidBog / FrozenWater / UnderworldGoo)
covering both natural and magical fluids. Per-liquid: viscosity
(0=water, 1=slime), flow direction+speed (radians+units/sec),
fog density+RGB, packed minimap RGBA color.

CLI: --gen-liquids (3-entry classic Water/Lava/Slime starter),
--gen-liquids-magical (4 magical pools incl. fel/holy/cosmic),
--gen-liquids-hazardous (3 high-damage liquids with WSPL DoT
cross-refs), --info-wliq, --validate-wliq with --json variants.
Validator catches id=0/duplicates, missing shader/material,
kind out of range, fog/viscosity outside 0..1, hazardous-kind-
without-damage warning, and Water/OceanSalt-with-damage warning
to flag accidental misconfiguration.
2026-05-09 19:10:03 -07:00
Kelsi
2666b976c9 feat(pipeline): add WHOL (Wowee Holiday) catalog
44th open format — replaces Holidays.dbc + HolidayDescriptions.dbc
+ HolidayNames.dbc plus the AzerothCore-style game_event SQL
tables. Defines time-gated world events: seasonal holidays
(Hallow's End / Brewfest / Winter Veil), weekly call-to-arms BG
bonuses, world-PvP windows (Wintergrasp), one-shot specials, and
recurring daily / weekly resets. Each holiday has a recurrence
rule (Annual / Monthly / WeeklyRecur / OneTime), a calendar
window (startMonth + startDay + durationHours), and optional
cross-refs to a feature creature, an intro quest, and a token /
item reward issued during the window.

Cross-references with prior formats — holidayQuestId points at
WQT.questId, bossCreatureId points at WCRT.creatureId,
itemRewardId points at WIT.itemId, and areaIdGate / mapIdGate
point at WMS.areaId / WMS.mapId.

CLI: --gen-holidays (3 seasonal starter), --gen-holidays-weekly
(3 weekly BG call-to-arms windows), --gen-holidays-special (3
world-PvP / lunar / children events), --info-whol, --validate-whol
with --json variants. Validator catches id=0/duplicates, kind /
recurrence out of range, durationHours=0, invalid month/day for
non-weekly recurrence, and calendar-only events (no quest +
boss + reward) as a warning.
2026-05-09 19:05:33 -07:00
Kelsi
dcbc9706f2 feat(pipeline): add WVHC (Wowee Vehicle) catalog
43rd open format — replaces Vehicle.dbc + VehicleSeat.dbc plus
the AzerothCore-style vehicle_template SQL tables. Defines
drivable vehicles: tanks, demolishers, motorcycles, gryphons,
choppers, siege weapons, multi-passenger transports. Each entry
pairs a creature template (the rendered model) with a fixed
seat layout — driver / passenger / gunner seats with their own
attachment points, control flags (kSeatDriver / kSeatGunner /
kSeatPassenger / kSeatHidesPlayer / kSeatNoEjectByCC), and
per-seat abilities mounted to the action bar.

Cross-references with prior formats — creatureId points at
WCRT.creatureId (the rendered model), flightCapabilityId points
at WMNT.mountId for shared fly-speed tables, and per-seat
controlSpellId / exitSpellId point at WSPL.spellId.

CLI: --gen-vehicles (3-vehicle starter chopper/wind-rider/tank),
--gen-vehicles-siege (3 siege weapons with control spellIds),
--gen-vehicles-flying (3 flying mounts cross-ref WMNT
flightCapabilityIds), --info-wvhc, --validate-wvhc with --json
variants. Validator catches id=0/duplicates, missing creature,
enum out-of-range, empty seat list, flying-vehicle on wrong
movement (would fall through world), driver-flag exclusivity
(0 or >1 drivers), and duplicate seatIndex within a vehicle.
2026-05-09 18:59:49 -07:00
Kelsi
92327fc0c0 feat(pipeline): add WGLY (Wowee Glyph) catalog
42nd open format — replaces GlyphProperties.dbc + GlyphSlot.dbc
plus the AzerothCore-style glyph_properties SQL table. Defines
the WotLK glyph system: per-class inscribable glyphs that
modify spell behavior. Each entry pairs a glyph item (the
inscriber's craft output) with the spell aura that applies the
modification, tagged with a Major / Minor / Prime slot type and
a classMask of allowed classes.

Cross-references with prior formats — spellId points at
WSPL.spellId (the aura), itemId points at WIT.itemId (the
inscribed item), and classMask bit positions match the WCHC
classId enum (1=Warrior, 2=Paladin, 3=Hunter, etc).

CLI: --gen-glyphs (3-entry per-role starter), --gen-glyphs-warrior
(6-entry full warrior allotment), --gen-glyphs-universal (4
classMask=All utility glyphs), --info-wgly, --validate-wgly with
--json variants. Validator catches id=0/duplicates, empty name,
spellId=0 (glyph applies no aura), classMask=0 (no class can
inscribe), itemId=0 warning, requiredLevel<25 warning (below
WotLK glyph threshold), and glyphType out-of-range.
2026-05-09 18:55:22 -07:00
Kelsi
0be9bf86db feat(pipeline): add WCMS (Wowee Cinematic) catalog
41st open format — replaces Movie.dbc / CinematicCamera.dbc /
CinematicSequences.dbc plus the AzerothCore cinematic_camera SQL
table. Defines pre-rendered videos, in-engine camera flythroughs,
text crawls, and still images, each with a media path, duration,
skippable flag, and a polymorphic trigger that fires on quest
events / class first-login / zone entry / dungeon clear /
achievements / level milestones.

Cross-references with prior formats — triggerTargetId resolves
by triggerKind to WQT.questId / WMS.areaId / WMS.mapId /
WCHC.classId / WACH.achievementId, and soundtrackId points at
WSND.soundId.

CLI: --gen-cinematics (3-entry starter), --gen-cinematics-intros
(4 class intros), --gen-cinematics-quests (3 quest-bound
cinematics referencing demo questIds 1/100/102), --info-wcms,
--validate-wcms with --json variants. Validator catches
id=0/duplicates, empty name/mediaPath, kind/trigger out of
range, missing target id for non-Manual/Login/LevelUp triggers,
zero-duration entries, and non-skippable pre-rendered videos.
2026-05-09 18:50:43 -07:00
Kelsi
af214d8b34 feat(pipeline): add WCHN (Wowee Chat Channel) catalog
Novel open replacement for Blizzard's ChatChannels.dbc +
the AzerothCore-style chat_channel SQL tables. The 40th
open format added to the editor.

Defines the world chat channel system: General, Trade,
LookingForGroup, GuildRecruitment, LocalDefense, plus
per-zone area channels and custom user-created channels.
Each channel has access rules (faction / level), join
behavior (auto vs opt-in), broadcast policy (announce /
moderated), and optional area / map gating that auto-joins
or auto-leaves the channel as the player moves.

Cross-references with previously-added formats:
  WCHN.entry.areaIdGate -> WMS.area.areaId
                           (channel auto-attaches in this area)
  WCHN.entry.mapIdGate  -> WMS.map.mapId
                           (channel auto-attaches on this map)

Format:
  • magic "WCHN", version 1, little-endian
  • per channel: channelId / name / description /
    channelType / factionAccess / autoJoin / announce /
    moderated / minLevel / areaIdGate / mapIdGate

Enums:
  • ChannelType (10): AreaLocal / Zone / Continent / World /
                      Trade / LookingForGroup / GuildRecruit /
                      LocalDefense / Custom / Pvp
  • FactionAccess (3): Alliance / Horde / Both

API: WoweeChannelLoader::save / load / exists / findById.

Three preset emitters:
  • makeStarter   — 4 stock channels (General Zone +
                     Trade + LFG + GuildRecruit) with
                     default autoJoin policies
  • makeCity      — 5 city-specific channels (3 Stormwind +
                     2 Orgrimmar) with mapId / areaId gates
                     so they auto-attach on entry
  • makeModerated — 3 moderated / restricted channels
                     (LocalDefense level 10+, WorldDefense
                     moderated, RaidCoordination level 60+)

CLI added (5 flags, 677 documented total now):
  --gen-channels / --gen-channels-city / --gen-channels-moderated
  --info-wchn / --validate-wchn

Validator catches: channelId=0 + duplicates, empty name,
unknown channelType / factionAccess, world / continent
channel with area or map gate (gate is silently ignored at
runtime — usually a typo), minLevel=0 (no level gate at all).
2026-05-09 18:43:26 -07:00
Kelsi
ab72380ee0 feat(pipeline): add WAUC (Wowee Auction House) catalog
Novel open replacement for Blizzard's AuctionHouse.dbc +
the AzerothCore-style auctionhouse / auctionhousebot SQL
tables. The 39th open format added to the editor.

Defines per-house rules for the auction system: faction
access, deposit rate (basis points of buyout price), house
cut on successful sale, three listing duration tiers with
per-tier deposit multipliers, disallowed item-class bitmask,
and the auctioneer NPC.

Cross-references with previously-added formats:
  WAUC.entry.auctioneerNpcId   -> WCRT.entry.creatureId
                                   (Auctioneer-flagged NPC)
  WAUC.entry.disallowedClassMask
                                  bitmask of WIT.Class values
                                  that may not be auctioned at
                                  this house

The faction-pair preset captures the canonical asymmetry:
faction houses charge 5% on a successful sale while neutral
houses charge 15% — the cross-faction tax that makes
neutral AHs profitable for goblins.

Format:
  • magic "WAUC", version 1, little-endian
  • per house: houseId / auctioneerNpcId / name /
    factionAccess / baseDepositRateBp / houseCutRateBp /
    maxBidCopper / 3 duration hours + 3 deposit multipliers /
    disallowedClassMask

Enums:
  • FactionAccess (4): Alliance / Horde / Neutral / Both
  • Rates use basis points: 10000 = 100%

API: WoweeAuctionLoader::save / load / exists / findById.

Three preset emitters showcase typical auction setups:
  • makeStarter        — 1 neutral house with default 12h /
                          24h / 48h tiers
  • makeFactionPair    — 3 houses (Stormwind / Orgrimmar /
                          Booty Bay) with auctioneer NPC IDs
                          + canonical faction-vs-neutral cut
                          rates
  • makeRestricted     — 1 house disallowing Containers (1) +
                          Quest items (12) + Keys (13) with
                          tighter durations + 1000g bid cap

CLI added (5 flags, 670 documented total now):
  --gen-auction / --gen-auction-pair / --gen-auction-restricted
  --info-wauc / --validate-wauc

Validator catches: houseId=0 + duplicates, empty name,
factionAccess out of range, duration tier=0, durations not
in short<=medium<=long order, houseCutRateBp >= 100% (seller
loses money on a sale), warns on >50% cut.
2026-05-09 18:34:54 -07:00
Kelsi
62e793800c feat(pipeline): add WPET (Wowee Pet System) catalog
Novel open replacement for AzerothCore-style pet_template +
pet_levelstats SQL + the pet-related subsets of
CreatureFamily.dbc + SpellFamilyName.dbc. The 38th open
format added to the editor.

Defines two related kinds of player-controlled NPCs in
one catalog:
  • Pet families  — hunter pet families (Wolf / Cat / Bear /
                     Boar / Raptor / Spider / etc.) with
                     per-family ability sets, base stat
                     multipliers, and diet preferences
  • Warlock minions — Imp / Voidwalker / Succubus /
                       Felhunter / Felguard, each with
                       their own summon spell, creature
                       template, and ability list

Cross-references with previously-added formats:
  WPET.family.familyId          -> WCRT.entry.familyId
                                    (matches creature family)
  WPET.family.abilities.spellId -> WSPL.entry.spellId
  WPET.minion.summonSpellId     -> WSPL.entry.spellId
  WPET.minion.creatureId        -> WCRT.entry.creatureId
                                    (used for stat scaling)
  WPET.minion.abilities.spellId -> WSPL.entry.spellId

The starter preset's familyIds (1=Wolf, 2=Cat) match
WCRT::FamilyId enum values, so a hunter taming a wolf via
WCRT links straight through to WPET ability sets.

Format:
  • magic "WPET", version 1, little-endian
  • families[]: familyId / name / description / icon /
    petType / baseAttackSpeed / damageMultiplier /
    armorMultiplier / dietMask / abilities[]
  • minions[]: minionId / name / summonSpellId / creatureId /
    abilities[] (each: spellId / rank / autocastDefault)

Enums:
  • PetType (3): Cunning / Ferocity / Tenacity
                  (WotLK+ talent tree categorization)
  • DietFlags:   Meat / Fish / Bread / Cheese / Fruit / Fungus

API: WoweePetLoader::save / load / exists +
WoweePet::findFamily / findMinion + dietMaskName helper
that decodes a dietMask into a "meat+fish" string.

Three preset emitters showcase typical pet catalogs:
  • makeStarter — 2 hunter families (Wolf + Cat) with full
                   3-ability sets + 1 warlock Imp
  • makeHunter  — 8 classic hunter families covering all
                   3 petType categories with appropriate
                   diet masks
  • makeWarlock — 5 warlock minions each with summon spell
                   ID and creatureId pointing into WCRT

CLI added (5 flags, 663 documented total now):
  --gen-pets / --gen-pets-hunter / --gen-pets-warlock
  --info-wpet / --validate-wpet

Validator catches: ids=0 + duplicates, empty name, petType
out of range, baseAttackSpeed<=0 (would divide by zero in
DPS calc), dietMask=0 (pet cannot be fed for happiness),
minion missing summonSpellId / creatureId.
2026-05-09 18:27:02 -07:00
Kelsi
f290a0d4a9 feat(pipeline): add WPCD (Wowee Player Condition) format
Novel open replacement for Blizzard's PlayerCondition.dbc +
the AzerothCore-style condition_template SQL tables. The
37th open format added to the editor.

Defines reusable boolean conditions that other formats can
reference for gating: "player has quest X completed",
"player level >= N", "player class is mage", "player has
item Y in inventory", "WSEA event Z is active".

Conditions can be grouped and combined with AND/OR
aggregators on a per-group basis: a quest-giver gossip
option that says "show only to level 60 alliance mages
who completed quest 1234" composes 4 conditions sharing
the same groupId with AND aggregation. The runtime walks
each group, applies the group's aggregator, and returns
the boolean result to the caller.

Cross-references with previously-added formats — the
targetId field has a polymorphic interpretation by kind:
  WPCD.targetId (kind=QuestCompleted/Active) -> WQT.questId
  WPCD.targetId (kind=HasItem)               -> WIT.itemId
  WPCD.targetId (kind=HasSpell)              -> WSPL.spellId
  WPCD.targetId (kind=HasAchievement)        -> WACH.achievementId
  WPCD.targetId (kind=AreaId)                -> WMS.areaId
  WPCD.targetId (kind=EventActive)           -> WSEA.eventId
  WPCD.targetId (kind=HasTitle)              -> WTIT.titleId
  WPCD.targetId (kind=FactionRep)            -> WFAC.factionId
  WPCD.targetId (kind=Class/Race)            -> WCHC class/race id

Future format extensions can reference WPCD.conditionId in
their own gating fields — WTRG triggers gated by player
state, WGSP options visible only when conditions are met,
WMOU summon spells condition-gated by quest progress, etc.

Format:
  • magic "WPCD", version 1, little-endian
  • per condition: conditionId / groupId (0 = standalone) /
    name / description / kind / aggregator / negated /
    targetId / minValue / maxValue

Enums:
  • Kind (17): AlwaysTrue / AlwaysFalse / QuestCompleted /
                QuestActive / HasItem / HasSpell / MinLevel /
                MaxLevel / ClassMatch / RaceMatch /
                FactionRep / HasAchievement / TeamSize /
                GuildLevel / EventActive / AreaId / HasTitle
  • Aggregator (2): And / Or

API: WoweeConditionLoader::save / load / exists / findById.

Three preset emitters showcase typical usage:
  • makeStarter — 4 standalone conditions covering the most
                   common kinds (quest-done / has-item /
                   min-level / class)
  • makeGated   — 5 conditions in 2 groups demonstrating
                   AND-aggregation (alliance + mage + lvl 60)
                   and OR-aggregation (did quest 1 OR quest 100)
  • makeEvent   — 3 event-gated conditions cross-referencing
                   WSEA event IDs (Hallow's End / Brewfest /
                   Winter's Veil)

CLI added (5 flags, 656 documented total now):
  --gen-conditions / --gen-conditions-gated / --gen-conditions-event
  --info-wpcd / --validate-wpcd

Validator catches: conditionId=0 + duplicates, kind /
aggregator out of range, kinds requiring targetId having
target=0 (skips AlwaysTrue/False, MinLevel/MaxLevel,
TeamSize, GuildLevel which use min/max instead), TeamSize
with min > max.
2026-05-09 18:18:27 -07:00