Skip to content

Developer & Technical Documentation

Joe edited this page Aug 5, 2026 · 4 revisions

Technical reference for working on Epithet itself. For translation-specific details, see Locales and Translations — this page covers everything else.

Architecture

Epithet/
├── Epithet.toc              # Addon manifest and load order
├── Core/
│   ├── Epithet.lua          # Bootstrap, DB defaults, slash commands, minimap button, event wiring
│   ├── Theme.lua            # Shared theme helpers, palette, bundled-font locale list
│   ├── TitleData.lua        # Live title scan and static-data bridge
│   ├── Filters.lua          # Filtering, sorting, and display list logic
│   ├── Settings.lua         # Blizzard Options panel
│   ├── SocialLayer.lua      # Target-frame title spotting overlay (nameplate hover, drag/lock, fade)
│   ├── SocialLayouts.lua    # Social layout registry
│   ├── SocialLayouts/
│   │   ├── classic.lua      # "Slimline" layout
│   │   └── portrait.lua     # "Portrait Card" layout
│   └── WhatsNew.lua         # What's New popup runtime (markdown-like renderer)
├── UI/
│   ├── MainFrame.xml/.lua   # Main window layout + controller
│   ├── TitleList.lua        # Virtualised title list
│   ├── Sidebar.lua          # Filter sidebar
│   └── Detail.lua           # Title detail panel
├── Spotting/
│   ├── TitleIndex.lua       # Runtime title fragment index
│   ├── Capture.lua          # Spot capture and debounce logic
│   ├── Achievements.lua     # Epithet Achievements system (registry, alerts, progress)
│   ├── Log.lua              # Spot log persistence and import/export
│   └── LogbookUI.lua        # Spotting log and achievements UI
├── WhatsNew/
│   ├── Content.lua          # Registry init
│   └── Versions/vX_Y_Z.lua  # One file per version's changelog content
├── Locales/
│   ├── LocaleManager.lua    # Locale registry, ns.L proxy, resolution API — see the locales page
│   ├── enGB.lua             # English base (also serves enUS)
│   ├── ruRU.lua
│   └── frFR.lua
├── data/                    # Gitignored: collector-generated TitlesDB.*.lua + schema.json
├── icons/, Fonts/, logo/    # Art assets (category/rarity/UI icons, bundled Unicode fonts)
├── libs/                    # Embedded Ace3 + LibDataBroker/LibDBIcon
├── docs/                    # Deep-dive docs: release notes, localization guide, What's New internals
└── scripts/                 # Build, link, fetch-libs, and validation scripts

WoW API Limitations

The World of Warcraft API for titles is quite limited:

Function Signature Notes
GetNumTitles() numTitles = GetNumTitles() Returns the highest title ID — IDs are sparse, gaps exist.
GetTitleName(titleId) name, playerTitle = GetTitleName(titleId) A trailing space in name means prefix; otherwise it's a suffix.
IsTitleKnown(titleId) isKnown = IsTitleKnown(titleId) Whether the character has earned it.
GetCurrentTitle() currentTitle = GetCurrentTitle() Active title ID (0 = none).
SetCurrentTitle(titleId) SetCurrentTitle(titleId) Protected — must originate from a hardware event (button click).

The API does not provide rarity, source, or expansion information — that's why Epithet joins the live scan against a curated static database (data/TitlesDB.enGB.lua). See Title Data Generation below.

Build, Link, Fetch, and Validate Scripts

All scripts live under scripts/, grouped by purpose:

  • scripts/link/retail/link-addon.ps1 / unlink-addon.ps1 — symlinks the repo into your live-client Interface/AddOns for iterative testing; the unlink script removes it.
  • scripts/link/dist-ptr/ and scripts/link/dist-retail/ — equivalent link/unlink pairs for testing a built distribution package (rather than the raw source tree) against PTR or retail clients.
  • scripts/fetch/fetch-libs.ps1 — downloads the Ace3 / LibDataBroker / LibDBIcon libraries into libs/.
  • scripts/build/build.ps1 — packages the addon for distribution into dist/.
  • scripts/validate/validate-locales.ps1 — lints the UI-string locale files (Locales/*.lua) for coverage, orphan keys, and unsupported escape sequences.
  • scripts/validate/validate-titlesdb-locales.ps1 — the same, for the title-database locale overlays (data/TitlesDB.*.lua).

Both validators exit non-zero on error, so they can gate CI.

Title Data Generation

Because the in-game API lacks title sources and rarity, Epithet joins the live scan against a static database that's generated outside this repo by a sibling collector tool (TitlesDBCollector). data/ is gitignored — the bundled TitlesDB.enGB.lua (and any locale overlays) are collector output, not hand-edited here.

The collector's tools/schema.json and this repo's expectations form a shared contract: the field list and output shape must stay in sync on both sides, which is why scripts/validate/validate-titlesdb-locales.ps1 exists as a safety net. If you spot a missing title, wrong rarity, or an obtainability change, don't hand-edit the data file — raise an issue using the appropriate template instead so it gets fixed at the source.

What's New Popup System

Per-version release notes are markdown-like content files in WhatsNew/Versions/, rendered by a small custom parser in Core/WhatsNew.lua (headings, bold/emphasis, bullet lists, and images — no SimpleHTML involved, since it turned out to be too fragile for free-form content). title/body fields can be a plain string or a table keyed by locale, resolved by WhatsNew:LocalizeField against the game client's own GetLocale(). See docs/WHATS_NEW_FEATURE.md in the repo for the full internals, content-format reference, and troubleshooting checklist.

Saved Variables

User settings are saved using AceDB-3.0 under EpithetDB, with defaults defined in Core/Epithet.lua (DB_DEFAULTS):

  • global.locale — account-wide language override ("auto" follows the game client; otherwise a locale code like "ruRU").
  • profile.filters — current selections for search, status, rarity, type, expansion, category, kind, faction, plus the hide-unobtainable / hide-time-sensitive / favourites-only toggles.
  • profile.favourites — a set of favourited titles, keyed by lowercase title text.
  • profile.sort — active sort mode (collectedFirst, expansion, alphabetical, quality, category).
  • profile.obtainableOnly — whether the collected-percentage counter is scoped to the obtainable pool only.
  • profile.social — Title Spotting configuration: enabled state, layout (classic/portrait), animated portrait, nameplate fade (enabled + duration), spotting/achievement chat notifications, achievement notification mode, achievement popup anchor (uiparent/alertframe), Spotting Log scope/view, hide-in-combat / hide-in-group, and the overlay's saved drag position.
  • profile.framePoint, profile.scale — main window position and scale.
  • profile.minimap — minimap button visibility.

Core/Epithet.lua:OnInitialize also normalizes a handful of these on load (e.g. clamping achievementAlertAnchor to a known value), so a corrupted or stale saved profile self-heals rather than erroring.

Dependencies

  • Ace3 (AceAddon-3.0, AceDB-3.0, CallbackHandler-1.0) — BSD licensed.
  • LibDataBroker-1.1 and LibDBIcon-1.0 — power the minimap launcher button.

All dependencies are OSI-approved and embedded under libs/ (fetch with scripts/fetch/fetch-libs.ps1 if building from source).