coa.10: CoA reputation factions (data-driven) + custom-class icons + all-professions Skills
release / release (push) Successful in 5s
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:
+15
-6
@@ -732,13 +732,22 @@ function Altoholic:ShowClassIcons()
|
||||
end)
|
||||
|
||||
local _, class = DS:GetCharacterClass(character)
|
||||
-- CoA: CLASS_ICON_TCOORDS only carries the vanilla 10 + DK on Voljin.
|
||||
-- For the 21 CoA custom classes the lookup is nil; fall back to
|
||||
-- WARRIOR's coords so we render *something* rather than crashing.
|
||||
local tc = CLASS_ICON_TCOORDS[class] or CLASS_ICON_TCOORDS["WARRIOR"]
|
||||
local itemTexture = _G[itemName .. "IconTexture"]
|
||||
itemTexture:SetTexture("Interface\\Glues\\CharacterCreate\\UI-CharacterCreate-Classes");
|
||||
itemTexture:SetTexCoord(tc[1], tc[2], tc[3], tc[4]);
|
||||
-- CoA: CLASS_ICON_TCOORDS only carries the vanilla 10 + DK on Voljin,
|
||||
-- so the 21 CoA custom classes have no entry. GetCoAClassIcon (defined
|
||||
-- in CoAClassColors.lua) returns the realm-authoritative atlas + coords
|
||||
-- for any CoA-playable class (incl. vanilla 10 + DK); it returns nil for
|
||||
-- an unknown/unscanned (no-value) token, in which case we keep the stock
|
||||
-- CLASS_ICON_TCOORDS path, defaulting to WARRIOR rather than crashing.
|
||||
local coaTex, l, r, t, b = Altoholic:GetCoAClassIcon(class)
|
||||
if coaTex then
|
||||
itemTexture:SetTexture(coaTex);
|
||||
itemTexture:SetTexCoord(l, r, t, b);
|
||||
else
|
||||
local tc = CLASS_ICON_TCOORDS[class] or CLASS_ICON_TCOORDS["WARRIOR"]
|
||||
itemTexture:SetTexture("Interface\\Glues\\CharacterCreate\\UI-CharacterCreate-Classes");
|
||||
itemTexture:SetTexCoord(tc[1], tc[2], tc[3], tc[4]);
|
||||
end
|
||||
itemTexture:SetWidth(36);
|
||||
itemTexture:SetHeight(36);
|
||||
itemTexture:SetAllPoints(itemButton);
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
## Author: Thaoky, Telkar-RG
|
||||
## X-Edited-By: Exiles (Sub-Net) — florian.berthold@sub-net.at
|
||||
## Version: 3.3.002b-coa.9
|
||||
## Version: 3.3.002b-coa.10
|
||||
## X-Category: Inventory, Tradeskill, Mail
|
||||
## X-Localizations: enUS, frFR, zhCN, zhTW, deDE, koKR, esES, esMX, ruRU
|
||||
## X-Website: http://wow.curse.com/downloads/wow-addons/details/altoholic.aspx
|
||||
|
||||
+17
-28
@@ -76,8 +76,6 @@ local function AddRealm(AccountName, RealmName)
|
||||
local realmBankSlots = 0
|
||||
local realmFreeBankSlots = 0
|
||||
|
||||
local SkillsCache = { {name = "", rank = 0}, {name = "", rank = 0} }
|
||||
|
||||
-- 1) Add the realm name
|
||||
table.insert(characterList, { linetype = INFO_REALM_LINE + (realmCount*3),
|
||||
isCollapsed = false,
|
||||
@@ -87,36 +85,27 @@ local function AddRealm(AccountName, RealmName)
|
||||
|
||||
-- 2) Add the characters
|
||||
for characterName, character in pairs(DataStore:GetCharacters(RealmName, AccountName)) do
|
||||
SkillsCache[1].name = ""
|
||||
SkillsCache[1].rank = 0
|
||||
SkillsCache[1].spellID = nil
|
||||
SkillsCache[2].name = ""
|
||||
SkillsCache[2].rank = 0
|
||||
SkillsCache[2].spellID = nil
|
||||
|
||||
local i = 1
|
||||
local professions = DataStore:GetPrimaryProfessions(character)
|
||||
if professions then
|
||||
for SkillName, s in pairs(professions) do
|
||||
SkillsCache[i].name = SkillName
|
||||
SkillsCache[i].rank = DataStore:GetSkillInfo(character, SkillName)
|
||||
SkillsCache[i].spellID = DataStore:GetProfessionSpellID(SkillName)
|
||||
i = i + 1
|
||||
|
||||
if i > 2 then -- it seems that under certain conditions, the loop continues after 2 professions.., so break
|
||||
break
|
||||
end
|
||||
-- CoA: characters can know ALL professions at once (no retail 2-primary
|
||||
-- limit) plus the customs Woodcutting/Woodworking. Build a dynamic list of
|
||||
-- every known primary profession instead of the old fixed 2 slots. Each
|
||||
-- entry carries its own name/rank/spellID(icon) so Skills.lua can render an
|
||||
-- arbitrary number of professions. GetPrimaryProfessionList never returns
|
||||
-- nil (returns {} for unscanned chars), but guard anyway.
|
||||
local professions = {}
|
||||
if DataStore.GetPrimaryProfessionList then
|
||||
local list = DataStore:GetPrimaryProfessionList(character) or {}
|
||||
for _, p in ipairs(list) do
|
||||
professions[#professions + 1] = {
|
||||
name = p.name,
|
||||
rank = p.rank or 0,
|
||||
spellID = DataStore:GetProfessionSpellID(p.name),
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
table.insert(characterList, { linetype = INFO_CHARACTER_LINE + (realmCount*3),
|
||||
key = character,
|
||||
skillName1 = SkillsCache[1].name,
|
||||
skillRank1 = SkillsCache[1].rank,
|
||||
spellID1 = SkillsCache[1].spellID,
|
||||
skillName2 = SkillsCache[2].name,
|
||||
skillRank2 = SkillsCache[2].rank,
|
||||
spellID2 = SkillsCache[2].spellID,
|
||||
professions = professions, -- CoA: dynamic list of all primary professions
|
||||
cooking = DataStore:GetCookingRank(character),
|
||||
firstaid = DataStore:GetFirstAidRank(character),
|
||||
fishing = DataStore:GetFishingRank(character),
|
||||
|
||||
@@ -24,7 +24,8 @@
|
||||
-- Source of truth: db.exil.es /coa/dev for the full palette;
|
||||
-- _G.RAID_CLASS_COLORS at FrameXML load time for the running client.
|
||||
|
||||
local AC = _G.Altoholic and _G.Altoholic.ClassInfo
|
||||
local Alto = _G.Altoholic
|
||||
local AC = Alto and Alto.ClassInfo
|
||||
if type(AC) ~= "table" then return end
|
||||
|
||||
local source = _G.RAID_CLASS_COLORS
|
||||
@@ -45,3 +46,72 @@ for token, color in pairs(source) do
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Class ICONS
|
||||
-- -----------
|
||||
-- WoW's _G.CLASS_ICON_TCOORDS only carries texcoords for the playable
|
||||
-- classes the *client* shipped with — on the CoA Voljin client that is
|
||||
-- the vanilla 10 + DEATHKNIGHT only. The 21 CoA custom classes
|
||||
-- (BARBARIAN, WITCHDOCTOR, CHRONOMANCER, …) have no entry, so any draw
|
||||
-- site that does `CLASS_ICON_TCOORDS[class]` falls back to a wrong or
|
||||
-- blank icon (Altoholic.lua:ShowClassIcons hit this).
|
||||
--
|
||||
-- The realm-authoritative class-icon atlas is the 512x512 (8x8 grid of
|
||||
-- 64px cells) BLP that the CoA Details! fork bundles and renders for
|
||||
-- all 32 classes. We ship a copy of that atlas as
|
||||
-- Interface\AddOns\Altoholic\images\coa-classes.blp and reproduce its
|
||||
-- per-token texcoords below (source: Details/functions/profiles.lua
|
||||
-- class_coords). Keyed by the UPPERCASE englishClass token — the same
|
||||
-- key DataStore stores (DataStore_Characters: UnitClass()'s 2nd return)
|
||||
-- and CLASS_ICON_TCOORDS uses, so it is a drop-in for both.
|
||||
--
|
||||
-- Includes the vanilla 10 + DK too, so a single lookup covers every
|
||||
-- CoA-playable class uniformly out of one texture.
|
||||
|
||||
local COA_CLASS_ICON_TEXTURE = [[Interface\AddOns\Altoholic\images\coa-classes]]
|
||||
|
||||
-- left, right, top, bottom (verbatim from the CoA Details atlas)
|
||||
local COA_CLASS_ICON_TCOORDS = {
|
||||
WITCHHUNTER = { 0.875, 1, 0.375, 0.5 },
|
||||
WITCHDOCTOR = { 0.75, 0.875, 0.375, 0.5 },
|
||||
WILDWALKER = { 0.625, 0.75, 0.375, 0.5 },
|
||||
WARRIOR = { 0.5, 0.625, 0.375, 0.5 },
|
||||
WARLOCK = { 0.375, 0.5, 0.375, 0.5 },
|
||||
TINKER = { 0.25, 0.375, 0.375, 0.5 },
|
||||
SUNCLERIC = { 0.125, 0.25, 0.375, 0.5 },
|
||||
STORMBRINGER = { 0, 0.125, 0.375, 0.5 },
|
||||
STARCALLER = { 0.875, 1, 0.25, 0.375 },
|
||||
SPIRITMAGE = { 0.75, 0.875, 0.25, 0.375 },
|
||||
SONOFARUGAL = { 0.625, 0.75, 0.25, 0.375 },
|
||||
SHAMAN = { 0.5, 0.625, 0.25, 0.375 },
|
||||
ROGUE = { 0.375, 0.5, 0.25, 0.375 },
|
||||
REAPER = { 0.25, 0.375, 0.25, 0.375 },
|
||||
RANGER = { 0.125, 0.25, 0.25, 0.375 },
|
||||
PYROMANCER = { 0, 0.125, 0.25, 0.375 },
|
||||
PROPHET = { 0.875, 1, 0.125, 0.25 },
|
||||
PRIEST = { 0.75, 0.875, 0.125, 0.25 },
|
||||
PALADIN = { 0.625, 0.75, 0.125, 0.25 },
|
||||
NECROMANCER = { 0.5, 0.625, 0.125, 0.25 },
|
||||
MONK = { 0.375, 0.5, 0.125, 0.25 },
|
||||
MAGE = { 0.25, 0.375, 0.125, 0.25 },
|
||||
HUNTER = { 0.125, 0.25, 0.125, 0.25 },
|
||||
HERO = { 0, 0.125, 0.125, 0.25 },
|
||||
GUARDIAN = { 0.875, 1, 0, 0.125 },
|
||||
FLESHWARDEN = { 0.75, 0.875, 0, 0.125 },
|
||||
DRUID = { 0.625, 0.75, 0, 0.125 },
|
||||
DEMONHUNTER = { 0.5, 0.625, 0, 0.125 },
|
||||
DEATHKNIGHT = { 0.375, 0.5, 0, 0.125 },
|
||||
CULTIST = { 0.25, 0.375, 0, 0.125 },
|
||||
CHRONOMANCER = { 0.125, 0.25, 0, 0.125 },
|
||||
BARBARIAN = { 0, 0.125, 0, 0.125 },
|
||||
}
|
||||
|
||||
-- Returns texture, left, right, top, bottom for a CoA-playable class
|
||||
-- token, or nil if the token is unknown (caller should fall back to the
|
||||
-- stock CLASS_ICON_TCOORDS path). Tolerant of a nil/missing token.
|
||||
function Alto:GetCoAClassIcon(token)
|
||||
if type(token) ~= "string" then return end
|
||||
local tc = COA_CLASS_ICON_TCOORDS[token]
|
||||
if not tc then return end
|
||||
return COA_CLASS_ICON_TEXTURE, tc[1], tc[2], tc[3], tc[4]
|
||||
end
|
||||
|
||||
@@ -14,6 +14,13 @@ local DARK_RED = "|cFFF00000"
|
||||
local ICON_UNKNOWN = "\124TInterface\\RaidFrame\\ReadyCheck-NotReady:14\124t"
|
||||
local ICON_EXALTED = "\124TInterface\\RaidFrame\\ReadyCheck-Ready:14\124t"
|
||||
|
||||
-- NOTE (Exiles/CoA): The Reputations view is DATA-DRIVEN.
|
||||
-- The hardcoded `Factions` table below is used ONLY as an icon lookup (faction name -> icon),
|
||||
-- so well-known Blizzard factions keep their nice icons. The list of factions actually shown,
|
||||
-- and their grouping, is built at runtime from what DataStore_Reputations scanned on each
|
||||
-- character (faction name + in-game category header). This means CoA's custom factions
|
||||
-- (and any new ones added over time) appear automatically, with no code edits required.
|
||||
-- Factions not present in the icon lookup fall back to a generic faction icon.
|
||||
local Factions = {
|
||||
-- Factions reference table, based on http://www.wowwiki.com/Factions
|
||||
{ -- [1]
|
||||
@@ -151,8 +158,96 @@ local VertexColors = {
|
||||
[FACTION_STANDING_LABEL8] = { r = 1.0, g = 1.0, b = 1.0 }, -- exalted
|
||||
}
|
||||
|
||||
local currentXPack = 1 -- default to wow classic
|
||||
local currentFactionGroup = (UnitFactionGroup("player") == "Alliance") and 1 or 2 -- default to alliance or horde
|
||||
local GENERIC_FACTION_ICON = "Achievement_Reputation_01" -- fallback icon for factions not in the lookup (ex: CoA custom factions)
|
||||
|
||||
-- Flat icon lookup built once from the hardcoded reference table above: faction name -> icon name.
|
||||
local FactionIcons = {}
|
||||
for _, xpack in ipairs(Factions) do
|
||||
for _, factionGroup in ipairs(xpack) do
|
||||
for _, faction in ipairs(factionGroup) do
|
||||
if faction.name and faction.icon then
|
||||
FactionIcons[faction.name] = faction.icon
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function GetFactionIcon(name)
|
||||
return FactionIcons[name] or GENERIC_FACTION_ICON
|
||||
end
|
||||
|
||||
-- *** Dynamic, data-driven group/faction model ***
|
||||
-- currentGroup = "" means "All factions" (every scanned faction, flat). Otherwise it's an in-game
|
||||
-- category header name (ex: "Wrath of the Lich King", or a CoA custom category).
|
||||
local ALL_GROUPS = ""
|
||||
local currentGroup = ALL_GROUPS
|
||||
|
||||
-- Rebuilt on each Update from the union of all characters' scanned reputations on the current realm.
|
||||
local displayedGroups = {} -- ordered list of { name = headerName } for the dropdown
|
||||
local displayedFactions = {} -- ordered list of faction names currently shown (filtered by currentGroup)
|
||||
|
||||
local function BuildModel()
|
||||
local DS = DataStore
|
||||
local realm, account = addon:GetCurrentRealm()
|
||||
|
||||
-- header (group) name -> { set of faction names }, plus first-seen order for stable display
|
||||
local groupSet = {}
|
||||
local factionHeader = {} -- faction name -> its header (last writer wins; headers are consistent across chars)
|
||||
local factionOrder = {} -- faction name -> first-seen index (stable ordering)
|
||||
local orderCounter = 0
|
||||
local groupOrder = {} -- header name -> first-seen index
|
||||
|
||||
for _, characterKey in pairs(DS:GetCharacters(realm, account)) do
|
||||
local reputations = DS:GetReputations(characterKey) or {}
|
||||
local headers = DS:GetReputationHeaders(characterKey) or {}
|
||||
for factionName in pairs(reputations) do
|
||||
local header = headers[factionName] or ""
|
||||
if factionOrder[factionName] == nil then
|
||||
orderCounter = orderCounter + 1
|
||||
factionOrder[factionName] = orderCounter
|
||||
end
|
||||
factionHeader[factionName] = header
|
||||
if not groupSet[header] then
|
||||
groupSet[header] = true
|
||||
groupOrder[header] = orderCounter
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Build the ordered group list for the dropdown.
|
||||
wipe(displayedGroups)
|
||||
local groupNames = {}
|
||||
for header in pairs(groupSet) do
|
||||
tinsert(groupNames, header)
|
||||
end
|
||||
table.sort(groupNames, function(a, b) return (groupOrder[a] or 0) < (groupOrder[b] or 0) end)
|
||||
for _, header in ipairs(groupNames) do
|
||||
tinsert(displayedGroups, header)
|
||||
end
|
||||
|
||||
-- If the previously selected group no longer exists, fall back to "All factions".
|
||||
if currentGroup ~= ALL_GROUPS and not groupSet[currentGroup] then
|
||||
currentGroup = ALL_GROUPS
|
||||
end
|
||||
|
||||
-- Build the ordered faction list for the currently selected group.
|
||||
wipe(displayedFactions)
|
||||
local names = {}
|
||||
for factionName in pairs(factionHeader) do
|
||||
if currentGroup == ALL_GROUPS or factionHeader[factionName] == currentGroup then
|
||||
tinsert(names, factionName)
|
||||
end
|
||||
end
|
||||
table.sort(names, function(a, b) return (factionOrder[a] or 0) < (factionOrder[b] or 0) end)
|
||||
for _, factionName in ipairs(names) do
|
||||
tinsert(displayedFactions, factionName)
|
||||
end
|
||||
end
|
||||
|
||||
local function GroupLabel(header)
|
||||
if header == ALL_GROUPS or header == "" then return ALL end -- "All", a Blizzard global string
|
||||
return header
|
||||
end
|
||||
|
||||
addon.Reputations = {}
|
||||
|
||||
@@ -194,46 +289,43 @@ local function DDM_AddCloseMenu()
|
||||
UIDropDownMenu_AddButton(info, 1)
|
||||
end
|
||||
|
||||
local function DDM_OnClick(self, xpackIndex, factionGroupIndex)
|
||||
currentXPack = xpackIndex
|
||||
currentFactionGroup = factionGroupIndex
|
||||
|
||||
local factionGroup = Factions[currentXPack][currentFactionGroup]
|
||||
UIDropDownMenu_SetText(AltoholicFrameReputations_SelectFaction, factionGroup.name)
|
||||
|
||||
local function DDM_OnClick(self, header)
|
||||
currentGroup = header or ALL_GROUPS
|
||||
|
||||
UIDropDownMenu_SetText(AltoholicFrameReputations_SelectFaction, GroupLabel(currentGroup))
|
||||
|
||||
ns:Update()
|
||||
end
|
||||
|
||||
local function Reputations_UpdateEx(self, offset, entry, desc)
|
||||
local line
|
||||
local size = desc:GetSize()
|
||||
|
||||
|
||||
local DS = DataStore
|
||||
local realm, account = addon:GetCurrentRealm()
|
||||
local character
|
||||
local factionGroup = Factions[currentXPack][currentFactionGroup]
|
||||
|
||||
|
||||
for i=1, desc.NumLines do
|
||||
line = i + offset
|
||||
if line <= size then
|
||||
local faction = factionGroup[line]
|
||||
|
||||
_G[entry..i.."Name"]:SetText(WHITE .. faction.name)
|
||||
local factionName = displayedFactions[line]
|
||||
|
||||
_G[entry..i.."Name"]:SetText(WHITE .. (factionName or ""))
|
||||
_G[entry..i.."Name"]:SetJustifyH("LEFT")
|
||||
_G[entry..i.."Name"]:SetPoint("TOPLEFT", 15, 0)
|
||||
|
||||
|
||||
for j = 1, 10 do -- loop through the 10 alts
|
||||
local itemName = entry.. i .. "Item" .. j;
|
||||
local itemButton = _G[itemName]
|
||||
local classButton = _G["AltoholicFrameClassesItem" .. j]
|
||||
|
||||
|
||||
local itemTexture = _G[itemName .. "_Background"]
|
||||
itemTexture:SetTexture("Interface\\Icons\\"..faction.icon)
|
||||
itemTexture:SetTexture("Interface\\Icons\\"..GetFactionIcon(factionName))
|
||||
|
||||
local status, rate
|
||||
if classButton.CharName then -- if there's an alt in this column..
|
||||
character = DS:GetCharacter(classButton.CharName, realm, account)
|
||||
status, _, _, rate = DS:GetReputationInfo(character, faction.name)
|
||||
status, _, _, rate = DS:GetReputationInfo(character, factionName)
|
||||
|
||||
if status and rate then
|
||||
local vc = VertexColors[status]
|
||||
@@ -276,22 +368,24 @@ local ReputationsScrollFrame_Desc = {
|
||||
NumLines = 8,
|
||||
LineHeight = 41,
|
||||
Frame = "AltoholicFrameReputations",
|
||||
GetSize = function() return #Factions[currentXPack][currentFactionGroup] end,
|
||||
GetSize = function() return #displayedFactions end,
|
||||
Update = Reputations_UpdateEx,
|
||||
}
|
||||
|
||||
function ns:DropDownFaction_Initialize()
|
||||
for xpackIndex, xpack in ipairs(Factions) do
|
||||
DDM_AddTitle(xpack.name)
|
||||
|
||||
for factionGroupIndex, factionGroup in ipairs(Factions[xpackIndex]) do
|
||||
DDM_Add(factionGroup.name, DDM_OnClick, xpackIndex, factionGroupIndex)
|
||||
end
|
||||
-- Dropdown is built dynamically from the categories actually scanned across all characters.
|
||||
BuildModel()
|
||||
|
||||
DDM_Add(GroupLabel(ALL_GROUPS), DDM_OnClick, ALL_GROUPS) -- "All factions" pseudo-group
|
||||
for _, header in ipairs(displayedGroups) do
|
||||
DDM_Add(GroupLabel(header), DDM_OnClick, header)
|
||||
end
|
||||
DDM_AddCloseMenu()
|
||||
end
|
||||
|
||||
function ns:Update()
|
||||
BuildModel()
|
||||
UIDropDownMenu_SetText(AltoholicFrameReputations_SelectFaction, GroupLabel(currentGroup))
|
||||
addon:ScrollFrameUpdate(ReputationsScrollFrame_Desc)
|
||||
end
|
||||
|
||||
@@ -302,12 +396,12 @@ function ns:OnEnter(frame)
|
||||
local DS = DataStore
|
||||
local realm, account = addon:GetCurrentRealm()
|
||||
local character = DS:GetCharacter(charName, realm, account)
|
||||
local factionGroup = Factions[currentXPack][currentFactionGroup]
|
||||
local faction = factionGroup[ frame:GetParent():GetID() ].name
|
||||
|
||||
local faction = displayedFactions[ frame:GetParent():GetID() ]
|
||||
if not faction then return end
|
||||
|
||||
local status, currentLevel, maxLevel, rate = DS:GetReputationInfo(character, faction)
|
||||
if not status then return end
|
||||
|
||||
|
||||
AltoTooltip:SetOwner(frame, "ANCHOR_LEFT");
|
||||
AltoTooltip:ClearLines();
|
||||
AltoTooltip:AddLine((DS:GetColoredCharacterName(character) or "?") .. WHITE .. " @ " .. TEAL .. faction,1,1,1);
|
||||
@@ -346,12 +440,12 @@ function ns:OnClick(frame, button)
|
||||
local DS = DataStore
|
||||
local realm, account = addon:GetCurrentRealm()
|
||||
local character = DS:GetCharacter(charName, realm, account)
|
||||
local factionGroup = Factions[currentXPack][currentFactionGroup]
|
||||
local faction = factionGroup[ frame:GetParent():GetID() ].name
|
||||
|
||||
local faction = displayedFactions[ frame:GetParent():GetID() ]
|
||||
if not faction then return end
|
||||
|
||||
local status, currentLevel, maxLevel, rate = DS:GetReputationInfo(character, faction)
|
||||
if not status then return end
|
||||
|
||||
|
||||
if ( button == "LeftButton" ) and ( IsShiftKeyDown() ) then
|
||||
local chat = ChatEdit_GetLastActiveWindow()
|
||||
if chat:IsShown() then
|
||||
|
||||
@@ -213,11 +213,11 @@
|
||||
</Anchors>
|
||||
<Scripts>
|
||||
<OnLoad>
|
||||
local faction = (UnitFactionGroup("player") == "Alliance") and FACTION_ALLIANCE or FACTION_HORDE
|
||||
|
||||
UIDropDownMenu_SetWidth(self, 100)
|
||||
-- Default to "All factions"; the dropdown contents are built dynamically
|
||||
-- from the categories actually scanned (see Reputations.lua / BuildModel).
|
||||
UIDropDownMenu_SetWidth(self, 140)
|
||||
UIDropDownMenu_SetButtonWidth(self, 20)
|
||||
UIDropDownMenu_SetText(self, faction)
|
||||
UIDropDownMenu_SetText(self, ALL)
|
||||
UIDropDownMenu_Initialize(self, Altoholic.Reputations.DropDownFaction_Initialize)
|
||||
</OnLoad>
|
||||
</Scripts>
|
||||
|
||||
+74
-65
@@ -81,13 +81,10 @@ function ns:Update()
|
||||
end
|
||||
_G[entry..i.."Level"]:SetText("")
|
||||
_G[entry..i.."Skill1NormalText"]:SetText("")
|
||||
_G[entry..i.."Skill2NormalText"]:SetText("")
|
||||
_G[entry..i.."CookingNormalText"]:SetText("")
|
||||
_G[entry..i.."FirstAidNormalText"]:SetText("")
|
||||
_G[entry..i.."FishingNormalText"]:SetText("")
|
||||
_G[entry..i.."RidingNormalText"]:SetText("")
|
||||
_G[entry..i.."WoodcuttingNormalText"]:SetText("")
|
||||
_G[entry..i.."WoodworkingNormalText"]:SetText("")
|
||||
|
||||
_G[ entry..i ]:SetID(line)
|
||||
_G[ entry..i ]:Show()
|
||||
@@ -113,28 +110,26 @@ function ns:Update()
|
||||
_G[entry..i.."NameNormalText"]:SetWidth(170)
|
||||
addon:SetCharacterRowNameLevel(entry, i, icon, character)
|
||||
|
||||
-- profession 1
|
||||
local field = Characters:GetField(line, "spellID1")
|
||||
if field then
|
||||
-- icon = addon:TextureToFontstring(addon:GetSpellIcon(field), size, size) .. " "
|
||||
icon = addon:TextureToFontstring2(addon:GetSpellIcon(field), size, size, inset, inset, inset, inset) .. " "
|
||||
else
|
||||
icon = ""
|
||||
-- CoA: render ALL primary professions the character knows into the
|
||||
-- single wide Professions cell, as a row of icon+rank segments.
|
||||
-- The list is precomputed in Characters.lua (field "professions")
|
||||
-- and may be empty (unscanned char) -> cell renders blank. Every
|
||||
-- value is guarded with "or 0" before GetColor/concat.
|
||||
local professions = Characters:GetField(line, "professions")
|
||||
local profText = ""
|
||||
if professions then
|
||||
for _, p in ipairs(professions) do
|
||||
local rank = p.rank or 0
|
||||
local profIcon = ""
|
||||
if p.spellID then
|
||||
profIcon = addon:TextureToFontstring2(addon:GetSpellIcon(p.spellID), size, size, inset, inset, inset, inset) .. " "
|
||||
end
|
||||
profText = profText .. profIcon .. ns:GetColor(rank) .. rank .. "|r "
|
||||
end
|
||||
end
|
||||
field = Characters:GetField(line, "skillRank1") or 0
|
||||
_G[entry..i.."Skill1NormalText"]:SetText(icon .. ns:GetColor(field) .. field)
|
||||
|
||||
-- profession 2
|
||||
field = Characters:GetField(line, "spellID2")
|
||||
if field then
|
||||
-- icon = addon:TextureToFontstring(addon:GetSpellIcon(field), size, size) .. " "
|
||||
icon = addon:TextureToFontstring2(addon:GetSpellIcon(field), size, size, inset, inset, inset, inset) .. " "
|
||||
else
|
||||
icon = ""
|
||||
end
|
||||
field = Characters:GetField(line, "skillRank2") or 0
|
||||
_G[entry..i.."Skill2NormalText"]:SetText(icon .. ns:GetColor(field) .. field)
|
||||
|
||||
_G[entry..i.."Skill1NormalText"]:SetText(profText)
|
||||
|
||||
local field
|
||||
-- cooking
|
||||
-- icon = addon:TextureToFontstring(addon:GetSpellIcon(2550), size, size) .. " "
|
||||
icon = addon:TextureToFontstring2(addon:GetSpellIcon(2550), size, size, inset, inset, inset, inset) .. " "
|
||||
@@ -193,20 +188,6 @@ function ns:Update()
|
||||
end
|
||||
|
||||
_G[entry..i.."RidingNormalText"]:SetText(icon .. ns:GetColor(field, 300) .. field)
|
||||
|
||||
-- CoA custom professions: Woodcutting (spell 13977860) + Woodworking (spell 1005008).
|
||||
-- Ranks are read live from DataStore_Skills' name-based getters (not from a
|
||||
-- precomputed Characters field) so this stays self-contained. The getters return
|
||||
-- 0 on non-CoA chars or chars not yet scanned; still guarded with "or 0" before
|
||||
-- GetColor/concat. DataStore methods may be absent if DataStore_Skills is an older
|
||||
-- build, so guard each call with an existence check.
|
||||
field = (DS.GetWoodcuttingRank and (DS:GetWoodcuttingRank(character)) or 0) or 0
|
||||
icon = addon:TextureToFontstring2(addon:GetSpellIcon(13977860), size, size, inset, inset, inset, inset) .. " "
|
||||
_G[entry..i.."WoodcuttingNormalText"]:SetText(icon .. ns:GetColor(field) .. field)
|
||||
|
||||
field = (DS.GetWoodworkingRank and (DS:GetWoodworkingRank(character)) or 0) or 0
|
||||
icon = addon:TextureToFontstring2(addon:GetSpellIcon(1005008), size, size, inset, inset, inset, inset) .. " "
|
||||
_G[entry..i.."WoodworkingNormalText"]:SetText(icon .. ns:GetColor(field) .. field)
|
||||
elseif (lineType == INFO_TOTAL_LINE) then
|
||||
_G[entry..i.."Collapse"]:Hide()
|
||||
_G[entry..i.."Name"]:SetWidth(200)
|
||||
@@ -215,13 +196,10 @@ function ns:Update()
|
||||
_G[entry..i.."NameNormalText"]:SetText(L["Totals"])
|
||||
_G[entry..i.."Level"]:SetText(Characters:GetField(line, "level"))
|
||||
_G[entry..i.."Skill1NormalText"]:SetText("")
|
||||
_G[entry..i.."Skill2NormalText"]:SetText("")
|
||||
_G[entry..i.."CookingNormalText"]:SetText("")
|
||||
_G[entry..i.."FirstAidNormalText"]:SetText("")
|
||||
_G[entry..i.."FishingNormalText"]:SetText("")
|
||||
_G[entry..i.."RidingNormalText"]:SetText("")
|
||||
_G[entry..i.."WoodcuttingNormalText"]:SetText("")
|
||||
_G[entry..i.."WoodworkingNormalText"]:SetText("")
|
||||
end
|
||||
_G[ entry..i ]:SetID(line)
|
||||
_G[ entry..i ]:Show()
|
||||
@@ -250,12 +228,46 @@ function ns:OnEnter(frame)
|
||||
|
||||
local id = frame:GetID()
|
||||
local skillName, rank, suggestion
|
||||
|
||||
|
||||
local DS = DataStore
|
||||
local character = DS:GetCharacter(Characters:GetInfo(line))
|
||||
|
||||
-- CoA: id 1 is now the combined "Professions" cell -> list every known primary
|
||||
-- profession with rank/max and recipe counts in a single tooltip.
|
||||
if id == 1 then
|
||||
skillName = Characters:GetField(line, "skillName1")
|
||||
elseif id == 2 then
|
||||
skillName = Characters:GetField(line, "skillName2")
|
||||
elseif id == 3 then
|
||||
local professions = Characters:GetField(line, "professions")
|
||||
AltoTooltip:ClearLines()
|
||||
AltoTooltip:SetOwner(frame, "ANCHOR_RIGHT")
|
||||
AltoTooltip:AddLine(L["Professions"] or "Professions", 1, 1, 1)
|
||||
if not professions or #professions == 0 then
|
||||
AltoTooltip:AddLine(L["No data"])
|
||||
AltoTooltip:Show()
|
||||
return
|
||||
end
|
||||
for _, p in ipairs(professions) do
|
||||
local pName = p.name
|
||||
local curRank, maxRank = DS:GetSkillInfo(character, pName)
|
||||
curRank, maxRank = curRank or 0, maxRank or 0
|
||||
local rankText = ns:GetColor(curRank) .. curRank .. "/" .. maxRank
|
||||
local recipeText = ""
|
||||
local prof = DS:GetProfession(character, pName)
|
||||
if prof and DS:GetNumCraftLines(prof) > 0 then
|
||||
local orange, yellow, green, grey = DS:GetNumRecipesByColor(prof)
|
||||
recipeText = WHITE .. " (" .. (orange + yellow + green + grey) .. " " .. TRADESKILL_SERVICE_LEARN .. ")"
|
||||
end
|
||||
-- localized display name where possible
|
||||
local displayName = pName
|
||||
local spellID = DS:GetProfessionSpellID(pName)
|
||||
if spellID then
|
||||
displayName = GetSpellInfo(spellID) or pName
|
||||
end
|
||||
AltoTooltip:AddDoubleLine(WHITE .. displayName, rankText .. recipeText)
|
||||
end
|
||||
AltoTooltip:Show()
|
||||
return
|
||||
end
|
||||
|
||||
if id == 3 then
|
||||
skillName = GetSpellInfo(2550) -- cooking
|
||||
elseif id == 4 then
|
||||
skillName = GetSpellInfo(3273) -- First Aid
|
||||
@@ -263,22 +275,13 @@ function ns:OnEnter(frame)
|
||||
skillName = GetSpellInfo(24303) -- Fishing
|
||||
elseif id == 6 then
|
||||
skillName = L["Riding"]
|
||||
elseif id == 8 then
|
||||
skillName = GetSpellInfo(13977860) or "Woodcutting" -- CoA custom: Woodcutting
|
||||
elseif id == 9 then
|
||||
skillName = GetSpellInfo(1005008) or "Woodworking" -- CoA custom: Woodworking
|
||||
end
|
||||
|
||||
local DS = DataStore
|
||||
local character = DS:GetCharacter(Characters:GetInfo(line))
|
||||
local curRank, maxRank = DS:GetSkillInfo(character, skillName)
|
||||
curRank, maxRank = curRank or 0, maxRank or 0 -- CoA: getter returns no value for skills DataStore_Skills hasn't scanned
|
||||
local profession = DS:GetProfession(character, skillName)
|
||||
|
||||
if (id == 8) or (id == 9) then -- CoA custom professions: show rank + recipe summary like the primary professions
|
||||
rank = ns:GetColor(curRank) .. curRank .. "/" .. maxRank
|
||||
suggestion = addon:GetSuggestion(skillName, curRank)
|
||||
elseif (id >= 1) and (id <= 6) then
|
||||
if (id >= 3) and (id <= 6) then
|
||||
if id == 6 then -- riding
|
||||
rank = ns:GetColor(curRank, 300) .. curRank .. "/" .. maxRank
|
||||
else
|
||||
@@ -303,7 +306,7 @@ function ns:OnEnter(frame)
|
||||
AltoTooltip:AddLine(skillName,1,1,1);
|
||||
AltoTooltip:AddLine(GREEN..rank,1,1,1);
|
||||
|
||||
if (id <= 4) or (id == 9) then -- crafting skills (incl. CoA Woodworking, id 9); skips fishing/riding/Woodcutting
|
||||
if (id == 3) or (id == 4) then -- crafting secondary skills (Cooking, First Aid); skips fishing/riding
|
||||
if skillName ~= GetSpellInfo(13614) and skillName ~= GetSpellInfo(8613) then -- no display for herbalism & skinning
|
||||
AltoTooltip:AddLine(" ");
|
||||
|
||||
@@ -381,17 +384,17 @@ function ns:OnClick(frame, button)
|
||||
|
||||
local skillName
|
||||
if id == 1 then
|
||||
skillName = Characters:GetField(line, "skillName1")
|
||||
elseif id == 2 then
|
||||
skillName = Characters:GetField(line, "skillName2")
|
||||
-- CoA: id 1 is the combined Professions cell. A single click can't pick one
|
||||
-- of several professions, so default to the first known primary profession
|
||||
-- (opens its recipes / supplies its trade link on shift-click).
|
||||
local professions = Characters:GetField(line, "professions")
|
||||
if professions and professions[1] then
|
||||
skillName = professions[1].name
|
||||
end
|
||||
elseif id == 3 then
|
||||
skillName = GetSpellInfo(2550) -- cooking
|
||||
elseif id == 4 then
|
||||
skillName = GetSpellInfo(3273) -- First Aid
|
||||
elseif id == 8 then
|
||||
skillName = GetSpellInfo(13977860) or "Woodcutting" -- CoA custom (gathering, no recipes)
|
||||
elseif id == 9 then
|
||||
skillName = GetSpellInfo(1005008) or "Woodworking" -- CoA custom (crafting)
|
||||
end
|
||||
|
||||
local DS = DataStore
|
||||
@@ -431,5 +434,11 @@ local skillColors = { RECIPE_GREY, RED, ORANGE, YELLOW, GREEN }
|
||||
function ns:GetColor(rank, skillCap)
|
||||
rank = rank or 0 -- CoA: skill fields are nil for chars DataStore_Characters hasn't scanned
|
||||
skillCap = skillCap or 450
|
||||
return skillColors[ floor(rank / (skillCap/4)) + 1 ]
|
||||
-- CoA: custom professions can exceed skillCap (e.g. ranks > 450), which would
|
||||
-- push the index past the 5-colour table and return nil -> crash on concat.
|
||||
-- Clamp into [1, #skillColors].
|
||||
local index = floor(rank / (skillCap / 4)) + 1
|
||||
if index < 1 then index = 1 end
|
||||
if index > #skillColors then index = #skillColors end
|
||||
return skillColors[index]
|
||||
end
|
||||
|
||||
+20
-28
@@ -108,7 +108,14 @@
|
||||
<NormalFont style="GameFontNormalSmallLeft"/>
|
||||
<HighlightFont style="GameFontHighlightSmallLeft"/>
|
||||
</Button>
|
||||
<!-- CoA: single wide "Professions" cell. Lists every known primary
|
||||
profession (incl. customs Woodcutting/Woodworking) as icon+rank
|
||||
segments, replacing the old fixed Prof.1/Prof.2 columns. Width
|
||||
(325) must match the "Professions" header in TabSummary.lua. -->
|
||||
<Button name="$parentSkill1" inherits="AltoSkillButtonTemplate" id="1">
|
||||
<Size>
|
||||
<AbsDimension x="325" y="18"/>
|
||||
</Size>
|
||||
<Anchors>
|
||||
<Anchor point="BOTTOMLEFT" relativeTo="$parentLevel" relativePoint="BOTTOMRIGHT">
|
||||
<Offset>
|
||||
@@ -116,19 +123,22 @@
|
||||
</Offset>
|
||||
</Anchor>
|
||||
</Anchors>
|
||||
</Button>
|
||||
<Button name="$parentSkill2" inherits="AltoSkillButtonTemplate" id="2">
|
||||
<Anchors>
|
||||
<Anchor point="BOTTOMLEFT" relativeTo="$parentSkill1" relativePoint="BOTTOMRIGHT">
|
||||
<Offset>
|
||||
<AbsDimension x="0" y="0"/>
|
||||
</Offset>
|
||||
</Anchor>
|
||||
</Anchors>
|
||||
<ButtonText name="$parentNormalText" justifyH="LEFT">
|
||||
<Size>
|
||||
<AbsDimension x="325" y="18"/>
|
||||
</Size>
|
||||
<Anchors>
|
||||
<Anchor point="LEFT">
|
||||
<Offset>
|
||||
<AbsDimension x="0" y="0"/>
|
||||
</Offset>
|
||||
</Anchor>
|
||||
</Anchors>
|
||||
</ButtonText>
|
||||
</Button>
|
||||
<Button name="$parentCooking" inherits="AltoSkillButtonTemplate" id="3">
|
||||
<Anchors>
|
||||
<Anchor point="BOTTOMLEFT" relativeTo="$parentSkill2" relativePoint="BOTTOMRIGHT">
|
||||
<Anchor point="BOTTOMLEFT" relativeTo="$parentSkill1" relativePoint="BOTTOMRIGHT">
|
||||
<Offset>
|
||||
<AbsDimension x="0" y="0"/>
|
||||
</Offset>
|
||||
@@ -162,24 +172,6 @@
|
||||
</Anchor>
|
||||
</Anchors>
|
||||
</Button>
|
||||
<Button name="$parentWoodcutting" inherits="AltoSkillButtonTemplate" id="8">
|
||||
<Anchors>
|
||||
<Anchor point="BOTTOMLEFT" relativeTo="$parentRiding" relativePoint="BOTTOMRIGHT">
|
||||
<Offset>
|
||||
<AbsDimension x="0" y="0"/>
|
||||
</Offset>
|
||||
</Anchor>
|
||||
</Anchors>
|
||||
</Button>
|
||||
<Button name="$parentWoodworking" inherits="AltoSkillButtonTemplate" id="9">
|
||||
<Anchors>
|
||||
<Anchor point="BOTTOMLEFT" relativeTo="$parentWoodcutting" relativePoint="BOTTOMRIGHT">
|
||||
<Offset>
|
||||
<AbsDimension x="0" y="0"/>
|
||||
</Offset>
|
||||
</Anchor>
|
||||
</Anchors>
|
||||
</Button>
|
||||
</Frames>
|
||||
</Button>
|
||||
|
||||
|
||||
@@ -160,8 +160,11 @@ function ns:SetMode(mode)
|
||||
elseif currentMode == 3 then
|
||||
Columns:Add(NAME, 100, function(self) addon.Characters:Sort(self, "GetCharacterName") end)
|
||||
Columns:Add(LEVEL, 60, function(self) addon.Characters:Sort(self, "GetCharacterLevel") end)
|
||||
Columns:Add(L["Prof. 1"], 65, function(self) addon.Characters:Sort(self, "skillName1") end)
|
||||
Columns:Add(L["Prof. 2"], 65, function(self) addon.Characters:Sort(self, "skillName2") end)
|
||||
-- CoA: a character can know ALL professions at once, so the old fixed
|
||||
-- Prof. 1 / Prof. 2 columns are replaced by one wide "Professions" column
|
||||
-- that lists every known primary profession (incl. the customs Woodcutting
|
||||
-- and Woodworking). Width matches the widened Skill1 cell in Skills.xml.
|
||||
Columns:Add(L["Professions"] or "Professions", 325, function(self) addon.Characters:Sort(self, "GetCharacterName") end)
|
||||
title = GetSpellInfo(2550) -- cooking
|
||||
Columns:Add(title, 65, function(self) addon.Characters:Sort(self, "GetCookingRank") end)
|
||||
title = GetSpellInfo(3273) -- First Aid
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user