diff --git a/src/Classes/GemSelectControl.lua b/src/Classes/GemSelectControl.lua index 8155e9868c..cceb4f983e 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 @@ -120,21 +122,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) @@ -142,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) @@ -176,7 +177,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 +259,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 +275,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 +469,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 @@ -494,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, @@ -542,38 +538,40 @@ function GemSelectClass:Draw(viewPort, noTooltip) end self:AddGemTooltip(gemInstance) else - self.tooltip:AddLine(16, toolTipText) - end + self.tooltip:AddLine(16, self.imbuedSelect and imbuedTooltipText or toolTipText) + 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 - 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) - 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") + -- 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) @@ -598,7 +596,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 +606,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") @@ -911,4 +909,4 @@ 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 diff --git a/src/Classes/ImportTab.lua b/src/Classes/ImportTab.lua index 1427ff4a97..b6813831c6 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] @@ -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.gemChangeFunc(data.gems[data.gemForBaseName[socketGroup.imbuedSupport:lower().." support"]], nil, nil, slotName) + end end end end diff --git a/src/Classes/SkillsTab.lua b/src/Classes/SkillsTab.lua index a7dfedcc09..d90a65cafe 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() @@ -94,7 +87,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 +120,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,10 +145,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.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.controls.showLegacyGems = new("CheckBoxControl", { "TOPLEFT", self.controls.groupList, "BOTTOMLEFT" }, { optionInputsX, optionInputsY + 166, 20 }, "^7Show legacy gems:", function(state) self.showLegacyGems = state end) @@ -177,6 +166,18 @@ 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] and self.displayGroup.imbuedSupport 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.gemId = nil + self.controls.imbuedSupport:SetText("") + self.displayGroup.imbuedSupport = nil -- reset saved support to None + end + self.imbuedSupportBySlot[self.displayGroup.slot] = nil + end + self.displayGroup.slot = value.slotName self:AddUndoState() self.build.buildFlag = true @@ -209,6 +210,47 @@ local SkillsTabClass = newClass("SkillsTab", "UndoHandler", "ControlHost", "Cont self:AddUndoState() 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 + 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.build.buildFlag = true + else + self.imbuedSupportBySlot[slotName or self.displayGroup.slot] = nil + 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) or not self.imbuedSupportBySlot[self.displayGroup.slot]) then + return true + else + 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" }, { 260, 0, 20, 20}, "x", 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.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() return self.displayGroup.source ~= nil @@ -272,33 +314,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 @@ -315,6 +335,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.gemChangeFunc(data.gems[data.gemForBaseName[socketGroup.imbuedSupport:lower().." support"]], nil, nil, socketGroup.slot) + end + for _, child in ipairs(node) do local gemInstance = { } gemInstance.nameSpec = sanitiseText(child.attrib.nameSpec or "") @@ -351,13 +376,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 +421,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 +460,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] @@ -463,6 +477,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 = { @@ -472,7 +487,6 @@ function SkillsTabClass:Save(xml) 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), @@ -506,7 +520,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 @@ -568,7 +582,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 +599,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, @@ -608,6 +621,13 @@ 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 + end +end + -- Create the controls for editing the gem at a given index function SkillsTabClass:CreateGemSlot(index) local slot = { } @@ -622,13 +642,12 @@ 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 self.gemSlots[index2].count:SetText(gemInstance.count or 1) end + updateImbuedSupportIndex(self.controls.imbuedSupport, #self.displayGroup.gemList) self:AddUndoState() self.build.buildFlag = true end) @@ -650,7 +669,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 +682,6 @@ function SkillsTabClass:CreateGemSlot(index) nameSpec = "", level = 1, quality = self.defaultGemQuality or 0, - qualityId = "Default", enabled = true, enableGlobal1 = true, enableGlobal2 = true, @@ -673,7 +691,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 +707,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 +721,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 +739,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 @@ -858,12 +779,10 @@ function SkillsTabClass:CreateGemSlot(index) 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, 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 +818,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 +901,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 +915,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 @@ -1045,10 +950,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 @@ -1058,8 +965,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 @@ -1149,6 +1054,7 @@ function SkillsTabClass:ProcessSocketGroup(socketGroup) end end end + updateImbuedSupportIndex(self.controls.imbuedSupport, #socketGroup.gemList) end -- Set the skill to be displayed/edited @@ -1163,6 +1069,14 @@ 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) + 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) + else + self.controls.imbuedSupport.gemId = nil + self.controls.imbuedSupport:SetText("") + end -- Update the gem slot controls self:UpdateGemSlots() @@ -1170,8 +1084,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 diff --git a/src/Modules/CalcSetup.lua b/src/Modules/CalcSetup.lua index b1ed688536..962a82d1f2 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] and group.imbuedSupport then + addExtraSupports(nil, build.skillsTab.imbuedSupportBySlot[slotName], 1) + end for gemIndex, gemInstance in ipairs(group.gemList) do -- Add support gems from this group