mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-05-11 03:23:51 +00:00
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.
140 lines
4.9 KiB
C++
140 lines
4.9 KiB
C++
#pragma once
|
||
|
||
#include <cstdint>
|
||
#include <string>
|
||
#include <vector>
|
||
|
||
namespace wowee {
|
||
namespace pipeline {
|
||
|
||
// Wowee Open Achievement Catalog (.wach) — novel 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), which means the runtime
|
||
// can reuse the same progress-tracking machinery for both.
|
||
//
|
||
// Cross-references with previously-added formats:
|
||
// 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.entry.categoryId → WACH.entry.achievementId (for header
|
||
// rows; achievements can be parented
|
||
// to other achievements as headers)
|
||
//
|
||
// Binary layout (little-endian):
|
||
// magic[4] = "WACH"
|
||
// version (uint32) = current 1
|
||
// nameLen + name (catalog label)
|
||
// entryCount (uint32)
|
||
// entries (each):
|
||
// achievementId (uint32)
|
||
// categoryId (uint32)
|
||
// nameLen + name
|
||
// descLen + description
|
||
// iconLen + iconPath
|
||
// titleLen + titleReward
|
||
// points (uint32)
|
||
// minLevel (uint16) / faction (uint8) / criteriaCount (uint8)
|
||
// flags (uint32)
|
||
// criteria (criteriaCount × {
|
||
// criteriaId (uint32)
|
||
// kind (uint8) + pad[3]
|
||
// targetId (uint32)
|
||
// quantity (uint32)
|
||
// descLen + description
|
||
// })
|
||
struct WoweeAchievement {
|
||
enum CriteriaKind : uint8_t {
|
||
KillCreature = 0,
|
||
CompleteQuest = 1,
|
||
LootItem = 2,
|
||
ReachLevel = 3,
|
||
EarnReputation = 4,
|
||
CastSpell = 5,
|
||
ReachSkillLevel = 6,
|
||
VisitArea = 7,
|
||
CompleteAchievement = 8, // meta-achievements
|
||
};
|
||
|
||
enum Faction : uint8_t {
|
||
FactionBoth = 0,
|
||
FactionAlliance = 1,
|
||
FactionHorde = 2,
|
||
};
|
||
|
||
enum Flags : uint32_t {
|
||
HiddenUntilEarned = 0x01, // not shown in panel until completed
|
||
ServerFirst = 0x02, // first-on-server rewards a global tag
|
||
RealmFirst = 0x04,
|
||
Tracking = 0x08, // shows progress UI in the panel
|
||
Counter = 0x10, // counts up forever (Pet Battles wins)
|
||
Account = 0x20, // account-wide, not per-character
|
||
};
|
||
|
||
struct Criterion {
|
||
uint32_t criteriaId = 0;
|
||
uint8_t kind = KillCreature;
|
||
uint32_t targetId = 0;
|
||
uint32_t quantity = 1;
|
||
std::string description;
|
||
};
|
||
|
||
struct Entry {
|
||
uint32_t achievementId = 0;
|
||
uint32_t categoryId = 0; // 0 = top-level
|
||
std::string name;
|
||
std::string description;
|
||
std::string iconPath;
|
||
std::string titleReward; // empty = no title
|
||
uint32_t points = 10;
|
||
uint16_t minLevel = 1;
|
||
uint8_t faction = FactionBoth;
|
||
uint32_t flags = 0;
|
||
std::vector<Criterion> criteria;
|
||
};
|
||
|
||
std::string name;
|
||
std::vector<Entry> entries;
|
||
|
||
bool isValid() const { return !entries.empty(); }
|
||
|
||
// Lookup by achievementId — nullptr if not present.
|
||
const Entry* findById(uint32_t achievementId) const;
|
||
|
||
static const char* criteriaKindName(uint8_t k);
|
||
static const char* factionName(uint8_t f);
|
||
};
|
||
|
||
class WoweeAchievementLoader {
|
||
public:
|
||
static bool save(const WoweeAchievement& cat,
|
||
const std::string& basePath);
|
||
static WoweeAchievement load(const std::string& basePath);
|
||
static bool exists(const std::string& basePath);
|
||
|
||
// Preset emitters used by --gen-achievements* variants.
|
||
//
|
||
// makeStarter — 3 demo achievements covering kill / quest
|
||
// completion / level reached criteria.
|
||
// makeBandit — bandit-themed: "Slay 50 Defias Bandits"
|
||
// + "Loot the Bandit Strongbox" + "Complete
|
||
// Bandit Trouble" — all referencing the
|
||
// WCRT/WGOT/WQT/WIT cross-referenced demo IDs.
|
||
// makeMeta — 3 base achievements + 1 meta-achievement
|
||
// that requires completing the others.
|
||
static WoweeAchievement makeStarter(const std::string& catalogName);
|
||
static WoweeAchievement makeBandit(const std::string& catalogName);
|
||
static WoweeAchievement makeMeta(const std::string& catalogName);
|
||
};
|
||
|
||
} // namespace pipeline
|
||
} // namespace wowee
|