feat(pipeline): add WACH (Wowee Achievement Catalog) format

Novel open replacement for Blizzard's Achievement.dbc +
AchievementCriteria.dbc + AchievementCategory.dbc + the
AzerothCore-style character_achievement /
character_achievement_progress SQL tables. The 21st open
format added to the editor.

Each achievement carries display metadata (name, description,
icon, points, faction restriction) plus a list of criteria
the player must satisfy. Criteria mirror the WQT objective
model (kind + targetId + quantity), so the runtime can
reuse the same progress-tracking machinery for both quests
and achievements.

Cross-references with previously-added formats — every
criterion kind has a real format target:
  WACH.criteria.targetId (kind=KillCreature)    -> WCRT.creatureId
  WACH.criteria.targetId (kind=CompleteQuest)   -> WQT.questId
  WACH.criteria.targetId (kind=LootItem)        -> WIT.itemId
  WACH.criteria.targetId (kind=CastSpell)       -> WSPL.spellId
  WACH.criteria.targetId (kind=ReachSkillLevel) -> WSKL.skillId
  WACH.criteria.targetId (kind=EarnReputation)  -> WFAC.factionId
  WACH.criteria.targetId (kind=CompleteAchievement) -> WACH.achievementId
                                                       (meta-achievements)

Format:
  • magic "WACH", version 1, little-endian
  • per achievement: id / categoryId / name / description /
    iconPath / titleReward / points / minLevel / faction /
    flags / criteria[]
  • per criterion: criteriaId / kind / targetId / quantity /
    description

Enums:
  • CriteriaKind (9): KillCreature / CompleteQuest / LootItem /
                      ReachLevel / EarnReputation / CastSpell /
                      ReachSkillLevel / VisitArea /
                      CompleteAchievement
  • Faction:    Both / Alliance / Horde
  • Flags:      HiddenUntilEarned / ServerFirst / RealmFirst /
                 Tracking / Counter / Account

API: WoweeAchievementLoader::save / load / exists /
findById; presets makeStarter (3 simple kill/quest/level
demos), makeBandit (3 with WCRT/WGOT/WQT cross-refs),
makeMeta (3 base + 1 meta-achievement granting "the
Versatile" title, exercising CompleteAchievement criterion
kind that lets achievements depend on other achievements).

CLI added (5 flags, 542 documented total now):
  --gen-achievements / --gen-achievements-bandit / --gen-achievements-meta
  --info-wach / --validate-wach

Validator catches: achievementId=0 + duplicates, empty name,
faction out of range, no criteria (achievement can never
be earned), criterion quantity=0, unknown criterion kind,
targetId=0 on criterion kinds that need a real resource
reference (everything except ReachLevel which uses the
quantity field for the level number).

The bandit preset's cross-references close the gameplay
graph end-to-end: kill 50 creatureId=1000 (matches WCRT/
WSPN/WLOT bandit), loot objectId=2000 (matches WGOT bandit
strongbox), complete questId=1 (matches WQT Bandit Trouble).
The meta preset closes a separate loop: 3 sub-achievements
covering Mining (skillId=186), Lockpicking (skillId=633),
and Frostbolt cast count (spellId=116) — each pointing at
a real WSKL/WSPL entry that already exists in the demo
content stack.
This commit is contained in:
Kelsi 2026-05-09 16:04:30 -07:00
parent f4f9804000
commit e5eaf13866
8 changed files with 763 additions and 0 deletions

View file

@ -989,6 +989,16 @@ void printUsage(const char* argv0) {
std::printf(" Print WSPL spell entries (id / school / effect / cast/cd / mana / range / damage range / name)\n");
std::printf(" --validate-wspl <wspl-base> [--json]\n");
std::printf(" Static checks: spellId>0+unique, name not empty, school 0..6, range/value min<=max, friendly+hostile incoherent\n");
std::printf(" --gen-achievements <wach-base> [name]\n");
std::printf(" Emit .wach starter: 3 achievements (First Blood / Helping Hand / Coming of Age)\n");
std::printf(" --gen-achievements-bandit <wach-base> [name]\n");
std::printf(" Emit .wach bandit-themed: 3 achievements with cross-refs to WCRT/WGOT/WQT bandit IDs\n");
std::printf(" --gen-achievements-meta <wach-base> [name]\n");
std::printf(" Emit .wach 3 base achievements + 1 meta-achievement (Jack of All Trades, title 'the Versatile')\n");
std::printf(" --info-wach <wach-base> [--json]\n");
std::printf(" Print WACH entries (id / points / faction / flags / criteria with kind+target+qty)\n");
std::printf(" --validate-wach <wach-base> [--json]\n");
std::printf(" Static checks: id>0+unique, name not empty, faction 0..2, criteria need targetId+quantity>0\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");