diff --git a/spec/System/TestItemMods_spec.lua b/spec/System/TestItemMods_spec.lua index b15074c41..fc99dbf2b 100644 --- a/spec/System/TestItemMods_spec.lua +++ b/spec/System/TestItemMods_spec.lua @@ -7,6 +7,50 @@ describe("TetsItemMods", function() -- newBuild() takes care of resetting everything in setup() end) + local function findAddModifierListEntry(list, line) + for _, listMod in ipairs(list) do + for _, modLine in ipairs(listMod.mod) do + if modLine == line then + return listMod + end + end + end + end + + it("Add Modifier lists applicable desecrated modifiers", function() + build.itemsTab:CreateDisplayItemFromRaw([[ + New Item + Ring + ]]) + + local ringMods = build.itemsTab:BuildAddModifierList("DESECRATED") + local cooldownMod = findAddModifierListEntry(ringMods, "(8-12)% increased Cooldown Recovery Rate") + + assert.truthy(cooldownMod) + assert.are.equals("desecrated", cooldownMod.type) + + local ringItem = new("Item", build.itemsTab.displayItem:BuildRaw()) + for _, line in ipairs(cooldownMod.mod) do + table.insert(ringItem.explicitModLines, { line = line, modTags = cooldownMod.mod.modTags, [cooldownMod.type] = true }) + end + ringItem:BuildAndParseRaw() + + assert.truthy(ringItem.desecrated) + assert.truthy(ringItem.explicitModLines[1].desecrated) + assert.truthy(ringItem:BuildRaw():find("{desecrated}", 1, true)) + + build.itemsTab:CreateDisplayItemFromRaw([[ + New Item + Fur Plate + ]]) + + local bodyArmourMods = build.itemsTab:BuildAddModifierList("DESECRATED") + local damageFromManaMod = findAddModifierListEntry(bodyArmourMods, "(10-20)% of Damage is taken from Mana before Life") + + assert.truthy(damageFromManaMod) + assert.are.equals("desecrated", damageFromManaMod.type) + end) + it("Both slots mod (evasion and es mastery)", function() build.configTab.input.customMods = "\z diff --git a/src/Classes/ItemsTab.lua b/src/Classes/ItemsTab.lua index 112b34356..ff240c0a7 100644 --- a/src/Classes/ItemsTab.lua +++ b/src/Classes/ItemsTab.lua @@ -58,6 +58,23 @@ local function isAnointable(item) and not item.corrupted and not item.mirrored end +local function sortItemModListByStats(modList) + table.sort(modList, function(a, b) + local modA = a.mod + local modB = b.mod + for i = 1, m_max(#modA, #modB) do + if not modA[i] then + return true + elseif not modB[i] then + return false + elseif modA.statOrder[i] ~= modB.statOrder[i] then + return modA.statOrder[i] < modB.statOrder[i] + end + end + return modA.level > modB.level + end) +end + local ItemsTabClass = newClass("ItemsTab", "UndoHandler", "ControlHost", "Control", function(self, build) self.UndoHandler() self.ControlHost() @@ -2656,6 +2673,57 @@ function ItemsTabClass:CorruptDisplayItem() -- todo implement vaal orb new outco main:OpenPopup(620, 103 + enchantNum * 20, "Corrupted Item", controls) end +-- Builds the selectable modifier list for the Add Modifier popup +function ItemsTabClass:BuildAddModifierList(sourceId) + local modList = { } + if sourceId == "PREFIX" or sourceId == "SUFFIX" then -- might be implied. + for _, mod in pairs(self.displayItem.affixes) do + if sourceId:lower() == mod.type:lower() and self.displayItem:GetModSpawnWeight(mod) > 0 then + t_insert(modList, { + label = mod.affix .. " ^8[" .. table.concat(mod, "/") .. "]", + mod = mod, + type = "custom", + }) + end + end + sortItemModListByStats(modList) + elseif sourceId == "ESSENCE" then + for _, essence in pairs(self.build.data.essences) do + local modId = essence.mods[self.displayItem.type] + if modId then + local mod = self.displayItem.affixes[modId] or data.itemMods.Exclusive[modId] + if mod then -- passive_hash mods don't get described + t_insert(modList, { + label = essence.name .. " " .. "^8[" .. table.concat(mod, "/") .. "]" .. " (" .. (mod.type or "Suffix") .. ")", + mod = mod, + type = "custom", + essence = essence, + }) + end + end + end + table.sort(modList, function(a, b) + if a.essence.type ~= b.essence.type then + return a.essence.type > b.essence.type + else + return a.essence.tierLevel > b.essence.tierLevel + end + end) + elseif sourceId == "DESECRATED" then + for _, mod in pairs(data.itemMods.Desecrated) do + if mod.type and self.displayItem:GetModSpawnWeight(mod) > 0 then + t_insert(modList, { + label = mod.affix .. " ^8[" .. table.concat(mod, "/") .. "]" .. " (" .. mod.type .. ")", + mod = mod, + type = "desecrated", + }) + end + end + sortItemModListByStats(modList) + end + return modList +end + -- Opens the custom modifier popup function ItemsTabClass:AddCustomModifierToDisplayItem() local controls = { } @@ -2665,52 +2733,8 @@ function ItemsTabClass:AddCustomModifierToDisplayItem() ---@param sourceId string @The crafting source id to build the list of mods for local function buildMods(sourceId) wipeTable(modList) - if sourceId == "PREFIX" or sourceId == "SUFFIX" then -- might be implied. - for _, mod in pairs(self.displayItem.affixes) do - if sourceId:lower() == mod.type:lower() and self.displayItem:GetModSpawnWeight(mod) > 0 then - t_insert(modList, { - label = mod.affix .. " ^8[" .. table.concat(mod, "/") .. "]", - mod = mod, - type = "custom", - }) - end - end - table.sort(modList, function(a, b) - local modA = a.mod - local modB = b.mod - for i = 1, m_max(#modA, #modB) do - if not modA[i] then - return true - elseif not modB[i] then - return false - elseif modA.statOrder[i] ~= modB.statOrder[i] then - return modA.statOrder[i] < modB.statOrder[i] - end - end - return modA.level > modB.level - end) - elseif sourceId == "ESSENCE" then - for _, essence in pairs(self.build.data.essences) do - local modId = essence.mods[self.displayItem.type] - if modId then - local mod = self.displayItem.affixes[modId] or data.itemMods.Exclusive[modId] - if mod then -- passive_hash mods don't get described - t_insert(modList, { - label = essence.name .. " " .. "^8[" .. table.concat(mod, "/") .. "]" .. " (" .. (mod.type or "Suffix") .. ")", - mod = mod, - type = "custom", - essence = essence, - }) - end - end - end - table.sort(modList, function(a, b) - if a.essence.type ~= b.essence.type then - return a.essence.type > b.essence.type - else - return a.essence.tierLevel > b.essence.tierLevel - end - end) + for _, mod in ipairs(self:BuildAddModifierList(sourceId)) do + t_insert(modList, mod) end end if not self.displayItem.crafted then @@ -2722,6 +2746,10 @@ function ItemsTabClass:AddCustomModifierToDisplayItem() if #modList > 0 then t_insert(sourceList, { label = "Essence", sourceId = "ESSENCE" }) end + buildMods("DESECRATED") + if #modList > 0 then + t_insert(sourceList, { label = "Desecrated", sourceId = "DESECRATED" }) + end t_insert(sourceList, { label = "Custom", sourceId = "CUSTOM" }) buildMods(sourceList[1].sourceId) local function addModifier()