4.9 KiB
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 — 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(<integer>) 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:
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 uses the standard WotLK 8-arg signature
CoA 3.3.5 fires COMBAT_LOG_EVENT_UNFILTERED with the plain WotLK layout —
no hideCaster, no sourceRaidFlags/destRaidFlags (those are
Cataclysm+):
(event, timestamp, subevent,
srcGUID, srcName, srcFlags,
destGUID, destName, destFlags,
spellId, spellName, spellSchool, …)
destFlags is arg 9, not arg 11. Do NOT insert the modern
hideCaster/RaidFlags params — doing so shifts everything right, so a
GUID slot receives a flags number and destGUID:sub(...) blows up.
This bit us once: the modern layout was wrongly applied to coa-dbm
(UNIT_DIED crash) and coa-quartz and had to be reverted. If an upstream
addon's handler reads (event, ts, subevent, hideCaster, …), change it
back to the 8-arg form for CoA.
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 <repo>/<AddonFolder>/<AddonFolder>.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 <Folder>/<Folder>.toc pairs
automatically.
Tagging convention
<upstream>-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/<repo>/releases/tag/<tag>.
See coa.exil.es/coa/dev/releases for the full release pipeline doc.