Commit graph

2 commits

Author SHA1 Message Date
Kelsi
89871c171c feat(editor): add WACH JSON round-trip authoring workflow
Closes the WACH open-format loop with --export-wach-json /
--import-wach-json, mirroring the JSON pairs added for
every other novel binary format. All 15 binary formats
added since WOL now have full JSON round-trip authoring.

Each achievement round-trips:
  • 11 scalar fields (id, categoryId, name, description,
    icon, titleReward, points, minLevel, faction, flags)
  • criteria array with full per-criterion fields

Three enum-typed fields emit dual int + name forms so a
hand-author can use either:
  • criterion.kind (kill/quest/loot/level/rep/cast/skill/visit/meta)
  • faction        (both/alliance/horde)
  • flags          (hidden/server-first/realm-first/tracking/...)

Verified byte-identical round-trip on the meta preset (4
achievements, 6 criteria including the 3 CompleteAchievement
criteria that wire the meta-achievement to its prerequisites).

Adds 2 flags (546 documented total now).
2026-05-09 16:07:53 -07:00
Kelsi
e5eaf13866 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.
2026-05-09 16:04:30 -07:00