diff --git a/src/Classes/ItemsTab.lua b/src/Classes/ItemsTab.lua index f0c43b6b4..fa523fcda 100644 --- a/src/Classes/ItemsTab.lua +++ b/src/Classes/ItemsTab.lua @@ -58,6 +58,80 @@ local function isAnointable(item) and not item.corrupted and not item.mirrored end +local function buildModSortList() + local sortList = { { label = "Default", stat = nil } } + local sortTransforms = { } + for _, entry in ipairs(data.powerStatList) do + if entry.stat and not entry.ignoreForNodes then + t_insert(sortList, { label = entry.label, stat = entry.stat }) + sortTransforms[entry.stat] = entry.transform + end + end + return sortList, sortTransforms +end + +local function getOutputStatValue(output, stat) + if stat == "FullDPS" then + if output[stat] ~= nil then + return output[stat] + end + if output.Minion and output.Minion.CombinedDPS ~= nil then + return output.Minion.CombinedDPS + end + end + if output.Minion and output.Minion[stat] ~= nil then + return output.Minion[stat] + end + if output[stat] ~= nil then + return output[stat] + end + return 0 +end + +local function setDefaultSortOrder(modList) + for index, listMod in ipairs(modList) do + listMod.defaultSortOrder = index + listMod.sortValue = nil + listMod.sortValues = nil + end +end + +local function getSortedModValue(item, listMod, stat, sortTransforms, calcFunc, slotName, useFullDPS, addModToItem) + listMod.sortValues = listMod.sortValues or { } + if listMod.sortValues[stat] ~= nil then + return listMod.sortValues[stat] + end + local testItem = new("Item", item:BuildRaw()) + testItem.id = item.id + addModToItem(testItem, listMod) + testItem:BuildAndParseRaw() + local output = calcFunc({ repSlotName = slotName, repItem = testItem }, useFullDPS) + local value = getOutputStatValue(output, stat) + if sortTransforms[stat] then + value = sortTransforms[stat](value) + end + listMod.sortValues[stat] = value + return value +end + +local function sortModList(modList, stat, getSortValue) + if stat then + for _, listMod in ipairs(modList) do + listMod.sortValue = getSortValue(listMod) + end + table.sort(modList, function(a, b) + if a.sortValue ~= b.sortValue then + return a.sortValue > b.sortValue + end + return (a.defaultSortOrder or 0) < (b.defaultSortOrder or 0) + end) + else + table.sort(modList, function(a, b) + return (a.defaultSortOrder or 0) < (b.defaultSortOrder or 0) + end) + end +end + local ItemsTabClass = newClass("ItemsTab", "UndoHandler", "ControlHost", "Control", function(self, build) self.UndoHandler() self.ControlHost() @@ -2389,7 +2463,7 @@ end -- Opens the item corrupting popup function ItemsTabClass:CorruptDisplayItem() -- todo implement vaal orb new outcomes this code is for poe 1 - local controls = { } + local controls = { } local enchantList = { } local enchantNum = 1 local shownExplicits = {} @@ -2397,6 +2471,7 @@ function ItemsTabClass:CorruptDisplayItem() -- todo implement vaal orb new outco local corruptedRanges = {} local currentModType = "Corrupted" local sourceList = { "Corrupted" } + local sortList, sortTransforms = buildModSortList() if self.displayItem.base.type == "Helmet" then t_insert(sourceList, "Glimpse of Chaos") end @@ -2407,18 +2482,19 @@ function ItemsTabClass:CorruptDisplayItem() -- todo implement vaal orb new outco enchantList[modType] = {} for modId, mod in pairs(data.itemMods.Corruption) do if mod.type == modType and self.displayItem:GetModSpawnWeight(mod) > 0 then - t_insert(enchantList[modType], mod) + t_insert(enchantList[modType], { mod = mod }) end end table.sort(enchantList[modType], function(a, b) - local an = a[1]:lower():gsub("%(.-%)","$"):gsub("[%+%-%%]",""):gsub("%d+","$") - local bn = b[1]:lower():gsub("%(.-%)","$"):gsub("[%+%-%%]",""):gsub("%d+","$") + local an = a.mod[1]:lower():gsub("%(.-%)","$"):gsub("[%+%-%%]",""):gsub("%d+","$") + local bn = b.mod[1]:lower():gsub("%(.-%)","$"):gsub("[%+%-%%]",""):gsub("%d+","$") if an ~= bn then return an < bn else - return a.level < b.level + return a.mod.level < b.mod.level end end) + setDefaultSortOrder(enchantList[modType]) end buildEnchantList("Corrupted") buildEnchantList("SpecialCorrupted") @@ -2426,7 +2502,8 @@ function ItemsTabClass:CorruptDisplayItem() -- todo implement vaal orb new outco local selfMod = control.selIndex and control.selIndex > 1 and control.list[control.selIndex].mod wipeTable(control.list) t_insert(control.list, { label = "None" }) - for _, mod in ipairs(enchantList[modType]) do + for _, listMod in ipairs(enchantList[modType]) do + local mod = listMod.mod local alreadySelected = false for _, other in ipairs(others) do local otherMod = other and other.selIndex and other.selIndex > 1 and other.list[other.selIndex].mod @@ -2440,21 +2517,14 @@ function ItemsTabClass:CorruptDisplayItem() -- todo implement vaal orb new outco end control:SelByValue(selfMod, "mod") end - local function corruptItem() - local item = new("Item", self.displayItem:BuildRaw()) - item.id = self.displayItem.id - item.corrupted = true + local function applyCorruptionMods(item, mods) local newEnchant = { } - for i = 1, enchantNum do - local control = controls["enchant"..i] - if control.selIndex > 1 then - local mod = control.list[control.selIndex].mod - for i, modLine in ipairs(mod) do - if mod.modTags[1] then - t_insert(newEnchant, { line = "{tags:" .. table.concat(mod.modTags, ",") .. "}" .. modLine, enchant = true, order = mod.statOrder[i] }) - else - t_insert(newEnchant, { line = modLine, enchant = true, order = mod.statOrder[i] }) - end + for _, mod in ipairs(mods) do + for i, modLine in ipairs(mod) do + if mod.modTags[1] then + t_insert(newEnchant, { line = "{tags:" .. table.concat(mod.modTags, ",") .. "}" .. modLine, enchant = true, order = mod.statOrder[i] }) + else + t_insert(newEnchant, { line = modLine, enchant = true, order = mod.statOrder[i] }) end end end @@ -2468,6 +2538,52 @@ function ItemsTabClass:CorruptDisplayItem() -- todo implement vaal orb new outco t_insert( item.enchantModLines, i, enchant) end end + end + local function sortEnchantList(stat) + if stat then + local slotName = self.displayItem:GetPrimarySlot() + local calcFunc = self.build.calcsTab:GetMiscCalculator() + local useFullDPS = stat == "FullDPS" + sortModList(enchantList[currentModType], stat, function(listMod) + return getSortedModValue(self.displayItem, listMod, stat, sortTransforms, calcFunc, slotName, useFullDPS, function(item, sortedMod) + applyCorruptionMods(item, { sortedMod.mod }) + end) + end) + else + sortModList(enchantList[currentModType]) + end + end + local function rebuildEnchantControls(resetSelection) + for i = 1, 8 do + local shown = i <= enchantNum + controls["enchant"..i].shown = shown + controls["enchant"..i.."Label"].shown = shown + if shown then + if resetSelection then + controls["enchant"..i]:SetSel(1) + end + local others = { } + for j = 1, enchantNum do + if i ~= j then + t_insert(others, controls["enchant"..j]) + end + end + buildList(controls["enchant"..i], others, currentModType) + end + end + end + local function corruptItem() + local item = new("Item", self.displayItem:BuildRaw()) + item.id = self.displayItem.id + item.corrupted = true + local mods = { } + for i = 1, enchantNum do + local control = controls["enchant"..i] + if control.selIndex > 1 then + t_insert(mods, control.list[control.selIndex].mod) + end + end + applyCorruptionMods(item, mods) for i, modLine in ipairs(item.explicitModLines) do if corruptedRanges[i] ~= 1 then modLine.corruptedRange = corruptedRanges[i] end end @@ -2538,6 +2654,8 @@ function ItemsTabClass:CorruptDisplayItem() -- todo implement vaal orb new outco end controls.source.shown = true controls.sourceLabel.shown = true + controls.sort.shown = true + controls.sortLabel.shown = true main.popups[1].height = 103 + 20 * enchantNum controls.close.y = 73 + 20 * enchantNum controls.save.y = 73 + 20 * enchantNum @@ -2557,6 +2675,8 @@ function ItemsTabClass:CorruptDisplayItem() -- todo implement vaal orb new outco end controls.source.shown = false controls.sourceLabel.shown = false + controls.sort.shown = false + controls.sortLabel.shown = false main.popups[1].height = 55 + explicitOffset controls.close.y = 25 + explicitOffset controls.save.y = 25 + explicitOffset @@ -2578,27 +2698,19 @@ function ItemsTabClass:CorruptDisplayItem() -- todo implement vaal orb new outco end end - for i = 1, 8 do - if i <= enchantNum then - controls["enchant"..i].shown = true - controls["enchant"..i.."Label"].shown = true - local others = { } - for j = 1, enchantNum do - if i ~= j then - t_insert(others, controls["enchant"..j]) - end - end - buildList(controls["enchant"..i], others, currentModType) - else - controls["enchant"..i].shown = false - controls["enchant"..i.."Label"].shown = false - end - controls["enchant"..i]:SetSel(1) + if controls.sort then + sortEnchantList(controls.sort.list[controls.sort.selIndex].stat) end + rebuildEnchantControls(true) main.popups[1].height = 103 + 20 * enchantNum controls.close.y = 73 + 20 * enchantNum controls.save.y = 73 + 20 * enchantNum end) + controls.sortLabel = new("LabelControl", {"TOPRIGHT",nil,"TOPLEFT"}, {350, 30, 0, 16}, "^7Sort by:") + controls.sort = new("DropDownControl", {"TOPLEFT",nil,"TOPLEFT"}, {355, 30, 240, 18}, sortList, function(index, value) + sortEnchantList(value.stat) + rebuildEnchantControls() + end) for i = 1, 8 do if i == 1 then controls.enchant1Label = new("LabelControl", {"TOPRIGHT",nil,"TOPLEFT"}, {95, 55, 0, 16}, function() @@ -2612,15 +2724,7 @@ function ItemsTabClass:CorruptDisplayItem() -- todo implement vaal orb new outco controls["enchant"..i.."Label"] = new("LabelControl", {"TOPRIGHT",nil,"TOPLEFT"}, {95, 35 + i * 20 , 0, 16}, "^7Enchant #"..i..":") end controls["enchant"..i] = new("DropDownControl", {"TOPLEFT",nil,"TOPLEFT"}, {100, 35 + i * 20, 440, 18}, nil, function() - for i = 1, enchantNum do - local others = { } - for j = 1, enchantNum do - if i ~= j then - t_insert(others, controls["enchant"..j]) - end - end - buildList(controls["enchant"..i], others, currentModType) - end + rebuildEnchantControls() end) controls["enchant"..i].tooltipFunc = function(tooltip, mode, index, value) tooltip:Clear() @@ -2631,24 +2735,8 @@ function ItemsTabClass:CorruptDisplayItem() -- todo implement vaal orb new outco self:AddModComparisonTooltip(tooltip, value.mod) end end - if i == 1 then - controls["enchant"..i].shown = true - controls["enchant"..i.."Label"].shown = true - else - controls["enchant"..i].shown = false - controls["enchant"..i.."Label"].shown = false - end - - if i <= enchantNum then - local others = { } - for j = 1, enchantNum do - if i ~= j then - t_insert(others, controls["enchant"..j]) - end - end - buildList(controls["enchant"..i], others, currentModType) - end end + rebuildEnchantControls() controls.save = new("ButtonControl", nil, {-45, 69 + enchantNum * 20, 80, 20}, "Corrupted", function() self:SetDisplayItem(corruptItem()) main:ClosePopup() @@ -2668,57 +2756,7 @@ function ItemsTabClass:AddCustomModifierToDisplayItem() local controls = { } local sourceList = { } local modList = { } - local sortList = { { label = "Default", stat = nil } } - local sortTransforms = { } - for _, entry in ipairs(data.powerStatList) do - if entry.stat and not entry.ignoreForNodes then - t_insert(sortList, { label = entry.label, stat = entry.stat }) - sortTransforms[entry.stat] = entry.transform - end - end - local function setDefaultSortOrder() - for index, listMod in ipairs(modList) do - listMod.defaultSortOrder = index - listMod.sortValue = nil - listMod.sortValues = nil - end - end - local function getOutputStatValue(output, stat) - if stat == "FullDPS" then - if output[stat] ~= nil then - return output[stat] - end - if output.Minion and output.Minion.CombinedDPS ~= nil then - return output.Minion.CombinedDPS - end - end - if output.Minion and output.Minion[stat] ~= nil then - return output.Minion[stat] - end - if output[stat] ~= nil then - return output[stat] - end - return 0 - end - local function getSortValue(listMod, stat, calcFunc, slotName, useFullDPS) - listMod.sortValues = listMod.sortValues or { } - if listMod.sortValues[stat] ~= nil then - return listMod.sortValues[stat] - end - local item = new("Item", self.displayItem:BuildRaw()) - item.id = self.displayItem.id - for _, line in ipairs(listMod.mod) do - t_insert(item.explicitModLines, { line = checkLineForAllocates(line, self.build.spec.nodes), modTags = listMod.mod.modTags, [listMod.type] = true }) - end - item:BuildAndParseRaw() - local output = calcFunc({ repSlotName = slotName, repItem = item }, useFullDPS) - local value = getOutputStatValue(output, stat) - if sortTransforms[stat] then - value = sortTransforms[stat](value) - end - listMod.sortValues[stat] = value - return value - end + local sortList, sortTransforms = buildModSortList() local function applySort(stat, selectFirst) if not controls.modSelect or not controls.modSelect:IsShown() then return @@ -2728,19 +2766,15 @@ function ItemsTabClass:AddCustomModifierToDisplayItem() local slotName = self.displayItem:GetPrimarySlot() local calcFunc = self.build.calcsTab:GetMiscCalculator() local useFullDPS = stat == "FullDPS" - for _, listMod in ipairs(modList) do - listMod.sortValue = getSortValue(listMod, stat, calcFunc, slotName, useFullDPS) - end - table.sort(modList, function(a, b) - if a.sortValue ~= b.sortValue then - return a.sortValue > b.sortValue - end - return (a.defaultSortOrder or 0) < (b.defaultSortOrder or 0) + sortModList(modList, stat, function(listMod) + return getSortedModValue(self.displayItem, listMod, stat, sortTransforms, calcFunc, slotName, useFullDPS, function(item, sortedMod) + for _, line in ipairs(sortedMod.mod) do + t_insert(item.explicitModLines, { line = checkLineForAllocates(line, self.build.spec.nodes), modTags = sortedMod.mod.modTags, [sortedMod.type] = true }) + end + end) end) else - table.sort(modList, function(a, b) - return (a.defaultSortOrder or 0) < (b.defaultSortOrder or 0) - end) + sortModList(modList) end controls.modSelect:UpdateSearch() if selected then @@ -2805,7 +2839,7 @@ function ItemsTabClass:AddCustomModifierToDisplayItem() end end) end - setDefaultSortOrder() + setDefaultSortOrder(modList) end if not self.displayItem.crafted then t_insert(sourceList, { label = "Prefix", sourceId = "PREFIX" })