From 6c1d128040ff0c958178ede76e5174574a7ad006 Mon Sep 17 00:00:00 2001 From: Peechey <92683202+Peechey@users.noreply.github.com> Date: Mon, 2 Mar 2026 23:56:14 -0600 Subject: [PATCH 01/12] remove Variant, AltQual, QualityId from SkillsTab and every damn place else because it's an infestation --- src/Classes/GemSelectControl.lua | 27 +--- src/Classes/ImportTab.lua | 4 +- src/Classes/SkillsTab.lua | 259 +++++++++---------------------- 3 files changed, 81 insertions(+), 209 deletions(-) diff --git a/src/Classes/GemSelectControl.lua b/src/Classes/GemSelectControl.lua index 8155e9868c..5caac872a4 100644 --- a/src/Classes/GemSelectControl.lua +++ b/src/Classes/GemSelectControl.lua @@ -120,21 +120,15 @@ function GemSelectClass:PopulateGemList() self.gems["Default:" .. gemId] = gemData end elseif showNormal or showAll then - if self.skillsTab.showAltQualityGems and (self.skillsTab.defaultGemQuality or 0) > 0 then - for _, altQual in ipairs(self.skillsTab:getGemAltQualityList(gemData)) do - self.gems[altQual.type .. ":" .. gemId] = gemData - end - else - self.gems["Default:" .. gemId] = gemData - end + self.gems["Default:" .. gemId] = gemData end end end end end -function GemSelectClass:GetQualityType(gemId) - return gemId and gemId:gsub(":.+","") or "Default" +function GemSelectClass:GetQualityType() -- todo: whatever is using this adds the Default quality to gems, it seems, can't fully remove yet? + return "Default" end function GemSelectClass:FilterSupport(gemId, gemData) @@ -176,7 +170,7 @@ function GemSelectClass:BuildList(buf) for i, pattern in ipairs(patternList) do local matchList = { } for gemId, gemData in pairs(self.gems) do - if self:FilterSupport(gemId, gemData) and not added[gemId] and ((" "..gemData.name:lower()):match(pattern) or altQualMap[self:GetQualityType(gemId)]:lower():match(pattern)) then + if self:FilterSupport(gemId, gemData) and not added[gemId] and ((" "..gemData.name:lower()):match(pattern)) then addThisGem = true if #tagsList > 0 then for _, tag in ipairs(tagsList) do @@ -258,12 +252,11 @@ function GemSelectClass:UpdateSortCache() and sortCache.outputRevision == self.skillsTab.build.outputRevision and sortCache.defaultLevel == self.skillsTab.defaultGemLevel and (sortCache.characterLevel == self.skillsTab.build.characterLevel or self.skillsTab.defaultGemLevel ~= "characterLevel") and sortCache.defaultQuality == self.skillsTab.defaultGemQuality and sortCache.sortType == self.skillsTab.sortGemsByDPSField - and sortCache.considerAlternates == self.skillsTab.showAltQualityGems and sortCache.considerGemType == self.skillsTab.showSupportGemTypes - and sortCache.showLegacyGems == self.skillsTab.showLegacyGems then + and sortCache.considerGemType == self.skillsTab.showSupportGemTypes and sortCache.showLegacyGems == self.skillsTab.showLegacyGems then return end - if not sameSortBy or not sortCache or (sortCache.considerAlternates ~= self.skillsTab.showAltQualityGems or sortCache.considerGemType ~= self.skillsTab.showSupportGemTypes + if not sameSortBy or not sortCache or (sortCache.considerGemType ~= self.skillsTab.showSupportGemTypes or sortCache.showLegacyGems ~= self.skillsTab.showLegacyGems or sortCache.defaultQuality ~= self.skillsTab.defaultGemQuality or sortCache.defaultLevel ~= self.skillsTab.defaultGemLevel @@ -275,7 +268,6 @@ function GemSelectClass:UpdateSortCache() -- Initialize a new sort cache sortCache = { considerGemType = self.skillsTab.showSupportGemTypes, - considerAlternates = self.skillsTab.showAltQualityGems, showLegacyGems = self.skillsTab.showLegacyGems, socketGroup = self.skillsTab.displayGroup, gemInstance = self.skillsTab.displayGroup.gemList[self.index], @@ -470,9 +462,6 @@ function GemSelectClass:Draw(viewPort, noTooltip) end end local gemText = gemData and gemData.name or "" - if gemId and gemId ~= "" then - gemText = altQualMap[self:GetQualityType(gemId)] .. gemText - end DrawString(0, y, "LEFT", height - 4, "VAR", gemText) if gemData then if gemData.grantedEffect.support and self.sortCache.canSupport[gemId] then @@ -598,7 +587,7 @@ function GemSelectClass:AddGemTooltip(gemInstance) if secondary and (not secondary.support or gemInstance.gemData.secondaryEffectName) then local grantedEffect = gemInstance.gemData.VaalGem and secondary or primary local grantedEffectSecondary = gemInstance.gemData.VaalGem and primary or secondary - self.tooltip:AddLine(fontSizeTitle, colorCodes.GEM .. altQualMap[gemInstance.qualityId]..grantedEffect.name, "FONTIN SC") + self.tooltip:AddLine(fontSizeTitle, colorCodes.GEM..grantedEffect.name, "FONTIN SC") self.tooltip:AddSeparator(10) self.tooltip:AddLine(fontSizeBig, "^x7F7F7F" .. gemInstance.gemData.tagString, "FONTIN SC") self:AddCommonGemInfo(gemInstance, grantedEffect, true) @@ -608,7 +597,7 @@ function GemSelectClass:AddGemTooltip(gemInstance) self:AddCommonGemInfo(gemInstance, grantedEffectSecondary) else local grantedEffect = gemInstance.gemData.grantedEffect - self.tooltip:AddLine(fontSizeTitle, colorCodes.GEM .. altQualMap[gemInstance.qualityId]..grantedEffect.name, "FONTIN SC") + self.tooltip:AddLine(fontSizeTitle, colorCodes.GEM..grantedEffect.name, "FONTIN SC") self.tooltip:AddSeparator(10) if grantedEffect.legacy then self.tooltip:AddLine(fontSizeTitle, colorCodes.WARNING .. "Legacy Gem", "FONTIN SC") diff --git a/src/Classes/ImportTab.lua b/src/Classes/ImportTab.lua index 1427ff4a97..d2a6232227 100644 --- a/src/Classes/ImportTab.lua +++ b/src/Classes/ImportTab.lua @@ -1116,11 +1116,11 @@ function ImportTabClass:ImportSocketedItems(item, socketedItems, slotName) self:ImportItem(socketedItem, slotName .. " Abyssal Socket "..abyssalSocketId) abyssalSocketId = abyssalSocketId + 1 else - local normalizedBasename, qualityType = self.build.skillsTab:GetBaseNameAndQuality(socketedItem.typeLine, nil) + local normalizedBasename, qualityType = sanitiseText(socketedItem.typeLine) local gemId = self.build.data.gemForBaseName[normalizedBasename:lower()] if socketedItem.hybrid then -- Used by transfigured gems and dual-skill gems (currently just Stormbind) - normalizedBasename, qualityType = self.build.skillsTab:GetBaseNameAndQuality(socketedItem.hybrid.baseTypeName, nil) + normalizedBasename, qualityType = sanitiseText(socketedItem.hybrid.baseTypeName) gemId = self.build.data.gemForBaseName[normalizedBasename:lower()] if gemId and socketedItem.hybrid.isVaalGem then gemId = self.build.data.gemGrantedEffectIdForVaalGemId[self.build.data.gems[gemId].grantedEffectId] diff --git a/src/Classes/SkillsTab.lua b/src/Classes/SkillsTab.lua index a7dfedcc09..63fbcd6743 100644 --- a/src/Classes/SkillsTab.lua +++ b/src/Classes/SkillsTab.lua @@ -94,7 +94,6 @@ local SkillsTabClass = newClass("SkillsTab", "UndoHandler", "ControlHost", "Cont self.sortGemsByDPS = true self.sortGemsByDPSField = "CombinedDPS" self.showSupportGemTypes = "ALL" - self.showAltQualityGems = false self.showLegacyGems = false self.defaultGemLevel = "normalMaximum" self.defaultGemQuality = main.defaultGemQuality @@ -128,7 +127,7 @@ local SkillsTabClass = newClass("SkillsTab", "UndoHandler", "ControlHost", "Cont -- Gem options local optionInputsX = 170 local optionInputsY = 45 - self.controls.optionSection = new("SectionControl", { "TOPLEFT", self.controls.groupList, "BOTTOMLEFT" }, { 0, optionInputsY + 50, 360, 180 }, "Gem Options") + self.controls.optionSection = new("SectionControl", { "TOPLEFT", self.controls.groupList, "BOTTOMLEFT" }, { 0, optionInputsY + 50, 360, 156 }, "Gem Options") self.controls.sortGemsByDPS = new("CheckBoxControl", { "TOPLEFT", self.controls.groupList, "BOTTOMLEFT" }, { optionInputsX, optionInputsY + 70, 20 }, "Sort gems by DPS:", function(state) self.sortGemsByDPS = state end, nil, true) @@ -153,9 +152,6 @@ local SkillsTabClass = newClass("SkillsTab", "UndoHandler", "ControlHost", "Cont self.showSupportGemTypes = value.show end) self.controls.showSupportGemTypesLabel = new("LabelControl", { "RIGHT", self.controls.showSupportGemTypes, "LEFT" }, { -4, 0, 0, 16 }, "^7Show support gems:") - self.controls.showAltQualityGems = new("CheckBoxControl", { "TOPLEFT", self.controls.groupList, "BOTTOMLEFT" }, { optionInputsX, optionInputsY + 166, 20 }, "^7Show quality variants:", function(state) - self.showAltQualityGems = state - end) self.controls.showLegacyGems = new("CheckBoxControl", { "TOPLEFT", self.controls.groupList, "BOTTOMLEFT" }, { optionInputsX, optionInputsY + 190, 20 }, "^7Show legacy gems:", function(state) self.showLegacyGems = state end) @@ -272,33 +268,11 @@ will automatically apply to the skill.]] self:CreateGemSlot(1) self.controls.gemNameHeader = new("LabelControl", {"BOTTOMLEFT", self.gemSlots[1].nameSpec, "TOPLEFT"}, {0, -2, 0, 16}, "^7Gem name:") self.controls.gemLevelHeader = new("LabelControl", {"BOTTOMLEFT", self.gemSlots[1].level, "TOPLEFT"}, {0, -2, 0, 16}, "^7Level:") - self.controls.gemQualityIdHeader = new("LabelControl", {"BOTTOMLEFT", self.gemSlots[1].qualityId, "TOPLEFT"}, {0, -2, 0, 16}, "^7Variant:") self.controls.gemQualityHeader = new("LabelControl", {"BOTTOMLEFT", self.gemSlots[1].quality, "TOPLEFT"}, {0, -2, 0, 16}, "^7Quality:") self.controls.gemEnableHeader = new("LabelControl", {"BOTTOMLEFT", self.gemSlots[1].enabled, "TOPLEFT"}, {-16, -2, 0, 16}, "^7Enabled:") self.controls.gemCountHeader = new("LabelControl", {"BOTTOMLEFT", self.gemSlots[1].count, "TOPLEFT"}, {8, -2, 0, 16}, "^7Count:") end) --- parse real gem name and quality by omitting the first word if alt qual is set -function SkillsTabClass:GetBaseNameAndQuality(gemTypeLine, quality) - gemTypeLine = sanitiseText(gemTypeLine) - -- if quality is default or nil check the gem type line if we have alt qual by comparing to the existing list - if gemTypeLine and (quality == nil or quality == "" or quality == "Default") then - local firstword, otherwords = gemTypeLine:match("(%w+)%s(.+)") - if firstword and otherwords then - for _, entry in ipairs(alternateGemQualityList) do - if firstword == entry.label then - -- return the gem name minus without a leading space and the new resolved type - if entry.type == nil or entry.type == "" then - entry.type = "Default" - end - return otherwords, entry.type - end - end - end - end - -- no alt qual found, return gemTypeLine as is and either existing quality or Default if none is set - return gemTypeLine, quality or "Default" -end function SkillsTabClass:LoadSkill(node, skillSetId) if node.elem ~= "Skill" then @@ -320,22 +294,6 @@ function SkillsTabClass:LoadSkill(node, skillSetId) gemInstance.nameSpec = sanitiseText(child.attrib.nameSpec or "") if child.attrib.gemId then local gemData - local possibleVariants = self.build.data.gemsByGameId[child.attrib.gemId] - if possibleVariants then - -- If it is a known gem, try to determine which variant is used - if child.attrib.variantId then - -- New save format from 3.23 that stores the specific variation (transfiguration) - gemData = possibleVariants[child.attrib.variantId] - elseif child.attrib.skillId then - -- Old format relying on the uniqueness of the granted effects id - for _, variant in pairs(possibleVariants) do - if variant.grantedEffectId == child.attrib.skillId then - gemData = variant - break - end - end - end - end if gemData then gemInstance.gemId = gemData.id gemInstance.skillId = gemData.grantedEffectId @@ -351,13 +309,7 @@ function SkillsTabClass:LoadSkill(node, skillSetId) end gemInstance.level = tonumber(child.attrib.level) gemInstance.quality = tonumber(child.attrib.quality) - local nameSpecOverride, qualityOverrideId = SkillsTabClass:GetBaseNameAndQuality(gemInstance.nameSpec, child.attrib.qualityId) - gemInstance.nameSpec = nameSpecOverride - gemInstance.qualityId = qualityOverrideId - - if gemInstance.gemData then - gemInstance.qualityId.list = self:getGemAltQualityList(gemInstance.gemData) - end + gemInstance.nameSpec = sanitiseText(gemInstance.nameSpec) gemInstance.enabled = not child.attrib.enabled and true or child.attrib.enabled == "true" gemInstance.enableGlobal1 = not child.attrib.enableGlobal1 or child.attrib.enableGlobal1 == "true" gemInstance.enableGlobal2 = child.attrib.enableGlobal2 == "true" @@ -402,10 +354,6 @@ function SkillsTabClass:Load(xml, fileName) self.sortGemsByDPS = xml.attrib.sortGemsByDPS == "true" end self.controls.sortGemsByDPS.state = self.sortGemsByDPS - if xml.attrib.showAltQualityGems then - self.showAltQualityGems = xml.attrib.showAltQualityGems == "true" - end - self.controls.showAltQualityGems.state = self.showAltQualityGems if xml.attrib.showLegacyGems then self.showLegacyGems = xml.attrib.showLegacyGems == "true" end @@ -445,8 +393,7 @@ function SkillsTabClass:Save(xml) sortGemsByDPS = tostring(self.sortGemsByDPS), showSupportGemTypes = self.showSupportGemTypes, sortGemsByDPSField = self.sortGemsByDPSField, - showAltQualityGems = tostring(self.showAltQualityGems), - showLegacyGems = tostring(self.showLegacyGems) + showLegacyGems = tostring(self.showLegacyGems), } for _, skillSetId in ipairs(self.skillSetOrderList) do local skillSet = self.skillSets[skillSetId] @@ -469,10 +416,8 @@ function SkillsTabClass:Save(xml) nameSpec = gemInstance.nameSpec, skillId = gemInstance.skillId, gemId = gemInstance.gemData and gemInstance.gemData.gameId, - variantId = gemInstance.gemData and gemInstance.gemData.variantId, level = tostring(gemInstance.level), quality = tostring(gemInstance.quality), - qualityId = gemInstance.qualityId, enabled = tostring(gemInstance.enabled), enableGlobal1 = tostring(gemInstance.enableGlobal1), enableGlobal2 = tostring(gemInstance.enableGlobal2), @@ -568,7 +513,7 @@ function SkillsTabClass:CopySocketGroup(socketGroup) skillText = skillText .. "Slot: " .. socketGroup.slot .. "\r\n" end for _, gemInstance in ipairs(socketGroup.gemList) do - skillText = skillText .. string.format("%s %d/%d %s %s %d\r\n", gemInstance.nameSpec, gemInstance.level, gemInstance.quality, gemInstance.qualityId, gemInstance.enabled and "" or "DISABLED", gemInstance.count or 1) + skillText = skillText .. string.format("%s %d/%d %s %s %d\r\n", gemInstance.nameSpec, gemInstance.level, gemInstance.quality, gemInstance.enabled and "" or "DISABLED", gemInstance.count or 1) end Copy(skillText) end @@ -585,12 +530,11 @@ function SkillsTabClass:PasteSocketGroup(testInput) if slot then newGroup.slot = slot end - for nameSpec, level, quality, qualityId, state, count in skillText:gmatch("([ %a']+) (%d+)/(%d+) (%a+%d?) ?(%a*) (%d+)") do + for nameSpec, level, quality, state, count in skillText:gmatch("([ %a']+) (%d+)/(%d+) (%a+%d?) ?(%a*) (%d+)") do t_insert(newGroup.gemList, { nameSpec = nameSpec, level = tonumber(level) or 20, quality = tonumber(quality) or 0, - qualityId = qualityId, enabled = state ~= "DISABLED", count = tonumber(count) or 1, enableGlobal1 = true, @@ -622,8 +566,6 @@ function SkillsTabClass:CreateGemSlot(index) self.gemSlots[index2].nameSpec:SetText(gemInstance.nameSpec) self.gemSlots[index2].level:SetText(gemInstance.level) self.gemSlots[index2].quality:SetText(gemInstance.quality) - self.gemSlots[index2].qualityId.list = self:getGemAltQualityList(gemInstance.gemData) - self.gemSlots[index2].qualityId:SelByValue(gemInstance.qualityId, "type") self.gemSlots[index2].enabled.state = gemInstance.enabled self.gemSlots[index2].enableGlobal1.state = gemInstance.enableGlobal1 self.gemSlots[index2].enableGlobal2.state = gemInstance.enableGlobal2 @@ -650,7 +592,7 @@ function SkillsTabClass:CreateGemSlot(index) self.controls["gemSlot"..index.."Delete"] = slot.delete -- Gem name specification - slot.nameSpec = new("GemSelectControl", { "LEFT", slot.delete, "RIGHT" }, { 2, 0, 300, 20 }, self, index, function(gemId, qualityId, addUndo) + slot.nameSpec = new("GemSelectControl", { "LEFT", slot.delete, "RIGHT" }, { 2, 0, 300, 20 }, self, index, function(gemId, addUndo) if not self.displayGroup then return end @@ -663,7 +605,6 @@ function SkillsTabClass:CreateGemSlot(index) nameSpec = "", level = 1, quality = self.defaultGemQuality or 0, - qualityId = "Default", enabled = true, enableGlobal1 = true, enableGlobal2 = true, @@ -673,7 +614,6 @@ function SkillsTabClass:CreateGemSlot(index) self.displayGroup.gemList[index] = gemInstance slot.level:SetText(gemInstance.level) slot.quality:SetText(gemInstance.quality) - slot.qualityId:SelByValue(gemInstance.qualityId) slot.enabled.state = true slot.enableGlobal1.state = true slot.enableGlobal2.state = true @@ -690,10 +630,6 @@ function SkillsTabClass:CreateGemSlot(index) -- New gems need to be constrained by ProcessGemLevel gemInstance.level = self:ProcessGemLevel(gemInstance.gemData) gemInstance.naturalMaxLevel = gemInstance.level - -- Gem changed, update the list and default the quality id - slot.qualityId.list = self:getGemAltQualityList(gemInstance.gemData) - slot.qualityId:SelByValue(qualityId or "Default", "type") - gemInstance.qualityId = qualityId or "Default" slot.level:SetText(gemInstance.level) slot.count:SetText(gemInstance.count or 1) if addUndo then @@ -708,11 +644,9 @@ function SkillsTabClass:CreateGemSlot(index) slot.level = new("EditControl", { "LEFT", slot.nameSpec, "RIGHT" }, { 2, 0, 60, 20 }, nil, nil, "%D", 2, function(buf) local gemInstance = self.displayGroup.gemList[index] if not gemInstance then - gemInstance = { nameSpec = "", level = self.defaultGemLevel or 20, quality = self.defaultGemQuality or 0, qualityId = "Default", enabled = true, enableGlobal1 = true, enableGlobal2 = true, count = 1, new = true } + gemInstance = { nameSpec = "", level = self.defaultGemLevel or 20, quality = self.defaultGemQuality or 0, enabled = true, enableGlobal1 = true, enableGlobal2 = true, count = 1, new = true } self.displayGroup.gemList[index] = gemInstance - slot.qualityId.list = self:getGemAltQualityList(gemInstance.gemData) slot.quality:SetText(gemInstance.quality) - slot.qualityId:SelByValue(gemInstance.qualityId, "type") slot.enabled.state = true slot.enableGlobal1.state = true slot.count:SetText(gemInstance.count) @@ -728,101 +662,11 @@ function SkillsTabClass:CreateGemSlot(index) end self.controls["gemSlot"..index.."Level"] = slot.level - -- Gem quality id - slot.qualityId = new("DropDownControl", {"LEFT",slot.level,"RIGHT"}, {2, 0, 90, 20}, alternateGemQualityList, function(dropDownIndex, value) - local gemInstance = self.displayGroup.gemList[index] - if not gemInstance then - gemInstance = { nameSpec = "", level = self.defaultGemLevel or 20, quality = self.defaultGemQuality or 0, qualityId = "Default", enabled = true, enableGlobal1 = true, enableGlobal2 = true, count = 1, new = true } - self.displayGroup.gemList[index] = gemInstance - slot.level:SetText(gemInstance.level) - slot.enabled.state = true - slot.enableGlobal1.state = true - slot.count:SetText(gemInstance.count) - end - gemInstance.qualityId = value.type - self:ProcessSocketGroup(self.displayGroup) - self:AddUndoState() - self.build.buildFlag = true - end) - slot.qualityId.enabled = function() - return index <= #self.displayGroup.gemList - end - slot.qualityId.tooltipFunc = function(tooltip) - -- Reset the tooltip - tooltip:Clear() - -- Get the gem instance from the skills - local gemInstance = self.displayGroup.gemList[index] - if not gemInstance then - return - end - local gemData = gemInstance.gemData - -- Get the hovered quality item - local hoveredQuality - if not slot.qualityId.dropped then - hoveredQuality = alternateGemQualityList[slot.qualityId.selIndex] - else - hoveredQuality = alternateGemQualityList[slot.qualityId.hoverSel] - end - -- gem data may not be initialized yet, or the quality may be nil, which happens when just floating over the dropdown - if not gemData or not hoveredQuality then - return - end - -- Function for both granted effect and secondary such as vaal - local addQualityLines = function(qualityList, grantedEffect) - tooltip:AddLine(18, colorCodes.GEM..grantedEffect.name) - -- Hardcoded to use 20% quality instead of grabbing from gem, this is for consistency and so we always show something - tooltip:AddLine(16, colorCodes.NORMAL.."At +20% Quality:") - for k, qual in pairs(qualityList) do - -- Do the stats one at a time because we're not guaranteed to get the descriptions in the same order we look at them here - local stats = { } - stats[qual[1]] = qual[2] * 20 - local descriptions = self.build.data.describeStats(stats, grantedEffect.statDescriptionScope) - -- line may be nil if the value results in no line due to not being enough quality - for _, line in ipairs(descriptions) do - if line then - -- Check if we have a handler for the mod in the gem's statMap or in the shared stat map for skills - if grantedEffect.statMap[qual[1]] or self.build.data.skillStatMap[qual[1]] then - tooltip:AddLine(16, colorCodes.MAGIC..line) - else - local line = colorCodes.UNSUPPORTED..line - line = main.notSupportedModTooltips and (line .. main.notSupportedTooltipText) or line - tooltip:AddLine(16, line) - end - end - end - end - end - -- Check if there is a quality of this type for the effect - if gemData and gemData.grantedEffect.qualityStats and gemData.grantedEffect.qualityStats[hoveredQuality.type] then - local qualityTable = gemData.grantedEffect.qualityStats[hoveredQuality.type] - addQualityLines(qualityTable, gemData.grantedEffect) - end - if gemData and gemData.secondaryGrantedEffect and gemData.secondaryGrantedEffect.qualityStats and gemData.secondaryGrantedEffect.qualityStats[hoveredQuality.type] then - local qualityTable = gemData.secondaryGrantedEffect.qualityStats[hoveredQuality.type] - tooltip:AddSeparator(10) - addQualityLines(qualityTable, gemData.secondaryGrantedEffect) - end - -- Add stat comparisons for hovered quality (based on set quality) - if self.displayGroup.gemList[index] then - local calcFunc, calcBase = self.build.calcsTab:GetMiscCalculator(self.build) - if calcFunc then - local tempQual = self.displayGroup.gemList[index].qualityId - self.displayGroup.gemList[index].qualityId = hoveredQuality.type - self:ProcessSocketGroup(self.displayGroup) - local output = calcFunc() - self.displayGroup.gemList[index].qualityId = tempQual - tooltip:AddSeparator(10) - self.build:AddStatComparesToTooltip(tooltip, calcBase, output, "^7Switching to this quality variant will give you:") - end - end - end - self.controls["gemSlot"..index.."QualityId"] = slot.qualityId - -- Gem quality - slot.quality = new("EditControl", {"LEFT",slot.qualityId,"RIGHT"}, {2, 0, 60, 20}, nil, nil, "%D", 2, function(buf) + slot.quality = new("EditControl", {"LEFT",slot.level,"RIGHT"}, {2, 0, 60, 20}, nil, nil, "%D", 2, function(buf) local gemInstance = self.displayGroup.gemList[index] if not gemInstance then - gemInstance = { nameSpec = "", level = self.defaultGemLevel or 20, quality = self.defaultGemQuality or 0, qualityId = "Default", enabled = true, enableGlobal1 = true, enableGlobal2 = true, count = 1, new = true } + gemInstance = { nameSpec = "", level = self.defaultGemLevel or 20, quality = self.defaultGemQuality or 0, enabled = true, enableGlobal1 = true, enableGlobal2 = true, count = 1, new = true } self.displayGroup.gemList[index] = gemInstance slot.level:SetText(gemInstance.level) slot.enabled.state = true @@ -854,16 +698,73 @@ function SkillsTabClass:CreateGemSlot(index) end self.controls["gemSlot"..index.."Quality"] = slot.quality + -- Imbued + slot.imbued = new("CheckBoxControl", {"LEFT",slot.quality,"RIGHT"}, {18, 0, 20}, nil, function(state) + slot.imbuedNameSpec.enabled = state + end) + slot.imbued.enabled = function() + return index <= #self.displayGroup.gemList + end + self.controls["gemSlot"..index.."Imbued"] = slot.imbued + + slot.imbuedNameSpec = new("GemSelectControl", { "LEFT", slot.imbued, "RIGHT" }, { 2, 0, 300, 20 }, self, index, function(gemId, addUndo) + if not self.displayGroup then + return + end + local id = index.."imbued" -- todo: how the hell do we handle the index of an imbued support + local gemInstance = self.displayGroup.gemList[id] + if not gemInstance then + if not gemId then + return + end + gemInstance = { + nameSpec = "", + level = 1, + quality = self.defaultGemQuality or 0, + enabled = true, + enableGlobal1 = true, + enableGlobal2 = true, + count = 1, + new = true + } + self.displayGroup.gemList[id] = gemInstance + slot.level:SetText(gemInstance.level) + slot.quality:SetText(gemInstance.quality) + slot.enabled.state = true + slot.enableGlobal1.state = true + slot.enableGlobal2.state = true + slot.count:SetText(gemInstance.count) + elseif gemId == gemInstance.gemId then + if addUndo then + self:AddUndoState() + end + return + end + gemInstance.gemId = gemId + gemInstance.skillId = nil + self:ProcessSocketGroup(self.displayGroup) + -- New gems need to be constrained by ProcessGemLevel + gemInstance.level = 1 -- todo: attempt to cap gem to level 1? + gemInstance.naturalMaxLevel = gemInstance.level + slot.level:SetText(gemInstance.level) + slot.count:SetText(gemInstance.count or 1) + if addUndo then + self:AddUndoState() + end + self.build.buildFlag = true + end, true) + slot.imbuedNameSpec:AddToTabGroup(self.controls.groupLabel) + self.controls["gemSlot"..index.."NameImbued"] = slot.imbuedNameSpec -- :todo "NameImbued" so we don't overwrite the actual active gem? + slot.imbuedNameSpec.enabled = false + -- Enable gem - slot.enabled = new("CheckBoxControl", {"LEFT",slot.quality,"RIGHT"}, {18, 0, 20}, nil, function(state) + slot.enabled = new("CheckBoxControl", {"LEFT",slot.imbuedNameSpec,"RIGHT"}, {18, 0, 20}, nil, function(state) local gemInstance = self.displayGroup.gemList[index] if not gemInstance then - gemInstance = { nameSpec = "", level = self.defaultGemLevel or 20, quality = self.defaultGemQuality or 0, qualityId = "Default", enabled = true, enableGlobal1 = true, enableGlobal2 = true, count = 1, new = true } + gemInstance = { nameSpec = "", level = self.defaultGemLevel or 20, quality = self.defaultGemQuality or 0, enabled = true, enableGlobal1 = true, enableGlobal2 = true, count = 1, new = true } self.displayGroup.gemList[index] = gemInstance slot.level:SetText(gemInstance.level) slot.quality:SetText(gemInstance.quality) - slot.qualityId.list = self:getGemAltQualityList(gemInstance.gemData) - slot.qualityId:SelByValue(gemInstance.qualityId, "type") slot.count:SetText(gemInstance.count) end if not gemInstance.gemData.vaalGem then @@ -899,12 +800,10 @@ function SkillsTabClass:CreateGemSlot(index) slot.count = new("EditControl", {"LEFT",slot.enabled,"RIGHT"}, {18, 0, 60, 20}, nil, nil, "%D", 2, function(buf) local gemInstance = self.displayGroup.gemList[index] if not gemInstance then - gemInstance = { nameSpec = "", level = self.defaultGemLevel or 20, quality = self.defaultGemQuality or 0, qualityId = "Default", enabled = true, enableGlobal1 = true, count = 1, new = true } + gemInstance = { nameSpec = "", level = self.defaultGemLevel or 20, quality = self.defaultGemQuality or 0, enabled = true, enableGlobal1 = true, count = 1, new = true } self.displayGroup.gemList[index] = gemInstance slot.level:SetText(gemInstance.level) - slot.qualityId.list = self:getGemAltQualityList(gemInstance.gemData) slot.quality:SetText(gemInstance.quality) - slot.qualityId:SelByValue(gemInstance.qualityId, "type") slot.enabled.state = true slot.enableGlobal1.state = true end @@ -984,17 +883,6 @@ function SkillsTabClass:CreateGemSlot(index) self.controls["gemSlot"..index.."EnableGlobal2"] = slot.enableGlobal2 end -function SkillsTabClass:getGemAltQualityList(gemData) - local altQualList = { } - - for indx, entry in ipairs(alternateGemQualityList) do - if gemData and (gemData.grantedEffect.qualityStats and gemData.grantedEffect.qualityStats[entry.type] or (gemData.secondaryGrantedEffect and gemData.secondaryGrantedEffect.qualityStats and gemData.secondaryGrantedEffect.qualityStats[entry.type])) then - t_insert(altQualList, entry) - end - end - return #altQualList > 0 and altQualList or {{ label = "Default", type = "Default" }} -end - -- Update the gem slot controls to reflect the currently displayed socket group function SkillsTabClass:UpdateGemSlots() if not self.displayGroup then @@ -1009,7 +897,6 @@ function SkillsTabClass:UpdateGemSlots() slot.nameSpec:SetText("") slot.level:SetText("") slot.quality:SetText("") - slot.qualityId:SelByValue("Default", "type") slot.enabled.state = false slot.count:SetText(1) else @@ -1058,8 +945,6 @@ function SkillsTabClass:ProcessGemLevel(gemData) end elseif self.defaultGemLevel == "normalMaximum" then return naturalMaxLevel - elseif self.defaultGemLevel == "levelOne" then - return 1 else -- self.defaultGemLevel == "characterLevel" local maxGemLevel = naturalMaxLevel if not grantedEffect.levels[maxGemLevel] then @@ -1170,8 +1055,6 @@ function SkillsTabClass:SetDisplayGroup(socketGroup) self.gemSlots[index].nameSpec:SetText(gemInstance.nameSpec) self.gemSlots[index].level:SetText(gemInstance.level) self.gemSlots[index].quality:SetText(gemInstance.quality) - self.gemSlots[index].qualityId.list = self:getGemAltQualityList(gemInstance.gemData) - self.gemSlots[index].qualityId:SelByValue(gemInstance.qualityId, "type") self.gemSlots[index].enabled.state = gemInstance.enabled self.gemSlots[index].enableGlobal1.state = gemInstance.enableGlobal1 self.gemSlots[index].enableGlobal2.state = gemInstance.enableGlobal2 From d2cb39855819737528ec5cd2c61b973a2256e0ba Mon Sep 17 00:00:00 2001 From: Peechey <92683202+Peechey@users.noreply.github.com> Date: Tue, 3 Mar 2026 00:20:15 -0600 Subject: [PATCH 02/12] clean up old list, re add variant --- src/Classes/SkillsTab.lua | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/Classes/SkillsTab.lua b/src/Classes/SkillsTab.lua index 63fbcd6743..3b7bb29d37 100644 --- a/src/Classes/SkillsTab.lua +++ b/src/Classes/SkillsTab.lua @@ -75,13 +75,6 @@ local sortGemTypeList = { { label = "Effective Hit Pool", type = "TotalEHP" }, } -local alternateGemQualityList ={ - { label = "Default", type = "Default" }, - { label = "Anomalous", type = "Alternate1" }, - { label = "Divergent", type = "Alternate2" }, - { label = "Phantasmal", type = "Alternate3" }, -} - local SkillsTabClass = newClass("SkillsTab", "UndoHandler", "ControlHost", "Control", function(self, build) self.UndoHandler() self.ControlHost() @@ -294,6 +287,22 @@ function SkillsTabClass:LoadSkill(node, skillSetId) gemInstance.nameSpec = sanitiseText(child.attrib.nameSpec or "") if child.attrib.gemId then local gemData + local possibleVariants = self.build.data.gemsByGameId[child.attrib.gemId] + if possibleVariants then + -- If it is a known gem, try to determine which variant is used + if child.attrib.variantId then + -- New save format from 3.23 that stores the specific variation (transfiguration) + gemData = possibleVariants[child.attrib.variantId] + elseif child.attrib.skillId then + -- Old format relying on the uniqueness of the granted effects id + for _, variant in pairs(possibleVariants) do + if variant.grantedEffectId == child.attrib.skillId then + gemData = variant + break + end + end + end + end if gemData then gemInstance.gemId = gemData.id gemInstance.skillId = gemData.grantedEffectId @@ -416,6 +425,7 @@ function SkillsTabClass:Save(xml) nameSpec = gemInstance.nameSpec, skillId = gemInstance.skillId, gemId = gemInstance.gemData and gemInstance.gemData.gameId, + variantId = gemInstance.gemData and gemInstance.gemData.variantId, level = tostring(gemInstance.level), quality = tostring(gemInstance.quality), enabled = tostring(gemInstance.enabled), From 5d120e0295ac8c76b848fd6a0b123df3ed14cdce Mon Sep 17 00:00:00 2001 From: Peechey <92683202+Peechey@users.noreply.github.com> Date: Sun, 15 Mar 2026 11:39:10 -0500 Subject: [PATCH 03/12] separate dropdown for imbued support, import, save/load --- src/Classes/ImportTab.lua | 4 ++ src/Classes/SkillsTab.lua | 139 +++++++++++++++++++++----------------- src/Modules/CalcSetup.lua | 46 +++++++------ 3 files changed, 108 insertions(+), 81 deletions(-) diff --git a/src/Classes/ImportTab.lua b/src/Classes/ImportTab.lua index d2a6232227..d31ff69fbc 100644 --- a/src/Classes/ImportTab.lua +++ b/src/Classes/ImportTab.lua @@ -1149,6 +1149,10 @@ function ImportTabClass:ImportSocketedItems(item, socketedItems, slotName) else t_insert(socketGroup.gemList, gemInstance) end + if socketedItem.builtInSupport then + socketGroup.imbuedSupport = socketedItem.builtInSupport:gsub("Supported by Level 1 ", "") + self.build.skillsTab.controls.imbuedSupport.selFunc(nil, socketedItem.builtInSupport:gsub("Supported by Level 1 ", ""), slotName) + end end end end diff --git a/src/Classes/SkillsTab.lua b/src/Classes/SkillsTab.lua index 3b7bb29d37..d3263f89cb 100644 --- a/src/Classes/SkillsTab.lua +++ b/src/Classes/SkillsTab.lua @@ -7,6 +7,7 @@ local pairs = pairs local ipairs = ipairs local t_insert = table.insert local t_remove = table.remove +local t_sort = table.sort local m_min = math.min local m_max = math.max @@ -145,7 +146,7 @@ local SkillsTabClass = newClass("SkillsTab", "UndoHandler", "ControlHost", "Cont self.showSupportGemTypes = value.show end) self.controls.showSupportGemTypesLabel = new("LabelControl", { "RIGHT", self.controls.showSupportGemTypes, "LEFT" }, { -4, 0, 0, 16 }, "^7Show support gems:") - self.controls.showLegacyGems = new("CheckBoxControl", { "TOPLEFT", self.controls.groupList, "BOTTOMLEFT" }, { optionInputsX, optionInputsY + 190, 20 }, "^7Show legacy gems:", function(state) + self.controls.showLegacyGems = new("CheckBoxControl", { "TOPLEFT", self.controls.groupList, "BOTTOMLEFT" }, { optionInputsX, optionInputsY + 166, 20 }, "^7Show legacy gems:", function(state) self.showLegacyGems = state end) @@ -166,6 +167,16 @@ local SkillsTabClass = newClass("SkillsTab", "UndoHandler", "ControlHost", "Cont end) self.controls.groupSlotLabel = new("LabelControl", { "TOPLEFT", self.anchorGroupDetail, "TOPLEFT" }, { 0, 30, 0, 16 }, "^7Socketed in:") self.controls.groupSlot = new("DropDownControl", { "TOPLEFT", self.anchorGroupDetail, "TOPLEFT" }, { 85, 28, 130, 20 }, groupSlotDropList, function(index, value) + -- maintain imbued support to new slot + if self.imbuedSupportBySlot[self.displayGroup.slot] then + if value.label ~= "None" then + self.imbuedSupportBySlot[value.label] = copyTable(self.imbuedSupportBySlot[self.displayGroup.slot], true) + else + self.controls.imbuedSupport.selIndex = 1 -- reset dropdown to None if socketedIn switched to None + end + self.imbuedSupportBySlot[self.displayGroup.slot] = nil + end + self.displayGroup.slot = value.slotName self:AddUndoState() self.build.buildFlag = true @@ -198,6 +209,59 @@ local SkillsTabClass = newClass("SkillsTab", "UndoHandler", "ControlHost", "Cont self:AddUndoState() self.build.buildFlag = true end) + + local imbuedSupportList = { } + local gemColor = "^7" + for _, gem in pairs(data.gems) do + if gem.tagString:match("Support") and not gem.tagString:match("Exceptional") and not gem.name:match("Awakened") then + -- wanted to add color but with sorting by name, it scrambled the gems AND we use value in the code later in CalcSetup and breaks Dropdown:SelByValue so we'd have to scrub it anyways + --if gem.grantedEffect then + -- if gem.grantedEffect.color == 1 then + -- gemColor = colorCodes.STRENGTH + -- elseif gem.grantedEffect.color == 2 then + -- gemColor = colorCodes.DEXTERITY + -- elseif gem.grantedEffect.color == 3 then + -- gemColor = colorCodes.INTELLIGENCE + -- end + --end + t_insert(imbuedSupportList, gem.name) + end + end + t_sort(imbuedSupportList) + t_insert(imbuedSupportList, 1, "None") + + self.imbuedSupportBySlot = { } + self.controls.imbuedSupportLabel = new("LabelControl", { "LEFT", self.controls.includeInFullDPS, "RIGHT" }, { 12, 0, 0, 16 }, colorCodes.POSITIVE.."Imbued Support:") + self.controls.imbuedSupport = new("DropDownControl", { "LEFT", self.controls.imbuedSupportLabel, "RIGHT" }, { 8, 0, 250, 20 }, imbuedSupportList, function(_, value, slotName) -- slotName used on Import + local gemName = value:gsub("%^7", "") + if value == "None" then + self.imbuedSupportBySlot[self.displayGroup.slot] = nil + else + if self.displayGroup then + self.displayGroup.imbuedSupport = gemName + end + self.imbuedSupportBySlot[slotName or self.displayGroup.slot] = data.gems[data.gemForBaseName[gemName:lower().." support"]].grantedEffect + end + self.build.buildFlag = true + end) + + self.controls.imbuedSupport.enabled = function() + if self.displayGroup.slot then + self.controls.imbuedSupport.tooltipText = nil + return true + else + self.controls.imbuedSupport.tooltipText = "Imbued supports must be socketed in an item." + return false + end + end + -- todo: tooltip to show imbued disabled if socketed in is None + --self.controls.imbuedSupport.tooltipFunc = function(tooltip) + -- tooltip:Clear() + -- if not self.controls.imbuedSupport.enabled then + -- tooltip:AddLine(16, "^7Imbued supports must be socketed in an item.") + -- end + --end + self.controls.groupCountLabel = new("LabelControl", { "LEFT", self.controls.includeInFullDPS, "RIGHT" }, { 16, 0, 0, 16 }, "Count:") self.controls.groupCountLabel.shown = function() return self.displayGroup.source ~= nil @@ -282,6 +346,11 @@ function SkillsTabClass:LoadSkill(node, skillSetId) socketGroup.mainActiveSkill = tonumber(node.attrib.mainActiveSkill) or 1 socketGroup.mainActiveSkillCalcs = tonumber(node.attrib.mainActiveSkillCalcs) or 1 socketGroup.gemList = { } + if node.attrib.imbuedSupport and node.attrib.slot then + socketGroup.imbuedSupport = node.attrib.imbuedSupport + self.controls.imbuedSupport.selFunc(nil, socketGroup.imbuedSupport, socketGroup.slot) + end + for _, child in ipairs(node) do local gemInstance = { } gemInstance.nameSpec = sanitiseText(child.attrib.nameSpec or "") @@ -419,6 +488,7 @@ function SkillsTabClass:Save(xml) source = socketGroup.source, mainActiveSkill = tostring(socketGroup.mainActiveSkill), mainActiveSkillCalcs = tostring(socketGroup.mainActiveSkillCalcs), + imbuedSupport = socketGroup.imbuedSupport and tostring(socketGroup.imbuedSupport), } } for _, gemInstance in ipairs(socketGroup.gemList) do t_insert(node, { elem = "Gem", attrib = { @@ -628,6 +698,7 @@ function SkillsTabClass:CreateGemSlot(index) slot.enableGlobal1.state = true slot.enableGlobal2.state = true slot.count:SetText(gemInstance.count) + --slot.imbued.state = false elseif gemId == gemInstance.gemId then if addUndo then self:AddUndoState() @@ -638,7 +709,7 @@ function SkillsTabClass:CreateGemSlot(index) gemInstance.skillId = nil self:ProcessSocketGroup(self.displayGroup) -- New gems need to be constrained by ProcessGemLevel - gemInstance.level = self:ProcessGemLevel(gemInstance.gemData) + gemInstance.level = self:ProcessGemLevel(gemInstance.gemData, self.addingImbuedSupport) gemInstance.naturalMaxLevel = gemInstance.level slot.level:SetText(gemInstance.level) slot.count:SetText(gemInstance.count or 1) @@ -708,67 +779,8 @@ function SkillsTabClass:CreateGemSlot(index) end self.controls["gemSlot"..index.."Quality"] = slot.quality - -- Imbued - slot.imbued = new("CheckBoxControl", {"LEFT",slot.quality,"RIGHT"}, {18, 0, 20}, nil, function(state) - slot.imbuedNameSpec.enabled = state - end) - slot.imbued.enabled = function() - return index <= #self.displayGroup.gemList - end - self.controls["gemSlot"..index.."Imbued"] = slot.imbued - - slot.imbuedNameSpec = new("GemSelectControl", { "LEFT", slot.imbued, "RIGHT" }, { 2, 0, 300, 20 }, self, index, function(gemId, addUndo) - if not self.displayGroup then - return - end - local id = index.."imbued" -- todo: how the hell do we handle the index of an imbued support - local gemInstance = self.displayGroup.gemList[id] - if not gemInstance then - if not gemId then - return - end - gemInstance = { - nameSpec = "", - level = 1, - quality = self.defaultGemQuality or 0, - enabled = true, - enableGlobal1 = true, - enableGlobal2 = true, - count = 1, - new = true - } - self.displayGroup.gemList[id] = gemInstance - slot.level:SetText(gemInstance.level) - slot.quality:SetText(gemInstance.quality) - slot.enabled.state = true - slot.enableGlobal1.state = true - slot.enableGlobal2.state = true - slot.count:SetText(gemInstance.count) - elseif gemId == gemInstance.gemId then - if addUndo then - self:AddUndoState() - end - return - end - gemInstance.gemId = gemId - gemInstance.skillId = nil - self:ProcessSocketGroup(self.displayGroup) - -- New gems need to be constrained by ProcessGemLevel - gemInstance.level = 1 -- todo: attempt to cap gem to level 1? - gemInstance.naturalMaxLevel = gemInstance.level - slot.level:SetText(gemInstance.level) - slot.count:SetText(gemInstance.count or 1) - if addUndo then - self:AddUndoState() - end - self.build.buildFlag = true - end, true) - slot.imbuedNameSpec:AddToTabGroup(self.controls.groupLabel) - self.controls["gemSlot"..index.."NameImbued"] = slot.imbuedNameSpec -- :todo "NameImbued" so we don't overwrite the actual active gem? - slot.imbuedNameSpec.enabled = false - -- Enable gem - slot.enabled = new("CheckBoxControl", {"LEFT",slot.imbuedNameSpec,"RIGHT"}, {18, 0, 20}, nil, function(state) + slot.enabled = new("CheckBoxControl", {"LEFT",slot.quality,"RIGHT"}, {18, 0, 20}, nil, function(state) local gemInstance = self.displayGroup.gemList[index] if not gemInstance then gemInstance = { nameSpec = "", level = self.defaultGemLevel or 20, quality = self.defaultGemQuality or 0, enabled = true, enableGlobal1 = true, enableGlobal2 = true, count = 1, new = true } @@ -955,6 +967,8 @@ function SkillsTabClass:ProcessGemLevel(gemData) end elseif self.defaultGemLevel == "normalMaximum" then return naturalMaxLevel + elseif self.defaultGemLevel == "levelOne" then + return 1 else -- self.defaultGemLevel == "characterLevel" local maxGemLevel = naturalMaxLevel if not grantedEffect.levels[maxGemLevel] then @@ -1058,6 +1072,7 @@ function SkillsTabClass:SetDisplayGroup(socketGroup) self.controls.groupEnabled.state = socketGroup.enabled self.controls.includeInFullDPS.state = socketGroup.includeInFullDPS and socketGroup.enabled self.controls.groupCount:SetText(socketGroup.groupCount or 1) + self.controls.imbuedSupport:SelByValue(socketGroup.imbuedSupport or "None") -- Update the gem slot controls self:UpdateGemSlots() diff --git a/src/Modules/CalcSetup.lua b/src/Modules/CalcSetup.lua index b1ed688536..18d31f50e8 100644 --- a/src/Modules/CalcSetup.lua +++ b/src/Modules/CalcSetup.lua @@ -1465,31 +1465,39 @@ function calcs.initEnv(build, mode, override, specEnv) t_insert(targetListList, supportLists[group]) end + local function addExtraSupports(value, grantedEffect, level) + local grantedEffect = grantedEffect or env.data.skills[value.skillId] + -- Some skill gems share the same name as support gems, e.g. Barrage. + -- Since a support gem is expected here, if the first lookup returns a skill, then + -- prepending "Support" to the skillId will find the support version of the gem. + if value and grantedEffect and not grantedEffect.support then + grantedEffect = env.data.skills["Support"..value.skillId] + grantedEffect.fromItem = true + end + if grantedEffect then + for _, targetList in ipairs(targetListList) do + t_insert(targetList, { + grantedEffect = grantedEffect, + gemData = env.data.gems[env.data.gemForBaseName[grantedEffect.name:lower()] or env.data.gemForBaseName[(grantedEffect.name .. " Support"):lower()]], + level = level or value.level, + quality = 0, + enabled = true, + }) + end + end + end + -- if not unique item that provides skills if not group.source then -- Add extra supports from the item this group is socketed in for _, value in ipairs(env.modDB:List(groupCfg, "ExtraSupport")) do - local grantedEffect = env.data.skills[value.skillId] - -- Some skill gems share the same name as support gems, e.g. Barrage. - -- Since a support gem is expected here, if the first lookup returns a skill, then - -- prepending "Support" to the skillId will find the support version of the gem. - if grantedEffect and not grantedEffect.support then - grantedEffect = env.data.skills["Support"..value.skillId] - end - grantedEffect.fromItem = true - if grantedEffect then - for _, targetList in ipairs(targetListList) do - t_insert(targetList, { - grantedEffect = grantedEffect, - gemData = env.data.gems[env.data.gemForBaseName[grantedEffect.name:lower()] or env.data.gemForBaseName[(grantedEffect.name .. " Support"):lower()]], - level = value.level, - quality = 0, - enabled = true, - }) - end - end + addExtraSupports(value) end end + -- if the slot has an imbued support, add it as an ExtraSupport + if build.skillsTab.imbuedSupportBySlot and build.skillsTab.imbuedSupportBySlot[slotName] then + addExtraSupports(nil, build.skillsTab.imbuedSupportBySlot[slotName], 1) + end for gemIndex, gemInstance in ipairs(group.gemList) do -- Add support gems from this group From c244ce3ce88dcce82ca2f7e54f426a54f73e32e8 Mon Sep 17 00:00:00 2001 From: Peechey <92683202+Peechey@users.noreply.github.com> Date: Mon, 16 Mar 2026 14:36:53 -0500 Subject: [PATCH 04/12] disable imbued for other socketGroups of a slot if another already has an imbued don't show imbued label/dropdown for skills from items --- src/Classes/SkillsTab.lua | 26 ++++++++++++-------------- src/Modules/CalcSetup.lua | 2 +- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/Classes/SkillsTab.lua b/src/Classes/SkillsTab.lua index d3263f89cb..1bc21d44e8 100644 --- a/src/Classes/SkillsTab.lua +++ b/src/Classes/SkillsTab.lua @@ -168,11 +168,12 @@ local SkillsTabClass = newClass("SkillsTab", "UndoHandler", "ControlHost", "Cont self.controls.groupSlotLabel = new("LabelControl", { "TOPLEFT", self.anchorGroupDetail, "TOPLEFT" }, { 0, 30, 0, 16 }, "^7Socketed in:") self.controls.groupSlot = new("DropDownControl", { "TOPLEFT", self.anchorGroupDetail, "TOPLEFT" }, { 85, 28, 130, 20 }, groupSlotDropList, function(index, value) -- maintain imbued support to new slot - if self.imbuedSupportBySlot[self.displayGroup.slot] then + if self.imbuedSupportBySlot[self.displayGroup.slot] and self.displayGroup.imbuedSupport then if value.label ~= "None" then self.imbuedSupportBySlot[value.label] = copyTable(self.imbuedSupportBySlot[self.displayGroup.slot], true) else self.controls.imbuedSupport.selIndex = 1 -- reset dropdown to None if socketedIn switched to None + self.displayGroup.imbuedSupport = nil -- reset saved support to None end self.imbuedSupportBySlot[self.displayGroup.slot] = nil end @@ -235,18 +236,19 @@ local SkillsTabClass = newClass("SkillsTab", "UndoHandler", "ControlHost", "Cont self.controls.imbuedSupport = new("DropDownControl", { "LEFT", self.controls.imbuedSupportLabel, "RIGHT" }, { 8, 0, 250, 20 }, imbuedSupportList, function(_, value, slotName) -- slotName used on Import local gemName = value:gsub("%^7", "") if value == "None" then - self.imbuedSupportBySlot[self.displayGroup.slot] = nil + self.imbuedSupportBySlot[slotName or self.displayGroup.slot] = nil else - if self.displayGroup then - self.displayGroup.imbuedSupport = gemName - end self.imbuedSupportBySlot[slotName or self.displayGroup.slot] = data.gems[data.gemForBaseName[gemName:lower().." support"]].grantedEffect end + + if self.displayGroup then + self.displayGroup.imbuedSupport = gemName + end self.build.buildFlag = true end) - self.controls.imbuedSupport.enabled = function() - if self.displayGroup.slot then + -- socketedIn must be set and the displayGroup must have an imbued, otherwise disable the imbued dropdown + if self.displayGroup.slot and ((self.imbuedSupportBySlot[self.displayGroup.slot] and (self.displayGroup.imbuedSupport and self.displayGroup.imbuedSupport ~= "None") or not self.imbuedSupportBySlot[self.displayGroup.slot])) then self.controls.imbuedSupport.tooltipText = nil return true else @@ -254,13 +256,9 @@ local SkillsTabClass = newClass("SkillsTab", "UndoHandler", "ControlHost", "Cont return false end end - -- todo: tooltip to show imbued disabled if socketed in is None - --self.controls.imbuedSupport.tooltipFunc = function(tooltip) - -- tooltip:Clear() - -- if not self.controls.imbuedSupport.enabled then - -- tooltip:AddLine(16, "^7Imbued supports must be socketed in an item.") - -- end - --end + self.controls.imbuedSupportLabel.shown = function() -- don't show imbued for skills from items + return not self.displayGroup.source + end self.controls.groupCountLabel = new("LabelControl", { "LEFT", self.controls.includeInFullDPS, "RIGHT" }, { 16, 0, 0, 16 }, "Count:") self.controls.groupCountLabel.shown = function() diff --git a/src/Modules/CalcSetup.lua b/src/Modules/CalcSetup.lua index 18d31f50e8..55ed9df9cd 100644 --- a/src/Modules/CalcSetup.lua +++ b/src/Modules/CalcSetup.lua @@ -1495,7 +1495,7 @@ function calcs.initEnv(build, mode, override, specEnv) end end -- if the slot has an imbued support, add it as an ExtraSupport - if build.skillsTab.imbuedSupportBySlot and build.skillsTab.imbuedSupportBySlot[slotName] then + if build.skillsTab.imbuedSupportBySlot and build.skillsTab.imbuedSupportBySlot[slotName] and (group.imbuedSupport and group.imbuedSupport ~= "None") then addExtraSupports(nil, build.skillsTab.imbuedSupportBySlot[slotName], 1) end From 8a0333454eb8563cf8a1e92ca07d616ec6577911 Mon Sep 17 00:00:00 2001 From: Peechey <92683202+Peechey@users.noreply.github.com> Date: Mon, 16 Mar 2026 18:26:32 -0500 Subject: [PATCH 05/12] clean up old code --- src/Classes/SkillsTab.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Classes/SkillsTab.lua b/src/Classes/SkillsTab.lua index 1bc21d44e8..46fb5e6bae 100644 --- a/src/Classes/SkillsTab.lua +++ b/src/Classes/SkillsTab.lua @@ -707,7 +707,7 @@ function SkillsTabClass:CreateGemSlot(index) gemInstance.skillId = nil self:ProcessSocketGroup(self.displayGroup) -- New gems need to be constrained by ProcessGemLevel - gemInstance.level = self:ProcessGemLevel(gemInstance.gemData, self.addingImbuedSupport) + gemInstance.level = self:ProcessGemLevel(gemInstance.gemData) gemInstance.naturalMaxLevel = gemInstance.level slot.level:SetText(gemInstance.level) slot.count:SetText(gemInstance.count or 1) From e8c32b9b1aefc4fc424d5daab37b99e57fef1b86 Mon Sep 17 00:00:00 2001 From: Peechey <92683202+Peechey@users.noreply.github.com> Date: Tue, 17 Mar 2026 23:19:59 -0500 Subject: [PATCH 06/12] refactor to use GemSelectControl, dps sort integrated into new imbued control --- src/Classes/GemSelectControl.lua | 57 +++++++++++++--------- src/Classes/ImportTab.lua | 2 +- src/Classes/SkillsTab.lua | 83 ++++++++++++++++---------------- src/Modules/CalcSetup.lua | 2 +- 4 files changed, 78 insertions(+), 66 deletions(-) diff --git a/src/Classes/GemSelectControl.lua b/src/Classes/GemSelectControl.lua index 5caac872a4..2d3439ff02 100644 --- a/src/Classes/GemSelectControl.lua +++ b/src/Classes/GemSelectControl.lua @@ -12,6 +12,7 @@ local m_max = math.max local m_floor = math.floor local toolTipText = "Prefix tag searches with a colon and exclude tags with a dash. e.g. :fire:lightning:-cold:area" +local imbuedTooltipText = "Socketed in must be set in order to add an imbued support. Only one imbued support is allowed per socketed in." local altQualMap = { ["Default"] = "", ["Alternate1"] = "Anomalous ", @@ -19,7 +20,7 @@ local altQualMap = { ["Alternate3"] = "Phantasmal ", } -local GemSelectClass = newClass("GemSelectControl", "EditControl", function(self, anchor, rect, skillsTab, index, changeFunc, forceTooltip) +local GemSelectClass = newClass("GemSelectControl", "EditControl", function(self, anchor, rect, skillsTab, index, changeFunc, forceTooltip, imbued) self.EditControl(anchor, rect, nil, nil, "^ %a':-") self.controls.scrollBar = new("ScrollBarControl", { "TOPRIGHT", self, "TOPRIGHT" }, {-1, 0, 18, 0}, (self.height - 4) * 4) self.controls.scrollBar.y = function() @@ -56,6 +57,7 @@ local GemSelectClass = newClass("GemSelectControl", "EditControl", function(self lifeReservationFlat = "Life", lifeReservationPercent = "LifePercent", } + self.imbuedSelect = imbued end) function GemSelectClass:CalcOutputWithThisGem(calcFunc, gemData, qualityId, useFullDPS) @@ -81,7 +83,7 @@ function GemSelectClass:CalcOutputWithThisGem(calcFunc, gemData, qualityId, useF -- Create gemInstance to represent the hovered gem local gemInstance = gemList[self.index] - gemInstance.level = self.skillsTab:ProcessGemLevel(gemData) + gemInstance.level = self.skillsTab:ProcessGemLevel(gemData, self.imbuedSelect) gemInstance.gemData = gemData gemInstance.displayEffect = nil if gemInstance.qualityId == nil or gemInstance.qualityId == "" then @@ -136,6 +138,11 @@ function GemSelectClass:FilterSupport(gemId, gemData) if gemData.grantedEffect.legacy and not self.skillsTab.showLegacyGems then return false end + + if self.imbuedSelect then + return (gemData.grantedEffect.support and not (gemData.tagString:match("Exceptional"))) + end + return (not gemData.grantedEffect.support or showSupportTypes == "ALL" or (showSupportTypes == "NORMAL" and not gemData.grantedEffect.plusVersionOf) @@ -483,7 +490,7 @@ function GemSelectClass:Draw(viewPort, noTooltip) local qualityType = self:GetQualityType(self.list[self.hoverSel]) local output= self:CalcOutputWithThisGem(calcFunc, gemData, qualityType, self.skillsTab.sortGemsByDPSField == "FullDPS") local gemInstance = { - level = self.skillsTab:ProcessGemLevel(gemData), + level = self.skillsTab:ProcessGemLevel(gemData, self.imbuedSelect), qualityId = qualityType, quality = self.skillsTab.defaultGemQuality or 0, count = 1, @@ -531,7 +538,7 @@ function GemSelectClass:Draw(viewPort, noTooltip) end self:AddGemTooltip(gemInstance) else - self.tooltip:AddLine(16, toolTipText) + self.tooltip:AddLine(16, self.imbuedSelect and imbuedTooltipText or toolTipText) end colorS = 0.5 @@ -546,23 +553,25 @@ function GemSelectClass:Draw(viewPort, noTooltip) self.tooltip:AddLine(16, "Only show Active gems") end - -- support shortcut - sx = x + width - 16 - 2 - SetDrawColor(colorS,colorS,colorS) - DrawImage(nil, sx, y+2, 16, height-4) - SetDrawColor(0,0,0) - DrawImage(nil, sx+1, y+2, 16-2, height-4) - SetDrawColor(colorS,colorS,colorS) - DrawString(sx + 8, y, "CENTER_X", height - 2, "VAR", "S") - - -- active shortcut - sx = x + width - (16*2) - (2*2) - SetDrawColor(colorA,colorA,colorA) - DrawImage(nil, sx, y+2, 16, height-4) - SetDrawColor(0,0,0) - DrawImage(nil, sx+1, y+2, 16-2, height-4) - SetDrawColor(colorA,colorA,colorA) - DrawString(sx + 8, y, "CENTER_X", height - 2, "VAR", "A") + if not self.imbuedSelect then + -- support shortcut + sx = x + width - 16 - 2 + SetDrawColor(colorS,colorS,colorS) + DrawImage(nil, sx, y+2, 16, height-4) + SetDrawColor(0,0,0) + DrawImage(nil, sx+1, y+2, 16-2, height-4) + SetDrawColor(colorS,colorS,colorS) + DrawString(sx + 8, y, "CENTER_X", height - 2, "VAR", "S") + + -- active shortcut + sx = x + width - (16*2) - (2*2) + SetDrawColor(colorA,colorA,colorA) + DrawImage(nil, sx, y+2, 16, height-4) + SetDrawColor(0,0,0) + DrawImage(nil, sx+1, y+2, 16-2, height-4) + SetDrawColor(colorA,colorA,colorA) + DrawString(sx + 8, y, "CENTER_X", height - 2, "VAR", "A") + end SetDrawLayer(nil, 10) self.tooltip:Draw(x, y, width, height, viewPort) @@ -900,4 +909,8 @@ function GemSelectClass:OnKeyUp(key) end local newSel = self.EditControl:OnKeyUp(key) return newSel == self.EditControl and self or newSel -end \ No newline at end of file +end + +function GemSelectClass:UpdateIndex(index) + self.index = index +end diff --git a/src/Classes/ImportTab.lua b/src/Classes/ImportTab.lua index d31ff69fbc..b6813831c6 100644 --- a/src/Classes/ImportTab.lua +++ b/src/Classes/ImportTab.lua @@ -1151,7 +1151,7 @@ function ImportTabClass:ImportSocketedItems(item, socketedItems, slotName) end if socketedItem.builtInSupport then socketGroup.imbuedSupport = socketedItem.builtInSupport:gsub("Supported by Level 1 ", "") - self.build.skillsTab.controls.imbuedSupport.selFunc(nil, socketedItem.builtInSupport:gsub("Supported by Level 1 ", ""), slotName) + self.build.skillsTab.controls.imbuedSupport.gemChangeFunc(data.gems[data.gemForBaseName[socketGroup.imbuedSupport:lower().." support"]], nil, nil, slotName) end end end diff --git a/src/Classes/SkillsTab.lua b/src/Classes/SkillsTab.lua index 46fb5e6bae..d2d71a6f56 100644 --- a/src/Classes/SkillsTab.lua +++ b/src/Classes/SkillsTab.lua @@ -169,10 +169,11 @@ local SkillsTabClass = newClass("SkillsTab", "UndoHandler", "ControlHost", "Cont self.controls.groupSlot = new("DropDownControl", { "TOPLEFT", self.anchorGroupDetail, "TOPLEFT" }, { 85, 28, 130, 20 }, groupSlotDropList, function(index, value) -- maintain imbued support to new slot if self.imbuedSupportBySlot[self.displayGroup.slot] and self.displayGroup.imbuedSupport then - if value.label ~= "None" then + if value.label ~= "None" and not self.imbuedSupportBySlot[value.label] then self.imbuedSupportBySlot[value.label] = copyTable(self.imbuedSupportBySlot[self.displayGroup.slot], true) else - self.controls.imbuedSupport.selIndex = 1 -- reset dropdown to None if socketedIn switched to None + self.controls.imbuedSupport.gemId = nil + self.controls.imbuedSupport:SetText("") self.displayGroup.imbuedSupport = nil -- reset saved support to None end self.imbuedSupportBySlot[self.displayGroup.slot] = nil @@ -211,54 +212,38 @@ local SkillsTabClass = newClass("SkillsTab", "UndoHandler", "ControlHost", "Cont self.build.buildFlag = true end) - local imbuedSupportList = { } - local gemColor = "^7" - for _, gem in pairs(data.gems) do - if gem.tagString:match("Support") and not gem.tagString:match("Exceptional") and not gem.name:match("Awakened") then - -- wanted to add color but with sorting by name, it scrambled the gems AND we use value in the code later in CalcSetup and breaks Dropdown:SelByValue so we'd have to scrub it anyways - --if gem.grantedEffect then - -- if gem.grantedEffect.color == 1 then - -- gemColor = colorCodes.STRENGTH - -- elseif gem.grantedEffect.color == 2 then - -- gemColor = colorCodes.DEXTERITY - -- elseif gem.grantedEffect.color == 3 then - -- gemColor = colorCodes.INTELLIGENCE - -- end - --end - t_insert(imbuedSupportList, gem.name) - end - end - t_sort(imbuedSupportList) - t_insert(imbuedSupportList, 1, "None") - self.imbuedSupportBySlot = { } self.controls.imbuedSupportLabel = new("LabelControl", { "LEFT", self.controls.includeInFullDPS, "RIGHT" }, { 12, 0, 0, 16 }, colorCodes.POSITIVE.."Imbued Support:") - self.controls.imbuedSupport = new("DropDownControl", { "LEFT", self.controls.imbuedSupportLabel, "RIGHT" }, { 8, 0, 250, 20 }, imbuedSupportList, function(_, value, slotName) -- slotName used on Import - local gemName = value:gsub("%^7", "") - if value == "None" then - self.imbuedSupportBySlot[slotName or self.displayGroup.slot] = nil + self.controls.imbuedSupport = new("GemSelectControl", { "LEFT", self.controls.imbuedSupportLabel, "RIGHT" }, { 8, 0, 250, 20 }, self, 1, function(gemData, _, _, slotName) -- slotName used on Import + if gemData and (type(gemData) == "string" or gemData.id) then + self.imbuedSupportBySlot[slotName or self.displayGroup.slot] = data.gems[gemData.id or gemData].grantedEffect + if self.displayGroup then + self.displayGroup.imbuedSupport = data.gems[gemData.id or gemData].name + end + self.build.buildFlag = true else - self.imbuedSupportBySlot[slotName or self.displayGroup.slot] = data.gems[data.gemForBaseName[gemName:lower().." support"]].grantedEffect - end - - if self.displayGroup then - self.displayGroup.imbuedSupport = gemName + self.imbuedSupportBySlot[slotName or self.displayGroup.slot] = nil end - self.build.buildFlag = true - end) + end, nil, true) self.controls.imbuedSupport.enabled = function() -- socketedIn must be set and the displayGroup must have an imbued, otherwise disable the imbued dropdown - if self.displayGroup.slot and ((self.imbuedSupportBySlot[self.displayGroup.slot] and (self.displayGroup.imbuedSupport and self.displayGroup.imbuedSupport ~= "None") or not self.imbuedSupportBySlot[self.displayGroup.slot])) then - self.controls.imbuedSupport.tooltipText = nil + if self.displayGroup.slot and ((self.imbuedSupportBySlot[self.displayGroup.slot] and self.displayGroup.imbuedSupport) or not self.imbuedSupportBySlot[self.displayGroup.slot]) then return true else - self.controls.imbuedSupport.tooltipText = "Imbued supports must be socketed in an item." return false end end self.controls.imbuedSupportLabel.shown = function() -- don't show imbued for skills from items return not self.displayGroup.source end + self.controls.imbuedSupportClear = new("ButtonControl", { "LEFT", self.controls.imbuedSupportLabel, "RIGHT" }, { 264, 0, 80, 20}, "Clear", function() + self.controls.imbuedSupport.gemId = nil + self.controls.imbuedSupport:SetText("") + self.displayGroup.imbuedSupport = nil + self.imbuedSupportBySlot[self.displayGroup.slot] = nil + + self.build.buildFlag = true + end) self.controls.groupCountLabel = new("LabelControl", { "LEFT", self.controls.includeInFullDPS, "RIGHT" }, { 16, 0, 0, 16 }, "Count:") self.controls.groupCountLabel.shown = function() @@ -346,7 +331,7 @@ function SkillsTabClass:LoadSkill(node, skillSetId) socketGroup.gemList = { } if node.attrib.imbuedSupport and node.attrib.slot then socketGroup.imbuedSupport = node.attrib.imbuedSupport - self.controls.imbuedSupport.selFunc(nil, socketGroup.imbuedSupport, socketGroup.slot) + self.controls.imbuedSupport.gemChangeFunc(data.gems[data.gemForBaseName[socketGroup.imbuedSupport:lower().." support"]], nil, nil, socketGroup.slot) end for _, child in ipairs(node) do @@ -630,6 +615,12 @@ function SkillsTabClass:PasteSocketGroup(testInput) end end +local function updateImbuedSupportIndex(control, gemListCount) + if gemListCount > 0 then + control.index = gemListCount + 1 + end +end + -- Create the controls for editing the gem at a given index function SkillsTabClass:CreateGemSlot(index) local slot = { } @@ -649,6 +640,7 @@ function SkillsTabClass:CreateGemSlot(index) self.gemSlots[index2].enableGlobal2.state = gemInstance.enableGlobal2 self.gemSlots[index2].count:SetText(gemInstance.count or 1) end + updateImbuedSupportIndex(self.controls.imbuedSupport, #self.displayGroup.gemList) self:AddUndoState() self.build.buildFlag = true end) @@ -952,10 +944,12 @@ function SkillsTabClass:FindSkillGem(nameSpec) return "Unrecognised gem name '" .. nameSpec .. "'" end -function SkillsTabClass:ProcessGemLevel(gemData) +function SkillsTabClass:ProcessGemLevel(gemData, imbued) local grantedEffect = gemData.grantedEffect local naturalMaxLevel = gemData.naturalMaxLevel - if self.defaultGemLevel == "awakenedMaximum" then + if imbued or self.defaultGemLevel == "levelOne" then + return 1 + elseif self.defaultGemLevel == "awakenedMaximum" then return naturalMaxLevel + 1 elseif self.defaultGemLevel == "corruptedMaximum" then if grantedEffect.plusVersionOf then @@ -965,8 +959,6 @@ function SkillsTabClass:ProcessGemLevel(gemData) end elseif self.defaultGemLevel == "normalMaximum" then return naturalMaxLevel - elseif self.defaultGemLevel == "levelOne" then - return 1 else -- self.defaultGemLevel == "characterLevel" local maxGemLevel = naturalMaxLevel if not grantedEffect.levels[maxGemLevel] then @@ -1056,6 +1048,7 @@ function SkillsTabClass:ProcessSocketGroup(socketGroup) end end end + updateImbuedSupportIndex(self.controls.imbuedSupport, #socketGroup.gemList) end -- Set the skill to be displayed/edited @@ -1070,7 +1063,13 @@ function SkillsTabClass:SetDisplayGroup(socketGroup) self.controls.groupEnabled.state = socketGroup.enabled self.controls.includeInFullDPS.state = socketGroup.includeInFullDPS and socketGroup.enabled self.controls.groupCount:SetText(socketGroup.groupCount or 1) - self.controls.imbuedSupport:SelByValue(socketGroup.imbuedSupport or "None") + if socketGroup.imbuedSupport then + self.controls.imbuedSupport.gemId = data.gems[data.gemForBaseName[socketGroup.imbuedSupport:lower().." support"]] + self.controls.imbuedSupport:SetText(socketGroup.imbuedSupport) + else + self.controls.imbuedSupport.gemId = nil + self.controls.imbuedSupport:SetText("") + end -- Update the gem slot controls self:UpdateGemSlots() diff --git a/src/Modules/CalcSetup.lua b/src/Modules/CalcSetup.lua index 55ed9df9cd..962a82d1f2 100644 --- a/src/Modules/CalcSetup.lua +++ b/src/Modules/CalcSetup.lua @@ -1495,7 +1495,7 @@ function calcs.initEnv(build, mode, override, specEnv) end end -- if the slot has an imbued support, add it as an ExtraSupport - if build.skillsTab.imbuedSupportBySlot and build.skillsTab.imbuedSupportBySlot[slotName] and (group.imbuedSupport and group.imbuedSupport ~= "None") then + if build.skillsTab.imbuedSupportBySlot and build.skillsTab.imbuedSupportBySlot[slotName] and group.imbuedSupport then addExtraSupports(nil, build.skillsTab.imbuedSupportBySlot[slotName], 1) end From b79243f474e62720f7f3db7f5d92c9d945883739 Mon Sep 17 00:00:00 2001 From: Peechey <92683202+Peechey@users.noreply.github.com> Date: Wed, 18 Mar 2026 11:50:29 -0500 Subject: [PATCH 07/12] comments --- src/Classes/SkillsTab.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Classes/SkillsTab.lua b/src/Classes/SkillsTab.lua index d2d71a6f56..0c84308ba3 100644 --- a/src/Classes/SkillsTab.lua +++ b/src/Classes/SkillsTab.lua @@ -615,6 +615,7 @@ function SkillsTabClass:PasteSocketGroup(testInput) end end +-- the imbued support control actively switches to the latest count of the current displayGroup's gemList so we can use the canSupport filtering local function updateImbuedSupportIndex(control, gemListCount) if gemListCount > 0 then control.index = gemListCount + 1 From 30cdcfbd7bda740af92fb76c06de28f6dd1b31a4 Mon Sep 17 00:00:00 2001 From: Peechey <92683202+Peechey@users.noreply.github.com> Date: Wed, 18 Mar 2026 19:36:07 -0500 Subject: [PATCH 08/12] add gem color to text update scrollBar in SkillsTab to fit imbued change Clear button to X design of the other gems --- src/Classes/SkillsTab.lua | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/Classes/SkillsTab.lua b/src/Classes/SkillsTab.lua index 0c84308ba3..a73a393e2c 100644 --- a/src/Classes/SkillsTab.lua +++ b/src/Classes/SkillsTab.lua @@ -216,10 +216,12 @@ local SkillsTabClass = newClass("SkillsTab", "UndoHandler", "ControlHost", "Cont self.controls.imbuedSupportLabel = new("LabelControl", { "LEFT", self.controls.includeInFullDPS, "RIGHT" }, { 12, 0, 0, 16 }, colorCodes.POSITIVE.."Imbued Support:") self.controls.imbuedSupport = new("GemSelectControl", { "LEFT", self.controls.imbuedSupportLabel, "RIGHT" }, { 8, 0, 250, 20 }, self, 1, function(gemData, _, _, slotName) -- slotName used on Import if gemData and (type(gemData) == "string" or gemData.id) then - self.imbuedSupportBySlot[slotName or self.displayGroup.slot] = data.gems[gemData.id or gemData].grantedEffect + local gem = data.gems[gemData.id or gemData] + self.imbuedSupportBySlot[slotName or self.displayGroup.slot] = gem.grantedEffect if self.displayGroup then - self.displayGroup.imbuedSupport = data.gems[gemData.id or gemData].name + self.displayGroup.imbuedSupport = gem.name end + self.controls.imbuedSupport:SetText(data.skillColorMap[gem.grantedEffect.color]..gem.name) -- hacky way to set gem color on gemSelect self.build.buildFlag = true else self.imbuedSupportBySlot[slotName or self.displayGroup.slot] = nil @@ -236,7 +238,7 @@ local SkillsTabClass = newClass("SkillsTab", "UndoHandler", "ControlHost", "Cont self.controls.imbuedSupportLabel.shown = function() -- don't show imbued for skills from items return not self.displayGroup.source end - self.controls.imbuedSupportClear = new("ButtonControl", { "LEFT", self.controls.imbuedSupportLabel, "RIGHT" }, { 264, 0, 80, 20}, "Clear", function() + self.controls.imbuedSupportClear = new("ButtonControl", { "LEFT", self.controls.imbuedSupportLabel, "RIGHT" }, { 260, 0, 20, 20}, "x", function() self.controls.imbuedSupport.gemId = nil self.controls.imbuedSupport:SetText("") self.displayGroup.imbuedSupport = nil @@ -244,6 +246,7 @@ local SkillsTabClass = newClass("SkillsTab", "UndoHandler", "ControlHost", "Cont self.build.buildFlag = true end) + self.controls.imbuedSupportClear.tooltipText = "Remove this imbued support." self.controls.groupCountLabel = new("LabelControl", { "LEFT", self.controls.includeInFullDPS, "RIGHT" }, { 16, 0, 0, 16 }, "Count:") self.controls.groupCountLabel.shown = function() @@ -514,7 +517,7 @@ function SkillsTabClass:Draw(viewPort, inputEvents) self.controls.scrollBarH.y = viewPort.y + viewPort.height - 18 do - local maxX = self.controls.gemCountHeader:GetPos() + self.controls.gemCountHeader:GetSize() + 15 + local maxX = self.controls.gemCountHeader:GetPos() + self.controls.gemCountHeader:GetSize() + 350 local contentWidth = maxX - self.x self.controls.scrollBarH:SetContentDimension(contentWidth, viewPort.width) end @@ -689,7 +692,6 @@ function SkillsTabClass:CreateGemSlot(index) slot.enableGlobal1.state = true slot.enableGlobal2.state = true slot.count:SetText(gemInstance.count) - --slot.imbued.state = false elseif gemId == gemInstance.gemId then if addUndo then self:AddUndoState() @@ -1065,8 +1067,9 @@ function SkillsTabClass:SetDisplayGroup(socketGroup) self.controls.includeInFullDPS.state = socketGroup.includeInFullDPS and socketGroup.enabled self.controls.groupCount:SetText(socketGroup.groupCount or 1) if socketGroup.imbuedSupport then - self.controls.imbuedSupport.gemId = data.gems[data.gemForBaseName[socketGroup.imbuedSupport:lower().." support"]] - self.controls.imbuedSupport:SetText(socketGroup.imbuedSupport) + local gemId = data.gems[data.gemForBaseName[socketGroup.imbuedSupport:lower().." support"]] + self.controls.imbuedSupport.gemId = gemId + self.controls.imbuedSupport:SetText(data.skillColorMap[gemId.grantedEffect.color]..socketGroup.imbuedSupport) else self.controls.imbuedSupport.gemId = nil self.controls.imbuedSupport:SetText("") From 0f5514b4e3e08861c2d47f9a3332fea972040f97 Mon Sep 17 00:00:00 2001 From: Peechey <92683202+Peechey@users.noreply.github.com> Date: Wed, 18 Mar 2026 20:55:19 -0500 Subject: [PATCH 09/12] comments --- src/Classes/GemSelectControl.lua | 24 ++++++++++++------------ src/Classes/SkillsTab.lua | 6 +++++- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/Classes/GemSelectControl.lua b/src/Classes/GemSelectControl.lua index 2d3439ff02..3997d5b056 100644 --- a/src/Classes/GemSelectControl.lua +++ b/src/Classes/GemSelectControl.lua @@ -541,19 +541,19 @@ function GemSelectClass:Draw(viewPort, noTooltip) self.tooltip:AddLine(16, self.imbuedSelect and imbuedTooltipText or toolTipText) end - colorS = 0.5 - colorA = 0.5 - if cursorX > (x + width - 18) then - colorS = 1 - self.tooltip:Clear() - self.tooltip:AddLine(16, "Only show Support gems") - elseif (cursorX > (x + width - 40) and cursorX < (cursorX + width - 20)) then - colorA = 1 - self.tooltip:Clear() - self.tooltip:AddLine(16, "Only show Active gems") - end - if not self.imbuedSelect then + colorS = 0.5 + colorA = 0.5 + if cursorX > (x + width - 18) then + colorS = 1 + self.tooltip:Clear() + self.tooltip:AddLine(16, "Only show Support gems") + elseif (cursorX > (x + width - 40) and cursorX < (cursorX + width - 20)) then + colorA = 1 + self.tooltip:Clear() + self.tooltip:AddLine(16, "Only show Active gems") + end + -- support shortcut sx = x + width - 16 - 2 SetDrawColor(colorS,colorS,colorS) diff --git a/src/Classes/SkillsTab.lua b/src/Classes/SkillsTab.lua index a73a393e2c..61a3f36834 100644 --- a/src/Classes/SkillsTab.lua +++ b/src/Classes/SkillsTab.lua @@ -212,6 +212,11 @@ local SkillsTabClass = newClass("SkillsTab", "UndoHandler", "ControlHost", "Cont self.build.buildFlag = true end) + -- self.imbuedSupportBySlot is used by CalcSetup to add an ExtraSupport mod of the selected gem + -- Each displayGroup has its own "imbuedSupport" and is saved to the xml to load when changing sockets or loading a build + -- "slotName" is used on import, which uses builtInSupport to get the gemData and pass in here + -- buildFlag to true triggers the reload/run the CalcSetup to add on the support + -- the last var in the GemSelectControl init, the true, sets imbuedSelect to true which sets the level to 1 and support filtering self.imbuedSupportBySlot = { } self.controls.imbuedSupportLabel = new("LabelControl", { "LEFT", self.controls.includeInFullDPS, "RIGHT" }, { 12, 0, 0, 16 }, colorCodes.POSITIVE.."Imbued Support:") self.controls.imbuedSupport = new("GemSelectControl", { "LEFT", self.controls.imbuedSupportLabel, "RIGHT" }, { 8, 0, 250, 20 }, self, 1, function(gemData, _, _, slotName) -- slotName used on Import @@ -243,7 +248,6 @@ local SkillsTabClass = newClass("SkillsTab", "UndoHandler", "ControlHost", "Cont self.controls.imbuedSupport:SetText("") self.displayGroup.imbuedSupport = nil self.imbuedSupportBySlot[self.displayGroup.slot] = nil - self.build.buildFlag = true end) self.controls.imbuedSupportClear.tooltipText = "Remove this imbued support." From 86901ca4454bcd021cfbc2ce615986f630739afb Mon Sep 17 00:00:00 2001 From: Peechey <92683202+Peechey@users.noreply.github.com> Date: Wed, 18 Mar 2026 21:01:16 -0500 Subject: [PATCH 10/12] remove unused code --- src/Classes/GemSelectControl.lua | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Classes/GemSelectControl.lua b/src/Classes/GemSelectControl.lua index 3997d5b056..cceb4f983e 100644 --- a/src/Classes/GemSelectControl.lua +++ b/src/Classes/GemSelectControl.lua @@ -910,7 +910,3 @@ function GemSelectClass:OnKeyUp(key) local newSel = self.EditControl:OnKeyUp(key) return newSel == self.EditControl and self or newSel end - -function GemSelectClass:UpdateIndex(index) - self.index = index -end From dfd3a21fdfae023df17735dc3f656beaaddcb9b5 Mon Sep 17 00:00:00 2001 From: Peechey <92683202+Peechey@users.noreply.github.com> Date: Wed, 18 Mar 2026 21:03:36 -0500 Subject: [PATCH 11/12] remove more unused code --- src/Classes/SkillsTab.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Classes/SkillsTab.lua b/src/Classes/SkillsTab.lua index 61a3f36834..d90a65cafe 100644 --- a/src/Classes/SkillsTab.lua +++ b/src/Classes/SkillsTab.lua @@ -7,7 +7,6 @@ local pairs = pairs local ipairs = ipairs local t_insert = table.insert local t_remove = table.remove -local t_sort = table.sort local m_min = math.min local m_max = math.max From 4f493350dbe537113093b3b90286e1d5417ad8ac Mon Sep 17 00:00:00 2001 From: Peechey <92683202+Peechey@users.noreply.github.com> Date: Sun, 22 Mar 2026 11:39:52 -0500 Subject: [PATCH 12/12] pr comments: tooltip showing for imbued, use better field for text color, click away from dropdown fix --- src/Classes/GemSelectControl.lua | 14 +++++++++++++- src/Classes/SkillsTab.lua | 16 ++++++++-------- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/Classes/GemSelectControl.lua b/src/Classes/GemSelectControl.lua index cceb4f983e..43c0f7ff8b 100644 --- a/src/Classes/GemSelectControl.lua +++ b/src/Classes/GemSelectControl.lua @@ -12,7 +12,7 @@ local m_max = math.max local m_floor = math.floor local toolTipText = "Prefix tag searches with a colon and exclude tags with a dash. e.g. :fire:lightning:-cold:area" -local imbuedTooltipText = "Socketed in must be set in order to add an imbued support. Only one imbued support is allowed per socketed in." +local imbuedTooltipText = "Socketed in must be set in order to add an imbued support.\nOnly one imbued support is allowed per socketed in." local altQualMap = { ["Default"] = "", ["Alternate1"] = "Anomalous ", @@ -531,6 +531,18 @@ function GemSelectClass:Draw(viewPort, noTooltip) local gemInstance = self.skillsTab.displayGroup.gemList[self.index] local cursorX, cursorY = GetCursorPos() self.tooltip:Clear() + + if hoverControl and hoverControl.imbuedSelect then -- tooltip for imbued + gemInstance = { } + if type(hoverControl.gemId) == "string" then -- on select + gemInstance["gemData"] = hoverControl.gems[hoverControl.gemId] + else -- on load + gemInstance["gemData"] = hoverControl.gemId + end + gemInstance.level = 1 + gemInstance.quality = 0 + end + if gemInstance and gemInstance.gemData then -- Check valid qualityId, set to 'Default' if missing if gemInstance.qualityId == nil or gemInstance.qualityId == "" then diff --git a/src/Classes/SkillsTab.lua b/src/Classes/SkillsTab.lua index d90a65cafe..cf5a862329 100644 --- a/src/Classes/SkillsTab.lua +++ b/src/Classes/SkillsTab.lua @@ -219,25 +219,24 @@ local SkillsTabClass = newClass("SkillsTab", "UndoHandler", "ControlHost", "Cont self.imbuedSupportBySlot = { } self.controls.imbuedSupportLabel = new("LabelControl", { "LEFT", self.controls.includeInFullDPS, "RIGHT" }, { 12, 0, 0, 16 }, colorCodes.POSITIVE.."Imbued Support:") self.controls.imbuedSupport = new("GemSelectControl", { "LEFT", self.controls.imbuedSupportLabel, "RIGHT" }, { 8, 0, 250, 20 }, self, 1, function(gemData, _, _, slotName) -- slotName used on Import + if not (self.displayGroup or slotName) then + return + end if gemData and (type(gemData) == "string" or gemData.id) then local gem = data.gems[gemData.id or gemData] self.imbuedSupportBySlot[slotName or self.displayGroup.slot] = gem.grantedEffect if self.displayGroup then self.displayGroup.imbuedSupport = gem.name end - self.controls.imbuedSupport:SetText(data.skillColorMap[gem.grantedEffect.color]..gem.name) -- hacky way to set gem color on gemSelect + self.controls.imbuedSupport.inactiveCol = data.skillColorMap[gem.grantedEffect.color] self.build.buildFlag = true else self.imbuedSupportBySlot[slotName or self.displayGroup.slot] = nil end - end, nil, true) + end, true, true) self.controls.imbuedSupport.enabled = function() -- socketedIn must be set and the displayGroup must have an imbued, otherwise disable the imbued dropdown - if self.displayGroup.slot and ((self.imbuedSupportBySlot[self.displayGroup.slot] and self.displayGroup.imbuedSupport) or not self.imbuedSupportBySlot[self.displayGroup.slot]) then - return true - else - return false - end + return (self.displayGroup.slot and ((self.imbuedSupportBySlot[self.displayGroup.slot] and self.displayGroup.imbuedSupport) or not self.imbuedSupportBySlot[self.displayGroup.slot])) end self.controls.imbuedSupportLabel.shown = function() -- don't show imbued for skills from items return not self.displayGroup.source @@ -1072,7 +1071,8 @@ function SkillsTabClass:SetDisplayGroup(socketGroup) if socketGroup.imbuedSupport then local gemId = data.gems[data.gemForBaseName[socketGroup.imbuedSupport:lower().." support"]] self.controls.imbuedSupport.gemId = gemId - self.controls.imbuedSupport:SetText(data.skillColorMap[gemId.grantedEffect.color]..socketGroup.imbuedSupport) + self.controls.imbuedSupport:SetText(socketGroup.imbuedSupport) + self.controls.imbuedSupport.inactiveCol = data.skillColorMap[gemId.grantedEffect.color] else self.controls.imbuedSupport.gemId = nil self.controls.imbuedSupport:SetText("")