Files
coa-template/PORTING.md
T

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.