coa.10: CoA reputation factions (data-driven) + custom-class icons + all-professions Skills
release / release (push) Successful in 5s

- Reputation view rebuilt data-driven from each char's scanned factions grouped
  by in-game category; CoA custom factions (and future ones) appear automatically.
  Old hardcoded tree kept only as an icon lookup.
- CoA custom-class icons (classes 12-32) render from bundled atlas
  Altoholic/images/coa-classes.blp (texcoords from coa-details) instead of the
  Warrior glue-icon fallback in ShowClassIcons.
- Skills tab shows ALL known professions (dynamic list incl Woodcutting/Woodworking),
  not 2 fixed slots; DataStore_Skills scans on PLAYER_ENTERING_WORLD/SKILL_LINES_CHANGED
  (fixes 'no profession data' that only scanned on ghost-release).
This commit is contained in:
2026-05-29 15:55:25 +02:00
parent ec868716ed
commit 0565051302
15 changed files with 428 additions and 177 deletions
+64 -2
View File
@@ -7,7 +7,7 @@ if not DataStore then return end
local addonName = "DataStore_Skills"
_G[addonName] = LibStub("AceAddon-3.0"):NewAddon(addonName, "AceConsole-3.0", "AceEvent-3.0")
_G[addonName] = LibStub("AceAddon-3.0"):NewAddon(addonName, "AceConsole-3.0", "AceEvent-3.0", "AceTimer-3.0")
local addon = _G[addonName]
@@ -35,6 +35,44 @@ local function _GetPrimaryProfessions(character)
return character.Skills[L["Professions"]]
end
-- CoA: a character can know ALL professions at once (no retail 2-primary limit),
-- and the two custom professions Woodcutting/Woodworking may sit under a different
-- skill-window header. To render "all professions" reliably we don't trust the
-- "Professions" category header alone: we collect every known crafting/gathering
-- profession by name across all categories. English skill names are the keys; on
-- non-English clients these names won't match and the list falls back to whatever
-- sits under L["Professions"] via _GetPrimaryProfessions (caller handles that).
local PRIMARY_PROFESSION_NAMES = {
"Alchemy", "Blacksmithing", "Enchanting", "Engineering", "Inscription",
"Jewelcrafting", "Leatherworking", "Tailoring", "Skinning", "Mining",
"Herbalism", "Woodcutting", "Woodworking",
}
-- Returns an ordered array of { name = <skillName>, rank = <n>, maxRank = <n> }
-- for every primary profession the character actually knows. Never returns nil.
local function _GetPrimaryProfessionList(character)
local result = {}
local skills = character.Skills
if not skills then return result end
for _, profName in ipairs(PRIMARY_PROFESSION_NAMES) do
for _, category in pairs(skills) do
local skill = category[profName]
if skill then
local rank, maxRank = strsplit("|", skill)
result[#result + 1] = {
name = profName,
rank = tonumber(rank) or 0,
maxRank = tonumber(maxRank) or 0,
}
break -- found this profession, move to the next name
end
end
end
return result
end
local function _GetSecondaryProfessions(character)
return character.Skills[L["Secondary Skills"]]
end
@@ -95,6 +133,7 @@ end
local PublicMethods = {
GetPrimaryProfessions = _GetPrimaryProfessions,
GetPrimaryProfessionList = _GetPrimaryProfessionList,
GetSecondaryProfessions = _GetSecondaryProfessions,
GetSkillInfo = _GetSkillInfo,
GetSkillInfoByCategory = _GetSkillInfoByCategory,
@@ -111,6 +150,7 @@ function addon:OnInitialize()
DataStore:RegisterModule(addonName, addon, PublicMethods)
DataStore:SetCharacterBasedMethod("GetPrimaryProfessions")
DataStore:SetCharacterBasedMethod("GetPrimaryProfessionList")
DataStore:SetCharacterBasedMethod("GetSecondaryProfessions")
DataStore:SetCharacterBasedMethod("GetSkillInfo")
DataStore:SetCharacterBasedMethod("GetSkillInfoByCategory")
@@ -123,12 +163,20 @@ function addon:OnInitialize()
end
function addon:OnEnable()
-- CoA fix: the old build only scanned in PLAYER_ALIVE while the player was a
-- ghost (see below), so a living character that never died was never scanned
-- and every profession rank rendered as 0 ("Skills shows no data"). We now scan
-- on login and whenever the skill window changes so every character populates.
addon:RegisterEvent("PLAYER_ALIVE")
addon:RegisterEvent("PLAYER_ENTERING_WORLD", "ScanOnLogin")
addon:RegisterEvent("SKILL_LINES_CHANGED", "ScanOnLogin")
addon:RegisterEvent("CHAT_MSG_SKILL")
end
function addon:OnDisable()
addon:UnregisterEvent("PLAYER_ALIVE")
addon:UnregisterEvent("PLAYER_ENTERING_WORLD")
addon:UnregisterEvent("SKILL_LINES_CHANGED")
addon:UnregisterEvent("CHAT_MSG_SKILL")
end
@@ -192,10 +240,24 @@ end
function addon:PLAYER_ALIVE()
-- print("DataStore_Skills.lua") -- DEBUG 2025 07 21
if not UnitIsGhost("player") then return end -- only scan if player released spirit and went to graveyard
ScanSkills()
end
-- CoA fix: scan once shortly after login / when skills change. SKILL_LINES_CHANGED
-- can fire many times in a burst (once per skill line during login), so throttle to
-- a single deferred scan instead of scanning on every event.
local scanScheduled
function addon:ScanOnLogin()
if scanScheduled then return end
scanScheduled = true
-- defer so the skill UI / API is fully populated before we read GetNumSkillLines()
addon:ScheduleTimer(function()
scanScheduled = nil
ScanSkills()
end, 2)
end
-- this turns
-- "Your skill in %s has increased to %d."
-- into