# Porting addons to CoA / Project Ascension 3.3.5 The CoA Beta client is WoW 3.3.5 with a heavily reworked FrameXML / SharedXML / StaticPopup / Settings system, 21 custom playable classes, and selectively-modern globals (`C_Timer.After`, `C_ClassInfo`). Most upstream retail / Classic / Wrath addons need a small bundle of fixes. This document lists every recurring failure mode we've seen across the existing 25 Exiles forks plus the matching one-paragraph fix. Keep this file in your fork until you're done porting; once everything loads cleanly you can leave it as documentation or delete it. The canonical / live version of this checklist is at [coa.exil.es/coa/dev/addons](https://coa.exil.es/coa/dev/addons) — if you discover a new failure mode while porting, please add it there. ## Bug-pattern checklist ### Retail-only globals are nil `InterfaceOptionsFrame*`, `InterfaceOptions_AddCategory`, `InterfaceOptionsFramePanelContainer`, `Settings.*`, `Enum.ClassMask` (only knows vanilla classes), retail `C_TooltipInfo`. Guard with `if X then … end` or fall back to a sensible default (`UIParent` for parent-frame fallbacks). ### FileDataIDs silently no-op `Set*Texture()` does nothing on 3.3.5 — textures render as red placeholders. Use string paths. The comment next to an FDID call in upstream code usually already names the path. ### Hardcoded class lists miss CoA's 21 custom classes `SHAMAN/HERO` masks, `CLASS_SORT_ORDER` iteration, `RAID_CLASS_COLORS` direct keys, `CLASS_ICON_TCOORDS`. Witchdoctor / Templar / Sun Cleric / Primalist / Tinker / etc. won't appear. Extend via `GetNumClasses()`, `LOCALIZED_CLASS_NAMES_MALE` fallback, or a class-keyed `or { … }` guard. ### `C_ClassInfo.GetSpecInfo(class, spec)` arg mismatch `GetAllSpecs(class)` returns non-string items on this client. Always `pcall` the `GetSpecInfo` / `GetSpecInfoByID` call and skip iterations that fail. ### `StaticPopup_Show` during `PLAYER_LOGIN` silently fails Fires too early on this client. Defer with `C_Timer.After(0, …)`. Failure mode is silent — the popup never appears and any code that depends on user confirmation (e.g. WeakAuras' downgrade-repair flow) never runs. ### `.tga` textures don't load The engine only loads `.blp`. Ship BLP2 / DXT3 (`alphaEncoding = 1`) — DXT5 (`ae=7`) does NOT decode on 3.3.5. Conversion: ```sh blp-conv --blp-version blp2 --blp-format dxt3 --alpha-bits 8 in.png out.blp ``` ### `Minimap:SetMaskTexture("Interface\\BUTTONS\\WHITE8X8")` silently rounds The shared white mask used by retail SexyMap-style addons falls back to the round minimap on CoA. Bundle an opaque BLP and point the mask at it instead. ### `UnitClass("player")` at file-load time returns nil Resolve class inside `OnEnable` / event handler, not as a file-level `local`. ### CLEU argument positions changed Verify against the 3.3.5 signature: ``` (event, timestamp, subevent, hideCaster, srcGUID, srcName, srcFlags, srcRaidFlags, destGUID, destName, destFlags, destRaidFlags, spellId, spellName, spellSchool, …) ``` `destFlags` is arg 11, not arg 9. Many retail-era addons get this wrong. ## Ace3 specifics If the addon embeds Ace3 libs (`Libs/AceXxx-3.0/`), use the canonical `Exiles/coa-ace3` bundle to overwrite them. The sweep script in that repo handles every fork in one pass — see its README. Don't ship a bespoke Ace3 vendor; mismatched MINOR versions across loaded addons cause silent breakage at LibStub resolution time. `coa-elvui` is the one exception — ElvUI ships its own customized Ace3 stack and is excluded from the sweep. ## Standard layout The Exiles fork-layout convention is `//.toc` at depth-1, with dev tooling (`tools/`, `.gitea/`, `README.md`, `LICENSE`, `PORTING.md`) at the repo root. Multi-addon repos place each addon in its own sibling folder. `tools/build_zip.sh` discovers these `/.toc` pairs automatically. ## Tagging convention `-coa.N` per repo. Examples: | Repo | Tag | |---|---| | `coa-decursive` | `Asc-1.1.6-coa.1` | | `coa-leatrix-plus` | `3.3.5-coa.1` | | `coa-ace3` | `52e5f2c-coa.1` (upstream commit pin) | | `coa-dbm` | `2026.05.25-coa.1` (no `## Version:` line; date-based) | The trailing `-coa.N` counter bumps for each CoA-fork iteration. Pushing the tag fires the release workflow and publishes the per-addon zips to `https://git.sub-net.at/Exiles//releases/tag/`. See [coa.exil.es/coa/dev/releases](https://coa.exil.es/coa/dev/releases) for the full release pipeline doc.