From 166eb1ec5e9401ae5c70491521cfead79e1b855f Mon Sep 17 00:00:00 2001 From: Florian Berthold Date: Sat, 9 May 2026 21:11:09 +0200 Subject: [PATCH] Common.lua: fall back to player's class when entry.Class is missing Ascension's `C_CharacterAdvancement.GetEntryByInternalID` returns the active character's *own* class entries with `Class` empty (the API treats the player's class as implicit), while still returning `Class` populated for every other class. The entry-walk gate `if entry and entry.Class then ...` was therefore silently dropping every talent of whatever class you ran the export on. A Venomancer alt would correctly capture the 41 *other* classes' talents/skills but produce zero rows for Prophet itself, leaving the db.exil.es Venomancer page perpetually missing icons for Rotting Away, Lure, Envenomed Weapons, and friends. Cache UnitClass("player") at the start of C.Run and substitute it for `entry.Class` whenever that field is missing or empty. The bucketing key in `info.cls` now matches the localized class string (consistent with how the other 41 classes show up in CoaExporterCatalog.talents). --- CoaExporter/Catalogs/Common.lua | 47 ++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/CoaExporter/Catalogs/Common.lua b/CoaExporter/Catalogs/Common.lua index dc47e98..6c34f23 100644 --- a/CoaExporter/Catalogs/Common.lua +++ b/CoaExporter/Catalogs/Common.lua @@ -89,7 +89,22 @@ function C.Run(filter, callback) return false end - local ctx = { startedAt = date(), filter = filter or "all" } + -- Ascension's GetEntryByInternalID returns the active character's + -- *own* class entries with `Class` unset (the API treats the player's + -- class as implicit). Cache the player's class so we can substitute + -- it when entry.Class is missing — otherwise an export from a + -- Venomancer alt would correctly capture the 41 *other* classes but + -- silently drop every Venomancer talent at the gate. + local playerLocalizedClass, playerClassFile = UnitClass("player") + playerLocalizedClass = playerLocalizedClass or "Unknown" + playerClassFile = playerClassFile or "UNKNOWN" + + local ctx = { + startedAt = date(), + filter = filter or "all", + playerClass = playerLocalizedClass, + playerClassFile = playerClassFile, + } for _, col in ipairs(collectors) do if col.onStart then col.onStart(ctx) end end @@ -100,7 +115,9 @@ function C.Run(filter, callback) local total = #entryKeys local idx = 1 - log(string.format("scanning %d entries for [%s]", total, ctx.filter)) + log(string.format( + "scanning %d entries for [%s] (active class: %s/%s)", + total, ctx.filter, playerLocalizedClass, playerClassFile)) C._isRunning = true local frame = CreateFrame("Frame") @@ -124,7 +141,16 @@ function C.Run(filter, callback) if id then entry = C_CharacterAdvancement.GetEntryByInternalID(id) end end - if entry and entry.Class then + -- Pre-relax: keep entries whose Class field is missing/empty. + -- They're typically the active character's own class (see the + -- comment near `playerLocalizedClass` above). We bucket them + -- under the player's class string further down. + local entryClass = entry and entry.Class + if entry and (not entryClass or entryClass == "") then + entryClass = playerLocalizedClass + end + + if entry and entryClass and entryClass ~= "" then -- Build a normalized info bag every collector can use. local spellId = 0 local allSpells = {} @@ -150,20 +176,27 @@ function C.Run(filter, callback) local tierVal = tonumber(entry.PositionY) or tonumber(entry.Row) or tonumber(entry.y) or 0 local colVal = tonumber(entry.PositionX) or tonumber(entry.Column) or tonumber(entry.x) or tonumber(entry.Col) or 0 - -- Garbage filter: tier=0/col=0/no-icon AND no-spell entries + local entryIcon = (type(entry.Icon) == "string" and entry.Icon ~= "") and entry.Icon or "" + local hasAnyIcon = (icon and icon ~= "") or entryIcon ~= "" + + -- Garbage filter: drop entries that have no spell/coords AND + -- no icon from either source (GetSpellInfo or entry.Icon). + -- entry.Icon catches spec-root talents whose only identity + -- is a server-resolved icon (e.g. Venomancer/Fortitude root). local valid = true - if tierVal == 0 and colVal == 0 and (not icon or icon == "") then valid = false end - if spellId == 0 and (not icon or icon == "") then valid = false end + if tierVal == 0 and colVal == 0 and not hasAnyIcon then valid = false end + if spellId == 0 and not hasAnyIcon then valid = false end if valid then local info = { - cls = tostring(entry.Class), + cls = tostring(entryClass), tab = tostring(entry.Tab or "General"), entryType = tostring(entry.Type or "Talent"), name = name, spellId = spellId, allSpells = allSpells, icon = icon or "", + entryIcon = entryIcon, tier = tierVal, col = colVal, tooltip = tooltip,