diff --git a/src/Classes/ItemDBControl.lua b/src/Classes/ItemDBControl.lua index 84e8e2f5f6..c5d929d57e 100644 --- a/src/Classes/ItemDBControl.lua +++ b/src/Classes/ItemDBControl.lua @@ -44,7 +44,7 @@ local ItemDBClass = newClass("ItemDBControl", "ListControl", function(self, anch self.controls.requirement = new("DropDownControl", {"LEFT",self.controls.sort,"BOTTOMLEFT"}, {0, 11, 179, 18}, { "Any requirements", "Current level", "Current attributes", "Current useable" }, function(index, value) self.listBuildFlag = true end) - self.controls.obtainable = new("DropDownControl", {"LEFT",self.controls.requirement,"RIGHT"}, {2, 0, 179, 18}, { "Obtainable", "Any source", "Unobtainable", "Vendor Recipe", "Upgraded", "Boss Item", "Corruption"}, function(index, value) + self.controls.obtainable = new("DropDownControl", { "LEFT", self.controls.requirement, "RIGHT" }, { 2, 0, 179, 18 }, { "Obtainable", "Any source", "Unobtainable", "Vendor Recipe", "Upgraded", "Boss Item", "Corruption", "Core drop pool" }, function(index, value) self.listBuildFlag = true end) end @@ -122,6 +122,8 @@ function ItemDBClass:DoesItemMatchFilters(item) return false elseif (self.controls.obtainable.selIndex == 7 and not (string.match(source, "Vaal Orb"))) then return false + elseif (self.controls.obtainable.selIndex == 8) and item.source then + return false end end if self.dbType == "UNIQUE" and self.controls.requirement.selIndex > 1 then diff --git a/src/Classes/ItemsTab.lua b/src/Classes/ItemsTab.lua index 1380881c02..d1bdb4722e 100644 --- a/src/Classes/ItemsTab.lua +++ b/src/Classes/ItemsTab.lua @@ -14,9 +14,11 @@ local m_min = math.min local m_ceil = math.ceil local m_floor = math.floor local m_modf = math.modf -local buySimilar = LoadModule("Classes/CompareBuySimilar") +local buySimilar = LoadModule("Classes/CompareBuySimilar") +local addImplicit = require("Modules.AddImplicitPopup") local gemTooltip = LoadModule("Classes/GemTooltip") + local rarityDropList = { { label = colorCodes.NORMAL.."Normal", rarity = "NORMAL" }, { label = colorCodes.MAGIC.."Magic", rarity = "MAGIC" }, @@ -566,7 +568,7 @@ holding Shift will put it in the second.]]) end --]] self.controls.displayItemAddImplicit = new("ButtonControl", {"TOPLEFT",self.controls.displayItemCorrupt,"TOPRIGHT",true}, {8, 0, 120, 20}, "Add Implicit...", function() - self:AddImplicitToDisplayItem() + addImplicit.AddImplicitToDisplayItem(self, self.displayItem) end) self.controls.displayItemAddImplicit.shown = function() return self.displayItem and @@ -2252,7 +2254,10 @@ function ItemsTabClass:UpdateAffixControl(control, item, affixType, outputTable, if (#testSubject.modMagnitudeMods > 0) or (testSubject.catalyst and testSubject.catalyst > 0) then local originalItem = testSubject:BuildRaw() for _, subMod in ipairs(mod) do - local modLine = { line = subMod, modTags = mod.modTags, [mod.type] = true } + local modLine = { line = subMod, modTags = mod.modTags } + if mod.type then + modLine[mod.type] = true + end t_insert(testSubject.explicitModLines, modLine) end testSubject:BuildAndParseRaw() @@ -2265,7 +2270,10 @@ function ItemsTabClass:UpdateAffixControl(control, item, affixType, outputTable, for _, line in ipairs(mod) do local rangedLine = itemLib.applyRange(line, main.defaultItemAffixQuality or 0.5, 1, 1) local modList, extra = modLib.parseMod(rangedLine) - local modLine = { line = line, modList = modList, extra = extra, modTags = mod.modTags, [mod.type] = true } + local modLine = { line = line, modList = modList, extra = extra, modTags = mod.modTags } + if mod.type then + modLine[mod.type] = true + end t_insert(testSubject.explicitModLines, modLine) end @@ -2410,7 +2418,11 @@ function ItemsTabClass:AddModComparisonTooltip(tooltip, mod) local newItem = new("Item", self.displayItem:BuildRaw()) for _, subMod in ipairs(mod) do - t_insert(newItem.explicitModLines, { line = checkLineForAllocates(subMod, self.build.spec.nodes), modTags = mod.modTags, [mod.type] = true }) + local modLine = { line = checkLineForAllocates(subMod, self.build.spec.nodes), modTags = mod.modTags } + if mod.type then + modLine[mod.type] = true + end + t_insert(newItem.explicitModLines, modLine) end newItem:BuildAndParseRaw() @@ -3770,370 +3782,7 @@ function ItemsTabClass:AddCrucibleModifierToDisplayItem() main:OpenPopup(710, 185, "Add Crucible Modifier to Item", controls, "save") end --- Opens the custom Implicit popup -function ItemsTabClass:AddImplicitToDisplayItem() - local controls = { } - local sourceList = { } - local modList = { } - local modGroups = {} - local sortList, sortStats = buildModSortList() - local function setDefaultSortOrder() - for groupIndex, group in ipairs(modGroups) do - group.defaultSortOrder = groupIndex - group.sortValue = nil - end - for _, listMods in ipairs(modList) do - for index, listMod in ipairs(listMods) do - listMod.defaultSortOrder = index - listMod.sortValue = nil - listMod.sortValues = nil - end - end - end - ---Mutates modList to contain mods from the specified source - ---@param sourceId string @The crafting source id to build the list of mods for - local function buildMods(sourceId) - wipeTable(modList) - wipeTable(modGroups) - local groupIndexes = {} - if sourceId == "EXARCH" or sourceId == "EATER" then - for i, mod in pairs(self.displayItem.affixes) do - if self.displayItem:GetModSpawnWeight(mod) > 0 and sourceId:lower() == mod.type:lower() then - local modLabel = table.concat(mod, "/") - local group = mod.group:gsub("PinnaclePresence", ""):gsub("UniquePresence", "") - if not groupIndexes[group] then - t_insert(modList, {}) - t_insert(modGroups, { - label = modLabel, - mod = mod, - modListIndex = #modList, - defaultOrder = i, - }) - groupIndexes[group] = #modGroups - end - t_insert(modList[groupIndexes[group]], { - label = modLabel, - mod = mod, - affixType = mod.type, - type = sourceId:lower(), - defaultOrder = i, - }) - end - end - table.sort(modGroups, 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) - for i, _ in pairs(modList) do - table.sort(modList[i], function(a, b) - local modA = a.mod - local modB = b.mod - if modA.group ~= modB.group then - if modA.group:match("PinnaclePresence") then - return false - elseif modB.group:match("PinnaclePresence") then - return true - elseif modA.group:match("UniquePresence") then - return false - else - return true - end - end - for j = 1, m_max(#modA, #modB) do - if not modA[j] then - return true - elseif not modB[j] then - return false - elseif modA.statOrder[j] ~= modB.statOrder[j] then - return modA.statOrder[j] < modB.statOrder[j] - else - local modAVal = tonumber(a.defaultOrder:match("%d+$")) - local modBVal = tonumber(b.defaultOrder:match("%d+$")) - return modAVal < modBVal - end - end - return modA.level > modB.level - end) - end - for i, _ in pairs(modGroups) do - modGroups[i].label = modList[modGroups[i].modListIndex][1].label:gsub("%([%d%.]+%-[%d%.]+%)", "#"):gsub("[%d%.]+", "#") - end - elseif sourceId == "SYNTHESIS" then - for i, mod in pairs(self.displayItem.affixes) do - if sourceId:lower() == mod.type:lower() then -- weights are missing and so are 0, how do I determine what goes on what item?, also arn't these supposed to work on jewels? - t_insert(modList, { - label = table.concat(mod, "/"), - mod = mod, - affixType = mod.type, - type = "synthesis", - defaultOrder = i, - }) - end - end - table.sort(modList, function(a, b) - return a.defaultOrder < b.defaultOrder - end) - elseif sourceId == "DelveImplicit" then - for i, mod in pairs(self.displayItem.affixes) do - if self.displayItem:GetModSpawnWeight(mod) > 0 and mod.type and sourceId:lower() == mod.type:lower() then - local modLabel = table.concat(mod, "/") - if not groupIndexes[mod.group] then - t_insert(modList, {}) - t_insert(modGroups, { - label = modLabel, - mod = mod, - modListIndex = #modList, - defaultOrder = i, - }) - groupIndexes[mod.group] = #modGroups - --elseif mod[1].len() < modGroups[groupIndexes[mod.group] ].mod[1].len() then - -- modGroups[groupIndexes[mod.group]].label = modLabel - -- modGroups[groupIndexes[mod.group]].mod = mod - end - t_insert(modList[groupIndexes[mod.group]], { - label = modLabel, - mod = mod, - affixType = mod.type, - type = "custom", - defaultOrder = i, - }) - end - end - for i, _ in pairs(modList) do - table.sort(modList[i], function(a, b) - return a.defaultOrder < b.defaultOrder - end) - end - end - setDefaultSortOrder() - end - if (self.displayItem.rarity ~= "UNIQUE" and self.displayItem.rarity ~= "RELIC") and (self.displayItem.type == "Helmet" or self.displayItem.type == "Body Armour" or self.displayItem.type == "Gloves" or self.displayItem.type == "Boots") then - if self.displayItem.cleansing then - t_insert(sourceList, { label = "Searing Exarch", sourceId = "EXARCH" }) - end - if self.displayItem.tangle then - t_insert(sourceList, { label = "Eater of Worlds", sourceId = "EATER" }) - end - end - if self.displayItem.type ~= "Flask" and self.displayItem.type ~= "Jewel" and self.displayItem.type ~= "Graft" then - --t_insert(sourceList, { label = "Synth", sourceId = "SYNTHESIS" }) -- synth removed until we get proper support for where the mods go - t_insert(sourceList, { label = "Delve", sourceId = "DelveImplicit" }) - end - t_insert(sourceList, { label = "Custom", sourceId = "CUSTOM" }) - buildMods(sourceList[1].sourceId) - ---Applies a candidate listMod to the item, mirroring the mutation addModifier() - ---performs at click-time. Eldritch (exarch/eater) sources replace an existing - ---implicit of the same type when present; other sources append. - local function applyCandidateMod(item, listMod) - if listMod.type == "exarch" or listMod.type == "eater" then - local index - for i, implicitMod in ipairs(item.implicitModLines) do - if implicitMod[listMod.type] then - index = i - break - end - end - if index then - for i, line in ipairs(listMod.mod) do - item.implicitModLines[index + i - 1] = { line = line, modTags = listMod.mod.modTags, [listMod.type] = true } - end - return - end - end - for _, line in ipairs(listMod.mod) do - t_insert(item.implicitModLines, { line = line, modTags = listMod.mod.modTags, [listMod.type] = true }) - end - 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 - applyCandidateMod(item, listMod) - item:BuildAndParseRaw() - local output = calcFunc({ repSlotName = slotName, repItem = item }, useFullDPS) - local value = data.powerStatList.GetFromOutput(output, sortStats[stat]) - listMod.sortValues[stat] = value - return value - end - local function applySort(stat, selectFirst) - if not controls.modSelect or not controls.modGroupSelect or not controls.modSelect:IsShown() then - return - end - local selectedGroup = not selectFirst and modGroups[controls.modGroupSelect.selIndex] or nil - local selectedMod = not selectFirst and controls.modSelect.list and controls.modSelect.list[controls.modSelect.selIndex] or nil - if stat then - local slotName = self.displayItem:GetPrimarySlot() - local calcFunc = self.build.calcsTab:GetMiscCalculator() - local useFullDPS = stat == "FullDPS" - for _, listMods in ipairs(modList) do - for _, listMod in ipairs(listMods) do - listMod.sortValue = getSortValue(listMod, stat, calcFunc, slotName, useFullDPS) - end - table.sort(listMods, 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) - end - for _, group in ipairs(modGroups) do - local best - for _, listMod in ipairs(modList[group.modListIndex] or { }) do - if not best or listMod.sortValue > best then - best = listMod.sortValue - end - end - group.sortValue = best or 0 - end - table.sort(modGroups, 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 - for _, listMods in ipairs(modList) do - table.sort(listMods, function(a, b) - return (a.defaultSortOrder or 0) < (b.defaultSortOrder or 0) - end) - end - table.sort(modGroups, function(a, b) - return (a.defaultSortOrder or 0) < (b.defaultSortOrder or 0) - end) - end - controls.modGroupSelect:UpdateSearch() - if selectedGroup then - for index, group in ipairs(modGroups) do - if group == selectedGroup then - controls.modGroupSelect.selIndex = index - break - end - end - else - controls.modGroupSelect:SetSel(1, true) - end - controls.modSelect.list = modList[modGroups[controls.modGroupSelect.selIndex].modListIndex] - controls.modSelect:UpdateSearch() - if selectedMod then - for index, listMod in ipairs(controls.modSelect.list) do - if listMod == selectedMod then - controls.modSelect.selIndex = index - break - end - end - else - controls.modSelect:SetSel(1, true) - end - end - local function addModifier() - local item = new("Item", self.displayItem:BuildRaw()) - item.id = self.displayItem.id - local sourceId = sourceList[controls.source.selIndex].sourceId - if sourceId == "CUSTOM" then - if controls.custom.buf:match("%S") then - t_insert(item.implicitModLines, { line = controls.custom.buf, custom = true }) - end - elseif sourceId == "SYNTHESIS" then - applyCandidateMod(item, modList[controls.modSelect.selIndex]) - else - applyCandidateMod(item, modList[modGroups[controls.modGroupSelect.selIndex].modListIndex][controls.modSelect.selIndex]) - end - item:BuildAndParseRaw() - return item - end - controls.sourceLabel = new("LabelControl", {"TOPRIGHT",nil,"TOPLEFT"}, {95, 20, 0, 16}, "^7Source:") - controls.source = new("DropDownControl", {"TOPLEFT",nil,"TOPLEFT"}, {100, 20, 150, 18}, sourceList, function(index, value) - if value.sourceId ~= "CUSTOM" then - controls.modSelectLabel.y = 70 - buildMods(value.sourceId) - controls.modGroupSelect:SetSel(1) - controls.modSelect.list = modList[modGroups[1].modListIndex] - controls.modSelect:SetSel(1) - if controls.sort then - applySort(controls.sort.list[controls.sort.selIndex].stat, true) - end - else - controls.modSelectLabel.y = 45 - end - end) - controls.source.enabled = #sourceList > 1 - controls.sortLabel = new("LabelControl", {"TOPRIGHT",nil,"TOPLEFT"}, {350, 20, 0, 16}, "^7Sort by:") - controls.sortLabel.shown = function() - return sourceList[controls.source.selIndex].sourceId ~= "CUSTOM" - end - controls.sort = new("DropDownControl", {"TOPLEFT",nil,"TOPLEFT"}, {355, 20, 240, 18}, sortList, function(index, value) - applySort(value.stat, true) - end) - controls.sort.shown = function() - return sourceList[controls.source.selIndex].sourceId ~= "CUSTOM" - end - controls.modGroupSelectLabel = new("LabelControl", {"TOPRIGHT",nil,"TOPLEFT"}, {95, 45, 0, 16}, "^7Type:") - controls.modGroupSelect = new("DropDownControl", {"TOPLEFT",nil,"TOPLEFT"}, {100, 45, 600, 18}, modGroups, function(index, value) - controls.modSelect.list = modList[value.modListIndex] - controls.modSelect:SetSel(1) - end) - controls.modGroupSelectLabel.shown = function() - if sourceList[controls.source.selIndex].sourceId == "CUSTOM" then - controls.modSelectLabel.y = 45 - end - return sourceList[controls.source.selIndex].sourceId ~= "CUSTOM" - end - controls.modGroupSelect.shown = function() - return sourceList[controls.source.selIndex].sourceId ~= "CUSTOM" - end - controls.modGroupSelect.tooltipFunc = function(tooltip, mode, index, value) - tooltip:Clear() - if mode ~= "OUT" and value then - for _, line in ipairs(value.mod) do - tooltip:AddLine(16, "^7"..line) - end - self:AddModComparisonTooltip(tooltip, value.mod) - end - end - controls.modSelectLabel = new("LabelControl", {"TOPRIGHT",nil,"TOPLEFT"}, {95, 70, 0, 16}, "^7Modifier:") - controls.modSelect = new("DropDownControl", {"TOPLEFT",nil,"TOPLEFT"}, {100, 70, 600, 18}, sourceList[controls.source.selIndex].sourceId ~= "CUSTOM" and modList[modGroups[1].modListIndex] or { }) - controls.modSelect.shown = function() - return sourceList[controls.source.selIndex].sourceId ~= "CUSTOM" - end - controls.modSelect.tooltipFunc = function(tooltip, mode, index, value) - tooltip:Clear() - if mode ~= "OUT" and value then - for _, line in ipairs(value.mod) do - tooltip:AddLine(16, "^7"..line) - end - self:AddModComparisonTooltip(tooltip, value.mod) - end - end - controls.custom = new("EditControl", {"TOPLEFT",nil,"TOPLEFT"}, {100, 45, 440, 18}) - controls.custom.shown = function() - return sourceList[controls.source.selIndex].sourceId == "CUSTOM" - end - controls.save = new("ButtonControl", nil, {-45, 100, 80, 20}, "Add", function() - self:SetDisplayItem(addModifier()) - main:ClosePopup() - end) - controls.save.tooltipFunc = function(tooltip) - tooltip:Clear() - self:AddItemTooltip(tooltip, addModifier()) - end - controls.close = new("ButtonControl", nil, {45, 100, 80, 20}, "Cancel", function() - main:ClosePopup() - end) - main:OpenPopup(710, 130, "Add Implicit to Item", controls, "save", sourceList[controls.source.selIndex].sourceId == "CUSTOM" and "custom") -end + function ItemsTabClass:AddItemSetTooltip(tooltip, itemSet) for _, slot in ipairs(self.orderedSlots) do diff --git a/src/Data/ModCache.lua b/src/Data/ModCache.lua index 5e65cff1d4..3149e8c408 100755 --- a/src/Data/ModCache.lua +++ b/src/Data/ModCache.lua @@ -9307,6 +9307,8 @@ c["Grants Level 20 Doryani's Touch Skill"]={{[1]={flags=0,keywordFlags=0,name="E c["Grants Level 20 Hatred Skill"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="Hatred"}}},nil} c["Grants Level 20 Illusory Warp Skill"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="IllusoryWarp"}}},nil} c["Grants Level 20 Misty Reflection Skill"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="MistyReflection"}}},nil} +c["Grants Level 20 Petrification Statue Skill"]={nil,nil} +c["Grants Level 20 Petrification Statue Skill 250% increased Energy Shield"]={nil,nil} c["Grants Level 20 Queen's Demand Skill"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="QueensDemand"}}},nil} c["Grants Level 20 Ravenous Skill"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="Ravenous"}}},nil} c["Grants Level 20 Savage Barnacle"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="BarnacleSnap"}}},nil} @@ -9318,8 +9320,6 @@ c["Grants Level 20 Summon Bestial Rhoa Skill"]={{[1]={flags=0,keywordFlags=0,nam c["Grants Level 20 Summon Bestial Snake Skill"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="SummonBeastialSnake"}}},nil} c["Grants Level 20 Summon Bestial Ursa Skill"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="SummonBeastialUrsa"}}},nil} c["Grants Level 20 Summon Doedre's Effigy Skill"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="SummonDoedresEffigy"}}},nil} -c["Grants Level 20 Summon Petrification Statue Skill"]={nil,nil} -c["Grants Level 20 Summon Petrification Statue Skill 250% increased Energy Shield"]={nil,nil} c["Grants Level 20 Summon Sentinel of Radiance Skill"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="SummonSentinelOfRadiance"}}},nil} c["Grants Level 20 Summon Shaper Memory"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="SummonShaperApparition"}}},nil} c["Grants Level 20 Thirst for Blood Skill"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="ThirstForBlood"}}},nil} @@ -11050,7 +11050,7 @@ c["Removes all but one Life on use Removed life is Regenerated as Energy Shield c["Removes all mana"]={{[1]={flags=0,keywordFlags=0,name="Mana",type="MORE",value=-100}},nil} c["Requires 8 Str, 8 Dex"]={nil,"Requires 8 Str, 8 Dex "} c["Requires 8 Str, 8 Dex 40% increased Cast Speed"]={nil,"Requires 8 Str, 8 Dex 40% increased Cast Speed "} -c["Requires 8 Str, 8 Dex Implicits: 0"]={nil,"Requires 8 Str, 8 Dex Implicits: 0 "} +c["Requires 8 Str, 8 Dex Source: Fishing"]={nil,"Requires 8 Str, 8 Dex Source: Fishing "} c["Requires Class Duelist"]={nil,"Requires Class Duelist "} c["Requires Class Duelist Allocates Bane of Legends if you have the matching modifier on Forbidden Flame"]={nil,"Requires Class Duelist Allocates Bane of Legends if you have the matching modifier on Forbidden Flame "} c["Requires Class Duelist Allocates Bane of Legends if you have the matching modifier on Forbidden Flesh"]={nil,"Requires Class Duelist Allocates Bane of Legends if you have the matching modifier on Forbidden Flesh "} diff --git a/src/Data/Uniques/body.lua b/src/Data/Uniques/body.lua index b4679d2706..fdb50a7d4c 100644 --- a/src/Data/Uniques/body.lua +++ b/src/Data/Uniques/body.lua @@ -182,6 +182,7 @@ Having a placed Banner does not prevent you gaining Valour Pragmatism Colosseum Plate League: Affliction +Source: unique{The King in the Mists} in the normal{Crux of Nothingness} Requires Level 49, 134 Str +12 to Level of Socketed Skill Gems (80-120)% increased Armour @@ -1157,6 +1158,7 @@ Gain a Power Charge for each Enemy you hit with a Critical Strike Waxen Soul Saint's Hauberk League: Ritual +Source: Reward from Nameless Ritual, and rarely a regular Ritual (10-20)% increased maximum Life +(17-29)% to Chaos Resistance Curse Skills cost Life instead of Mana diff --git a/src/Data/Uniques/boots.lua b/src/Data/Uniques/boots.lua index 17ece3e698..00b0fdd0eb 100644 --- a/src/Data/Uniques/boots.lua +++ b/src/Data/Uniques/boots.lua @@ -133,6 +133,7 @@ Unwavering Stance Redblade Tramplers Ancient Greaves League: Warbands +Source: Drops from Redblade Mercenary monsters Variant: Pre 2.6.0 Variant: Current Requires Level 46, 82 Str @@ -612,6 +613,7 @@ Stun Threshold is based on 500% of your Mana instead of Life Steppan Eard Sorcerer Boots League: Warbands +Source: Drops from Renegade Warband monsters Variant: Pre 3.0.0 Variant: Current Requires Level 67, 123 Int @@ -784,6 +786,7 @@ Lose Adrenaline when you cease to be Flame-Touched Gamblesprint Hydrascale Boots League: Affliction +Source: Reward from Ultimatum encounters Requires Level 59, 56 Str, 56 Dex +(30-40) to Dexterity (100-150)% increased Armour and Evasion @@ -951,6 +954,7 @@ Gain (10-20) Life per Enemy Killed Brinerot Whalers Trapper Boots League: Warbands +Source: Drops from Brinerot Warband monsters Variant: Pre 2.6.0 Variant: Pre 3.0.0 Variant: Current @@ -1170,6 +1174,7 @@ Celestial Footprints Olroth's Charge Runic Sollerets League: Expedition +Source: Drops from Expedition monsters Requires Level 48, 37 Str, 37 Dex, 37 Int (50-80)% increased Ward (30-50)% slower Restoration of Ward diff --git a/src/Data/Uniques/fishing.lua b/src/Data/Uniques/fishing.lua index cc7348da88..33630862ce 100644 --- a/src/Data/Uniques/fishing.lua +++ b/src/Data/Uniques/fishing.lua @@ -17,6 +17,7 @@ Glows while in an Area containing a Unique Fish Song of the Sirens Fishing Rod Requires 8 Str, 8 Dex +Source: Fishing Implicits: 0 Siren Worm Bait (50-60)% increased Rarity of Fish Caught diff --git a/src/Data/Uniques/gloves.lua b/src/Data/Uniques/gloves.lua index d6d342239d..246280a623 100644 --- a/src/Data/Uniques/gloves.lua +++ b/src/Data/Uniques/gloves.lua @@ -6,6 +6,7 @@ return { Admiral's Arrogance Antique Gauntlets League: Settlers of Kalguur +Source: Drops from unique{Admiral Valerius} in normal{Shipping encounters} Requires Level 39, 58 Str (6-12)% increased Attack Speed (100-140)% increased Armour @@ -886,6 +887,7 @@ Chaos Skills have 20% chance to Ignite Hand of Heresy Martyr Gloves League: Mercenaries of Trarthus +Source: Reward from Mercenary duel Variant: Pre 3.28.0 Variant: Current Requires Level 77, 70 Str, 70 Int @@ -921,7 +923,6 @@ Unaffected by Shock while Leeching Energy Shield Algor Mortis Carnal Mitts League: Delirium -Source: Drops from the Simulacrum Encounter Requires Level 50, 39 Dex, 39 Int +(50-70) to maximum Energy Shield +(15-20)% to Cold and Lightning Resistances @@ -1064,6 +1065,7 @@ Requires Level 5 ]],[[ Malachai's Mark Murder Mitts +Source: Drops from unique{Nightmare of the Depraved Trinity} in normal{Abomination Map} Requires Level 67, 51 Dex, 51 Int (80-100)% increased Evasion and Energy Shield +(60-80) to maximum Life @@ -1147,6 +1149,7 @@ Medved's Challenge Runic Gauntlets Requires Level 69, 38 Str, 38 Dex, 38 Int League: Expedition +Source: Drops from Expedition monsters 800% increased Attribute Requirements (30-50)% increased Ward +(15-25)% to all Elemental Resistances @@ -1159,6 +1162,7 @@ Variant: Pre 3.16.0 Variant: Pre 3.25.0 Variant: Current League: Expedition +Source: Drops from Expedition monsters Requires Level 48, 31 Str, 31 Dex, 31 Int (33-48)% increased Ward +(17-23)% to Chaos Resistance diff --git a/src/Data/Uniques/helmet.lua b/src/Data/Uniques/helmet.lua index f223435711..e26b16b3d6 100644 --- a/src/Data/Uniques/helmet.lua +++ b/src/Data/Uniques/helmet.lua @@ -133,6 +133,7 @@ Requires Level 55, 114 Str Kaom's Command Siege Helmet League: Settlers of Kalguur +Source: Kingsmarch Shipping to normal{Ngakanu} or normal{Te Onui} Requires Level 48, 101 Str +(60-80) to maximum Life (25-35)% increased Warcry Speed @@ -784,6 +785,7 @@ Bone Circlet Variant: Pre 3.19.0 Variant: Pre 3.24.0 Variant: Current +Source: Drops from unique{Nightmare of Catarina} in normal{Ziggurat Map} Requires Level: 34, 73 Int {variant:3}Has 4 Abyssal Sockets {variant:1,2}+2 to Level of Socketed Minion Gems @@ -1028,6 +1030,7 @@ Requires Level 36, 42 Str, 42 Dex El'Abin's Visage Fencer Helm League: Crucible +Source: Drops from Crucible monsters +(20-30) to Strength +(20-30) to Dexterity (80-120)% increased Armour and Evasion @@ -1038,6 +1041,7 @@ Crucible Passive Skill Tree is removed if this Modifier is removed The Trickster's Smile Visored Sallet League: Affliction +Source: Drops from Viridian Wildwood and Ritual monsters Requires Level 23, 28 Str, 28 Dex (60-100)% increased Armour and Evasion Reflects 100 Cold Damage to Melee Attackers @@ -1508,10 +1512,11 @@ Chaos Resistance is Zero Corrupted ]],[[ Gorgon's Gaze +Source: Drops from unique{Talin, Faithbreaker} in normal{Pillars of Arun} Regicide Mask Requires Level 52, 58 Dex, 58 Int Implicits: 0 -Grants Level 20 Summon Petrification Statue Skill +Grants Level 20 Petrification Statue Skill (200-250)% increased Energy Shield +(60-80) to maximum Life (5-10)% increased Attack and Cast Speed @@ -1714,6 +1719,7 @@ Lose all Power Charges when you Block Faithguard Runic Helm League: Expedition +Source: Drops from Expedition monsters Variant: Pre 3.19.0 Variant: Current +(20-30) to Intelligence diff --git a/src/Data/Uniques/jewel.lua b/src/Data/Uniques/jewel.lua index ced15ff27c..7ecb8a4861 100644 --- a/src/Data/Uniques/jewel.lua +++ b/src/Data/Uniques/jewel.lua @@ -857,18 +857,21 @@ Radius: Medium [[ Amanamu's Gaze Ghastly Eye Jewel +Source: Drops from unique{Abyssal Liches} in normal{Abyssal Depths} +(5-10) to all Attributes Minions have +6% to Damage over Time Multiplier per Ghastly Eye Jewel affecting you, up to a maximum of +30% ]],[[ Kurgal's Gaze Hypnotic Eye Jewel +Source: Drops from unique{Abyssal Liches} in normal{Abyssal Depths} +(10-20) to Intelligence 8% increased Effect of Arcane Surge on you per Hypnotic Eye Jewel affecting you, up to a maximum of 40% ]],[[ Tecrod's Gaze Murderous Eye Jewel +Source: Drops from unique{Abyssal Liches} in normal{Abyssal Depths} Variant: Pre 3.21.0 Variant: Current Requires Level 40 @@ -884,6 +887,7 @@ Requires Level 40 ]],[[ Ulaman's Gaze Searching Eye Jewel +Source: Drops from unique{Abyssal Liches} in normal{Abyssal Depths} Requires Level 40 +(10-20) to Dexterity Projectiles have 4% chance to be able to Chain when colliding with terrain per diff --git a/src/Data/Uniques/quiver.lua b/src/Data/Uniques/quiver.lua index 05afdc51d7..d7c9bcd588 100644 --- a/src/Data/Uniques/quiver.lua +++ b/src/Data/Uniques/quiver.lua @@ -295,6 +295,7 @@ Broadhead Arrow Quiver Variant: Pre 3.17.0 Variant: Current LevelReq: 52 +Source: Labyrinth Implicits: 2 {variant:2}(8-10)% increased Attack Speed {variant:1}6 to 12 Added Physical Damage with Bow Attacks diff --git a/src/Data/Uniques/shield.lua b/src/Data/Uniques/shield.lua index a08e27671f..08ee673a53 100644 --- a/src/Data/Uniques/shield.lua +++ b/src/Data/Uniques/shield.lua @@ -136,6 +136,7 @@ Triggers Level 20 Elemental Aegis when Equipped Redblade Banner Painted Tower Shield League: Warbands +Source: Drops from Redblade Mercenary monsters Variant: Pre 2.6.0 Variant: Pre 3.0.0 Variant: Pre 3.11.0 @@ -157,6 +158,7 @@ Implicits: 1 Svalinn Girded Tower Shield League: Settlers of Kalguur +Source: Drops from unique{The Black Knight} in a normal{Starfall Crater} Requires Level 51, 123 Str Implicits: 1 +(10-20) to maximum Life @@ -392,6 +394,7 @@ You are at Maximum Chance to Block Spell Damage if you have not Blocked Recently Mutewind Pennant Enameled Buckler League: Warbands +Source: Drop from Mutewind Mercenary monsters Variant: Pre 2.6.0 Variant: Pre 3.0.0 Variant: Pre 3.11.0 @@ -536,6 +539,7 @@ Your Raised Spectres also gain Arcane Surge when you do Brinerot Flag Tarnished Spirit Shield League: Warbands +Source: Drops from Brinerot Warband monsters Variant: Pre 2.6.0 Variant: Pre 3.0.0 Variant: Pre 3.11.0 @@ -672,6 +676,7 @@ Shocks you when you reach Maximum Power Charges Manastorm {variant:1}Fossilised Spirit Shield {variant:2,3}Lacewood Spirit Shield +Source: Drops from unique{Nightmare of Uhtred} in normal{Citadel Map} Variant: Pre 3.19.0 Variant: Pre 3.24.0 Variant: Current @@ -749,6 +754,7 @@ Implicits: 0 ]],[[ The Scales of Justice Chiming Spirit Shield +Source: Labyrinth Implicits: 1 (10-15)% increased Spell Damage Has no Energy Shield @@ -777,6 +783,7 @@ Curse Enemies with Elemental Weakness when you Block their Spell Damage, ignorin The Flawed Refuge Maple Round Shield League: Affliction +Source: Drops from Viridian Wildwood and Ritual monsters Requires Level 39, 52 Str, 52 Dex Implicits: 1 180% increased Block Recovery @@ -827,6 +834,7 @@ Teak Round Shield Variant: Pre 3.16.0 Variant: Current League: Heist +Source: Reward from Mercenary duel Implicits: 1 180% increased Block Recovery +2 to Level of Socketed Support Gems @@ -887,6 +895,7 @@ Socketed Support Gems can also Support Skills from your Main Hand ]],[[ Vix Lunaris Cardinal Round Shield +Source: Drops from unique{Selenia, the Endless Night} in normal{The Twilight Temple} Implicits: 0 +2 to Level of Socketed Gems Triggers Level 20 Cold Aegis when Equipped @@ -943,6 +952,7 @@ Implicits: 0 Broken Faith Archon Kite Shield League: Warbands +Source: Drops from Renegade Warband monsters Variant: Pre 2.6.0 Variant: Pre 3.11.0 Variant: Current @@ -976,6 +986,7 @@ Glancing Blows ]],[[ Invictus Solaris Archon Kite Shield +Source: Drops from unique{Helial, the Day Unending} Implicits: 1 +12% to all Elemental Resistances +2 to Level of Socketed Gems @@ -1214,7 +1225,6 @@ Implicits: 2 ]],[[ Leper's Alms Mirrored Spiked Shield -Source: Drops from unique{The Eradicator} Variant: Pre 3.5.0 Variant: Current Implicits: 1 diff --git a/src/Data/Uniques/staff.lua b/src/Data/Uniques/staff.lua index ec1afd8f1f..8c0bbd4139 100644 --- a/src/Data/Uniques/staff.lua +++ b/src/Data/Uniques/staff.lua @@ -780,6 +780,7 @@ Highborn Staff Variant: Pre 3.25.0 Variant: Current League: Crucible +Source: Drops from Crucible monsters Implicits: 2 {variant:1}+18% Chance to Block Attack Damage {variant:2}+22% Chance to Block Attack Damage diff --git a/src/Data/Uniques/sword.lua b/src/Data/Uniques/sword.lua index 70edcaf0b4..bc5138f0e6 100644 --- a/src/Data/Uniques/sword.lua +++ b/src/Data/Uniques/sword.lua @@ -494,6 +494,7 @@ Adds (75-92) to (125-154) Physical Damage The Redblade Gladius League: Crucible +Source: Drops from Crucible monsters Implicits: 1 40% increased Global Accuracy Rating (150-180)% increased Physical Damage diff --git a/src/Data/Vestigial.lua b/src/Data/Vestigial.lua new file mode 100644 index 0000000000..7cdea4f40c --- /dev/null +++ b/src/Data/Vestigial.lua @@ -0,0 +1,1425 @@ +-- This file is automatically generated, do not edit! +-- Game data (c) Grinding Gear Games + +-- This file describes which item each mod ID comes from. + +-- spell-checker: disable +return { + ["DivergentAbyssJewelSocketUnique__10"] = { + "Command of the Pit", + }, + ["DivergentAbyssJewelSocketUnique__12"] = { + "Bubonic Trail", + }, + ["DivergentAbyssJewelSocketUnique__14"] = { + "Replica Shroud of the Lightless", + }, + ["DivergentAbyssJewelSocketUnique__15"] = { + "Shroud of the Lightless", + }, + ["DivergentAbyssJewelSocketUnique__17"] = { + "Wraithlord", + }, + ["DivergentAbyssJewelSocketUnique__18"] = { + "Hale Negator", + }, + ["DivergentAddedChaosDamagePerCurseUnique__1"] = { + "Doedre's Scorn", + }, + ["DivergentAddedChaosDamageToAttacksPer50StrengthUnique__1"] = { + "Replica Alberon's Warpath", + }, + ["DivergentAddedColdDamageUniqueBodyDex1"] = { + "Hyrri's Ire", + }, + ["DivergentAddedLightningDamageUnique__4"] = { + "Replica Hyrri's Ire", + }, + ["DivergentAddedPhysicalDamageUniqueShieldDex6"] = { + "Great Old One's Ward", + }, + ["DivergentAdditionalBlockChanceUniqueShieldDex2"] = { + "The Unshattered Will", + }, + ["DivergentAdditionalCurseOnEnemiesUnique__1"] = { + "Windscream", + }, + ["DivergentAdditionalHolyRelicUnique__1"] = { + "Geofri's Crest", + }, + ["DivergentAdditionalPierceWhilePhasingUnique__1"] = { + "Voidwalker", + }, + ["DivergentAdrenalineOnFillingLifeLeechUnique__1"] = { + "Tanu Ahi", + }, + ["DivergentAdrenalineOnWardBreakUnique__1"] = { + "Olroth's Charge", + }, + ["DivergentAilmentDamageOverTimeMultiplierPerElderItemUnique__1"] = { + "Blasphemer's Grasp", + }, + ["DivergentAllAttributesUnique__21"] = { + "Forbidden Shako", + }, + ["DivergentAllAttributesUnique__6"] = { + "Loreweave", + }, + ["DivergentAllDamageCanFreezeUnique__1"] = { + "Expedition's End", + }, + ["DivergentAllDamageCanPoisonGloriousMadnessUnique___1"] = { + "Beacon of Madness", + }, + ["DivergentAllDefencesUnique__2"] = { + "Skin of the Loyal", + }, + ["DivergentAllResistancesUniqueHelmetDex3"] = { + "Goldrim", + }, + ["DivergentAllResistancesUnique__23__"] = { + "Medved's Challenge", + }, + ["DivergentAlternateColdAilmentUnique__1"] = { + "Galesight", + }, + ["DivergentAlternateFireAilmentUnique__1"] = { + "Flamesight", + }, + ["DivergentAlternateLightningAilmentUnique__1__"] = { + "Thundersight", + }, + ["DivergentAnimatedMinionsHaveMeleeSplashUnique__1"] = { + "Chains of Command", + }, + ["DivergentAnyRingMagicDamageExtraRollUnique__1"] = { + "Viridi's Veil", + }, + ["DivergentApplyAilmentsMoreDamageUnique__1"] = { + "Painseeker", + }, + ["DivergentArcaneSurgeOnMovementSkillUnique"] = { + "Scornflux", + }, + ["DivergentArcticArmourReservationCostUnique__1"] = { + "The Snowblind Grace", + }, + ["DivergentAreaOfEffectPerEnemyKilledRecentlyCapped25Unique__1"] = { + "Zeel's Amplifier", + }, + ["DivergentAreaOfEffectUniqueBodyDexInt1"] = { + "Carcass Jack", + }, + ["DivergentArmourAppliesToChaosDamagePercentUnique__1"] = { + "The Fourth Vow", + }, + ["DivergentArmourAppliesToLightningDamagePercentUnique__1"] = { + "Doryani's Prototype", + }, + ["DivergentArmourIncreasedByUncappedFireResistanceUnique__1"] = { + "The Formless Flame", + }, + ["DivergentArmourPerTotemUnique__1"] = { + "Tukohama's Fortress", + }, + ["DivergentAttackCorrosionOnHitChanceUnique__1"] = { + "Ceaseless Feast", + }, + ["DivergentAttackLightningDamageMaximumManaUnique__1__"] = { + "Mind of the Council", + }, + ["DivergentAttackSpeedOnFullLifeUniqueGlovesStr1"] = { + "Ondar's Clasp", + }, + ["DivergentAttackerTakesColdDamageUnique__1"] = { + "The Trickster's Smile", + }, + ["DivergentAttackerTakesFireDamageUnique__1"] = { + "The Trickster's Smile", + }, + ["DivergentAttackerTakesLightningDamageUnique__1"] = { + "The Trickster's Smile", + }, + ["DivergentAttacksBleedOnHitWithCatsStealthUnique__1_"] = { + "Farrul's Pounce", + }, + ["DivergentAuraEffectUniqueShieldInt2"] = { + "Matua Tupuna", + }, + ["DivergentAuraEffectWhileLinkedUnique__1"] = { + "The Hand of Phrecia", + }, + ["DivergentAvianAspectBuffEffectUnique__1"] = { + "Saqawal's Nest", + }, + ["DivergentAviansMightColdDamageUnique__1"] = { + "Saqawal's Winds", + }, + ["DivergentAviansMightLightningDamageUnique__1_"] = { + "Saqawal's Winds", + }, + ["DivergentAvoidFreezeAndChillIfFireSkillUsedRecentlyUnique__1"] = { + "Hrimnor's Resolve", + }, + ["DivergentAvoidIgniteOnLowLifeUniqueShieldStrInt5"] = { + "Rise of the Phoenix", + }, + ["DivergentAvoidInterruptionWhileCastingUnique__1"] = { + "Sandstorm Visage", + }, + ["DivergentBannerResourceGainedUnique__1"] = { + "Perfidy", + }, + ["DivergentBaseManaRegenerationUniqueBodyDexInt2"] = { + "Cloak of Defiance", + }, + ["DivergentBaseUnarmedCriticalStrikeChanceUnique__2"] = { + "Seven Teachings", + }, + ["DivergentBleedOnSelfDealChaosDamageUnique__1"] = { + "Apep's Supremacy", + }, + ["DivergentBleedingEnemiesExplodeUnique__1"] = { + "Haemophilia", + }, + ["DivergentBleedingImmunityUnique__1"] = { + "Death's Door", + }, + ["DivergentBlightSecondarySkillEffectDurationUnique__1"] = { + "Allelopathy", + }, + ["DivergentBlockChancePer50StrengthUnique__1"] = { + "The Iron Fortress", + }, + ["DivergentBlockChanceVersusCursedEnemiesUnique__1"] = { + "Chalice of Horrors", + }, + ["DivergentBlockVsProjectilesUniqueShieldStr2"] = { + "Titucius' Span", + }, + ["DivergentCannotBeFrozenUnique__1"] = { + "Vix Lunaris", + }, + ["DivergentCannotBeShockedWhileMaximumEnduranceChargesUnique_1"] = { + "Veruso's Battering Rams", + }, + ["DivergentCannotBeSlowedBelowBaseUnique__1"] = { + "Kaom's Roots", + }, + ["DivergentCannotBeStunnedSuppressedDamageUnique__1"] = { + "Orbala's Stand", + }, + ["DivergentCannotLoseCrabBarriersIfLostRecentlyUnique__1"] = { + "Craiceann's Chitin", + }, + ["DivergentCastSpeedAppliesToTrapSpeedUnique__1"] = { + "Architect's Hand", + }, + ["DivergentCatAspectReservesNoManaUnique__1___"] = { + "Farrul's Fur", + }, + ["DivergentCatsStealthTriggeredIntimidatingCry"] = { + "Farrul's Chase", + }, + ["DivergentChanceToBlockSpellsPerPowerChargeUnique__2_"] = { + "Willclash", + }, + ["DivergentChanceToCastOnManaSpentUnique__1"] = { + "Kitava's Thirst", + }, + ["DivergentChanceToFreezeShockIgniteUnique__1"] = { + "The Admiral", + }, + ["DivergentChanceToGainMaximumCrabBarriersUnique__1_"] = { + "Craiceann's Pincers", + }, + ["DivergentChanceToGainMaximumPowerChargesUnique__1_"] = { + "Inya's Epiphany", + }, + ["DivergentChanceToGainMaximumRageUnique__1"] = { + "Admiral's Arrogance", + }, + ["DivergentChanceToSapVsEnemiesInChillingAreasUnique__1"] = { + "Algor Mortis", + }, + ["DivergentChanceToSuppressSpellsUnique__1_"] = { + "The Oppressor", + }, + ["DivergentChanceToSuppressSpellsWhileChannellingUnique__1____"] = { + "Assailum", + }, + ["DivergentChanceToThrowFourAdditionalTrapsUnique__1"] = { + "Architect's Hand", + }, + ["DivergentChaosDamageCanIgniteUnique__1"] = { + "Replica Volkuur's Guidance", + }, + ["DivergentChaosDamageDoesNotBypassESNotLowLifeOrManaUnique__1"] = { + "Esh's Visage", + }, + ["DivergentChaosDamageDoesNotBypassEnergyShieldPercentUnique__2"] = { + "Shavronne's Wrappings", + }, + ["DivergentChaosDamageOverTimeUnique__1"] = { + "Solaris Lorica", + }, + ["DivergentChaosDamageRemovedFromManaBeforeLifeUnique__1___"] = { + "The Ivory Tower", + }, + ["DivergentChaosDegenAuraUnique__1"] = { + "Death's Oath", + }, + ["DivergentChaosResistanceIsZeroUnique__1"] = { + "Glimpse of Chaos", + }, + ["DivergentChaosResistanceWhileStationaryUnique__1"] = { + "Replica Red Trail", + }, + ["DivergentChaosResistanceWhileUsingFlaskUniqueBootsStrDex3"] = { + "Dusktoe", + }, + ["DivergentChargeDurationUniqueBodyDexInt3"] = { + "The Restless Ward", + }, + ["DivergentColdAddedAsFireChilledEnemyUnique__1"] = { + "Heatshiver", + }, + ["DivergentColdDamageCanPoisonAndLessDurationUnique__1"] = { + "Volkuur's Guidance", + }, + ["DivergentColdDamageOverTimeMultiplierUnique__2"] = { + "Rime Gaze", + }, + ["DivergentColdExposureOnHitUnique__1"] = { + "Eye of Malice", + }, + ["DivergentColdHitAndDoTDamageTakenAsLightningUnique__1"] = { + "Font of Thunder", + }, + ["DivergentColdIgnitesUniqueHelmetDexInt4_"] = { + "The Three Dragons", + }, + ["DivergentColdResistanceOverrideUnique__1"] = { + "Cowl of the Cryophile", + }, + ["DivergentCommandmentOfInfernoOnCritUnique__1"] = { + "Unyielding Flame", + }, + ["DivergentConvertFireToChaosUniqueBodyInt4Updated"] = { + "Infernal Mantle", + }, + ["DivergentConvertPhysicalToColdUniqueGlovesDex1"] = { + "Hrimsorrow", + }, + ["DivergentConvertPhysicalToFireUniqueShieldStr3"] = { + "Chernobog's Pillar", + }, + ["DivergentCorpseWalkUnique__1"] = { + "Corpsewalker", + }, + ["DivergentCounterAttacksAddedColdDamageUnique__1"] = { + "Lycosidae", + }, + ["DivergentCrabBarriersLostWhenHitUnique__1_"] = { + "Craiceann's Tracks", + }, + ["DivergentCreateSmokeCloudWhenTrapTriggeredUnique__1"] = { + "Kongming's Stratagem", + }, + ["DivergentCriticalMultiplierPerBlockChanceUnique__1"] = { + "Light of Lunaris", + }, + ["DivergentCriticalStrikeChancePerBrandUnique__1___"] = { + "Replica Tukohama's Fortress", + }, + ["DivergentCriticalStrikeChanceUniqueGlovesDex2"] = { + "Maligaro's Virtuosity", + }, + ["DivergentCriticalStrikeChanceUniqueHelmetDex6"] = { + "Rat's Nest", + }, + ["DivergentCurseOnHitCriticalWeaknessUniqueNewUnique__1"] = { + "Oskarm", + }, + ["DivergentCurseOnHitTemporalChainsUnique__1"] = { + "Asenath's Gentle Touch", + }, + ["DivergentCurseSkillsCostAndReserveLifeUnique__1"] = { + "Waxen Soul", + }, + ["DivergentDamageOverTimeMultiplierIfCrit8SecondsUnique__1_"] = { + "Qotra's Regulator", + }, + ["DivergentDamagePer15DexterityUnique__2"] = { + "Briskwrap", + }, + ["DivergentDamageTakenFromMarkedTargetUnique__1"] = { + "Mercenary's Lot", + }, + ["DivergentDamageTakenFromTotemLifeBeforePlayerUnique__1"] = { + "Dawnstrider", + }, + ["DivergentDamageTakenPer5RageCappedAt50PercentUnique_1"] = { + "The Caged Mammoth", + }, + ["DivergentDamageYouReflectGainedAsLifeUniqueHelmetDexInt6"] = { + "Crown of the Pale King", + }, + ["DivergentDebuffTimePassedUnique__2"] = { + "Stasis Prison", + }, + ["DivergentDisplayDamageAuraUniqueHelmetDexInt2"] = { + "Leer Cast", + }, + ["DivergentDisplayGrantsBloodOfferingUnique__1_"] = { + "Bloodbond", + }, + ["DivergentDisplaySocketedGemGetsAddedLightningDamageUnique__1"] = { + "Thunderfist", + }, + ["DivergentDisplaySocketedGemGetsFasterAttackUniqueHelmetStrDex4"] = { + "The Bringer of Rain", + }, + ["DivergentDisplaySocketedGemGetsSpellTotemBodyInt7"] = { + "Soul Mantle", + }, + ["DivergentDisplaySocketedMinionGemsSupportedByLifeLeechUnique__1"] = { + "Cloak of Tawm'r Isley", + }, + ["DivergentDisplaySupportedByAddedColdDamageUnique__2"] = { + "Replica Covenant", + }, + ["DivergentDisplaySupportedByUnleashUnique__1"] = { + "Replica Kalisa's Grace", + }, + ["DivergentDodgeAndSpellDodgePerMaximumManaUnique__1"] = { + "Omeyocan", + }, + ["DivergentDoubleDamageChanceGloriousMadnessUnique_1"] = { + "Beacon of Madness", + }, + ["DivergentDrainAllManaLightningDamageUnique__1"] = { + "Manastorm", + }, + ["DivergentElementalAilmentImmunityGloriousMadnessUnique1"] = { + "Beacon of Madness", + }, + ["DivergentElementalConfluxesGloriousMadnessUnique1"] = { + "Beacon of Madness", + }, + ["DivergentElementalDamageTakenAsChaosUniqueBodyStrInt5"] = { + "Incandescent Heart", + }, + ["DivergentElementalDamageTakenAsPhysicalUnique__1"] = { + "The Flawed Refuge", + }, + ["DivergentElementalWeaknessOnSpellBlockUniqueShieldInt4"] = { + "Sentari's Answer", + }, + ["DivergentElusiveEffectUnique__1"] = { + "Replica Three-step Assault", + }, + ["DivergentEnemiesBlockedAreIntimidatedUnique__1"] = { + "The Anticipation", + }, + ["DivergentEnemiesCantLifeLeechUnique__1"] = { + "Sin Trek", + }, + ["DivergentEnemiesCountAsMovingElementalAilmentsUnique__1"] = { + "The Tempest Rising", + }, + ["DivergentEnemiesExplodeOnDeathChaosGloriousMadnessUnique1"] = { + "Beacon of Madness", + }, + ["DivergentEnemiesKilledApplyImpaleDamageUnique__1"] = { + "Great Old One's Tentacles", + }, + ["DivergentEnemiesKilledCountAsYoursUnique__1"] = { + "Gravebind", + }, + ["DivergentEnemyExtraDamageRollsOnFullLifeUnique__2"] = { + "Foxshade", + }, + ["DivergentEnemyExtraDamagerollsWithPhysicalDamageUnique_1"] = { + "Refuge in Isolation", + }, + ["DivergentEnemyKnockbackDirectionReversedUniqueGlovesStr5_"] = { + "Empire's Grasp", + }, + ["DivergentEnergyShieldAdditiveModifiersInsteadApplyToWardUnique__"] = { + "Faithguard", + }, + ["DivergentEnergyShieldGainedOnBlockUniqueShieldStrInt4"] = { + "Aegis Aurora", + }, + ["DivergentEnergyShieldPerStrengthUnique__1"] = { + "Shaper's Touch", + }, + ["DivergentEnergyShieldRechargeOnKillUnique__1__"] = { + "Sudden Dawn", + }, + ["DivergentEnergyShieldRecoveryRateUnique__1"] = { + "The Beast Fur Shawl", + }, + ["DivergentEvasionIncreasedByUncappedColdResistanceUnique__1"] = { + "The Snowblind Grace", + }, + ["DivergentEvasionIncreasedByUncappedColdResistanceUnique__2"] = { + "The Perfect Form", + }, + ["DivergentEvasionModifersApplyToSpellDamageUnique__1"] = { + "The Unblinking Eye", + }, + ["DivergentEvasionRatingPerIntelligenceUnique__1"] = { + "Shaper's Touch", + }, + ["DivergentEvasionRatingPercentOnLowLifeUniqueHelmetDex4"] = { + "Starkonja's Head", + }, + ["DivergentExcommunicateOnMeleeHitUnique"] = { + "Hand of Heresy", + }, + ["DivergentFacebreakerUnarmedMoreDamage"] = { + "Facebreaker", + }, + ["DivergentFireDamageCanPoisonAndLessDurationUnique__1"] = { + "Volkuur's Guidance", + }, + ["DivergentFireDamageTakenConvertedToPhysicalUnique__1"] = { + "The Rat Cage", + }, + ["DivergentFireExposureOnHitUnique__1"] = { + "Eye of Malice", + }, + ["DivergentFireHitAndDoTDamageTakenAsLightningUnique__1"] = { + "Font of Thunder", + }, + ["DivergentFireResistanceOverrideUnique__1__"] = { + "Cowl of the Thermophile", + }, + ["DivergentFireShocksUniqueHelmetDexInt4"] = { + "The Three Dragons", + }, + ["DivergentFortifyEffectSelfGloriousMadnessUnique1"] = { + "Beacon of Madness", + }, + ["DivergentFreezeDurationUniqueGlovesStrInt3"] = { + "Southbound", + }, + ["DivergentFreezeEnemiesWhenHitChanceUnique__1"] = { + "Icetomb", + }, + ["DivergentFrenzyChargeOnCritCloseRangeUnique__1"] = { + "Usurper's Penance", + }, + ["DivergentFungalAroundWhenStationaryUnique__1_"] = { + "Sporeguard", + }, + ["DivergentGainArmourEqualToManaReservedUnique__1"] = { + "Memory Vault", + }, + ["DivergentGainFrenzyChargeOnTrapTriggeredUnique__1"] = { + "Tinkerskin", + }, + ["DivergentGainLifeOnBlockUnique__1"] = { + "The Surrender", + }, + ["DivergentGainManaAsExtraEnergyShieldUnique__1"] = { + "Mindspiral", + }, + ["DivergentGainMaximumEnduranceChargesWhenCritUnique__1"] = { + "Ambu's Charge", + }, + ["DivergentGainOnslaughtWhileCatsAgilityUnique__1_"] = { + "Replica Farrul's Fur", + }, + ["DivergentGainSoulEaterStackOnHitUnique__1"] = { + "Soul Ascension", + }, + ["DivergentGainThaumaturgyBuffRotationUnique__1_"] = { + "Malachai's Mark", + }, + ["DivergentGhostFurnace1"] = { + "The Draugur's Lantern", + }, + ["DivergentGlimpseOfEternityWhenHitUnique__1"] = { + "The Eternity Shroud", + }, + ["DivergentGlobalAddedChaosDamageWardUnique__"] = { + "Nightgrip", + }, + ["DivergentGlobalIncreaseMinionSpellSkillGemLevelUnique__3"] = { + "The Devourer of Minds", + }, + ["DivergentGlobalIncreaseMinionSpellSkillGemLevelUnique__4"] = { + "The Dark Monarch", + }, + ["DivergentGrantAlliesFrenzyChargeOnHitUnique__1"] = { + "Victario's Charity", + }, + ["DivergentGrantAlliesPowerChargeOnKillUnique__1"] = { + "Victario's Charity", + }, + ["DivergentGrantsAlliesEnduranceChargeOnHitUnique__1"] = { + "Replica Victario's Charity", + }, + ["DivergentGrantsAlliesFrenzyChargeOnKillUnique__1_"] = { + "Replica Victario's Charity", + }, + ["DivergentGrantsAvianTornadoUnique__1__"] = { + "Saqawal's Flock", + }, + ["DivergentGrantsBirdAspect1_"] = { + "Saqawal's Talons", + }, + ["DivergentGrantsCatAspect1"] = { + "Farrul's Bite", + }, + ["DivergentGrantsRavenousSkillUnique__1"] = { + "Veruso's Ambition", + }, + ["DivergentGrantsSpiderAspect1"] = { + "Fenumus' Weave", + }, + ["DivergentGrantsSummonArbalistsSkillUnique__1_"] = { + "Vorana's March", + }, + ["DivergentGrantsSummonBeastRhoaUnique__1"] = { + "Yriel's Fostering", + }, + ["DivergentGrantsSummonBeastSnakeUnique__1"] = { + "Yriel's Fostering", + }, + ["DivergentGrantsSummonBeastUrsaUnique__1"] = { + "Yriel's Fostering", + }, + ["DivergentGrantsSummonVoidSpawnUnique__1"] = { + "Servant of Decay", + }, + ["DivergentGrantsTouchOfGodUnique__1"] = { + "Doryani's Fist", + }, + ["DivergentGrantsVoidGazeUnique__1"] = { + "Eber's Unification", + }, + ["DivergentGraspFromBeyondTrapUnique_1"] = { + "Hand of the Lords", + }, + ["DivergentHarbingerSkillOnEquipUnique2_5"] = { + "The Tempest's Liberation", + }, + ["DivergentHarbingerSkillOnEquipUnique2__3"] = { + "The Immortal Will", + }, + ["DivergentHarbingerSkillOnEquipUnique__3"] = { + "The Unshattered Will", + }, + ["DivergentHarbingerSkillOnEquipUnique__5"] = { + "The Tempest's Binding", + }, + ["DivergentHasBrutalShrineBuffUnique__1"] = { + "Blunderbore", + }, + ["DivergentHasMassiveShrineBuffUnique__1"] = { + "Blunderbore", + }, + ["DivergentHealAlliesOnDeathUniqueShieldDexInt2"] = { + "Maligaro's Lens", + }, + ["DivergentIgnoreHexproofUnique___1"] = { + "Cospri's Will", + }, + ["DivergentImmuneToBurningGroundUniqueBootsStr3"] = { + "Redblade Tramplers", + }, + ["DivergentImmuneToDesecratedGroundUniqueBootsInt6"] = { + "Steppan Eard", + }, + ["DivergentImmuneToElementalAilmentsWhileLifeAndManaCloseUnique__1"] = { + "The Scales of Justice", + }, + ["DivergentIncreaseProjectileAttackDamagePerAccuracyUnique__1"] = { + "Obscurantis", + }, + ["DivergentIncreaseSocketedSupportGemQualityUnique__1___"] = { + "The Squire", + }, + ["DivergentIncreasedAttackSpeedUniqueBootsDexInt1"] = { + "Sundance", + }, + ["DivergentIncreasedDamagePerPowerChargeUnique__1"] = { + "Inya's Epiphany", + }, + ["DivergentIncreasedDamageToIgnitedTargetsUniqueBootsStrInt3"] = { + "Gang's Momentum", + }, + ["DivergentIncreasedDamageWhileLeechingUnique__2__"] = { + "Offering to the Serpent", + }, + ["DivergentIncreasedElementalResistancesUnique__1"] = { + "Replica Veil of the Night", + }, + ["DivergentIncreasedEvasionIfHitRecentlyUnique___1"] = { + "Kintsugi", + }, + ["DivergentIncreasedEvasionWithOnslaughtUnique_1"] = { + "Three-step Assault", + }, + ["DivergentIncreasedExperienceUniqueIntHelmet3"] = { + "Chitus' Apex", + }, + ["DivergentIncreasedItemRarityUniqueShieldStrDex2"] = { + "Wheel of the Stormsail", + }, + ["DivergentIncreasedLifeLeechRateUniqueBodyStrDex4"] = { + "Cherrubim's Maleficence", + }, + ["DivergentIncreasedLifeNoLifeModifiersUnique__1"] = { + "Utula's Hunger", + }, + ["DivergentIncreasedLifeUniqueBodyStr1"] = { + "Kaom's Heart", + }, + ["DivergentIncreasedLifeUnique__114"] = { + "Kaom's Spirit", + }, + ["DivergentIncreasedLifeWhileNoCorruptedItemsUnique__1"] = { + "Voll's Vision", + }, + ["DivergentIncreasedManaUnique__19"] = { + "Replica Kaom's Heart", + }, + ["DivergentIncreasedMaximumResistsUniqueShieldStrInt1"] = { + "Saffell's Frame", + }, + ["DivergentIncreasedPhysicalDamagePercentUnique__4"] = { + "Gruthkul's Pelt", + }, + ["DivergentIncreasedProjectileDamageUniqueBootsDexInt4"] = { + "Brinerot Whalers", + }, + ["DivergentIncreasedSpellDamagePerPowerChargeUnique__1"] = { + "Malachai's Loop", + }, + ["DivergentIncreasedSpiderWebCountUnique__1"] = { + "Fenumus' Spinnerets", + }, + ["DivergentIronWillUniqueGlovesStrInt4__"] = { + "Repentance", + }, + ["DivergentItemActsAsConcentratedAOESupportUnique__1"] = { + "Wyrmsign", + }, + ["DivergentItemFoundRarityIncreaseUniqueBodyStr5"] = { + "Greed's Embrace", + }, + ["DivergentItemFoundRarityIncreaseUniqueGlovesStrDex2"] = { + "Aurseize", + }, + ["DivergentItemFoundRarityIncreaseUnique__10"] = { + "Goldwyrm", + }, + ["DivergentItemFoundRarityIncreaseUnique__7"] = { + "Sadima's Touch", + }, + ["DivergentItemHasSixLinkedWhiteSocketsUniqueBodyInt6"] = { + "Tabula Rasa", + }, + ["DivergentItemRarityOnLowLifeUniqueBootsInt1"] = { + "Wondertrap", + }, + ["DivergentKeystoneAncestralBondUnique__2"] = { + "Wilma's Requital", + }, + ["DivergentKeystoneCallToArmsUnique__2_"] = { + "Mutewind Pennant", + }, + ["DivergentKeystoneCorruptedSoulUnique__2_"] = { + "Mahuxotl's Machination", + }, + ["DivergentKeystoneDivineFleshUnique__1_"] = { + "Mahuxotl's Machination", + }, + ["DivergentKeystoneEternalYouthUnique__2_"] = { + "Mahuxotl's Machination", + }, + ["DivergentKeystoneEverlastingSacrificeUnique__1"] = { + "Mahuxotl's Machination", + }, + ["DivergentKeystoneGlancingBlowsUnique__1___"] = { + "Emperor's Vigilance", + }, + ["DivergentKeystoneInnerConvictionUnique__1"] = { + "Voll's Protector", + }, + ["DivergentKeystoneIronGripUnique__1"] = { + "Giantsbane", + }, + ["DivergentKeystoneSoulTetherUnique__2"] = { + "Mahuxotl's Machination", + }, + ["DivergentKeystoneUnwaveringStanceUnique__1"] = { + "Kaom's Roots", + "Ezomyte Peak", + }, + ["DivergentKeystoneVaalPactUnique__2"] = { + "Mahuxotl's Machination", + }, + ["DivergentLifeFromEnergyShieldArmourPercentUnique__1"] = { + "The Apostate", + }, + ["DivergentLifeGainOnEndurangeChargeConsumptionUniqueBodyStrInt6"] = { + "Kingsguard", + }, + ["DivergentLifeRegenPerMinutePerEnduranceChargeUnique__1"] = { + "The Restless Ward", + }, + ["DivergentLifeRegenerationFlatOnLowLifeUnique__1"] = { + "Springleaf", + }, + ["DivergentLifeRegenerationPer500EnergyShieldUnique__1"] = { + "Mask of the Stitched Demon", + }, + ["DivergentLifeRegenerationWith1000EnergyShieldUnique__1"] = { + "Mask of the Spirit Drinker", + }, + ["DivergentLightRadiusToDamageUnique_1"] = { + "Wreath of Phrecia", + }, + ["DivergentLightRadiusUniqueBodyInt8"] = { + "Zahndethus' Cassock", + }, + ["DivergentLightningAddedAsColdShockedEnemyUnique__1"] = { + "Replica Heatshiver", + }, + ["DivergentLightningDamageCanPoisonAndLessDurationUnique__1"] = { + "Volkuur's Guidance", + }, + ["DivergentLightningFreezesUniqueHelmetDexInt4"] = { + "The Three Dragons", + }, + ["DivergentLightningResistanceOverrideUnique__1_"] = { + "Cowl of the Ceraunophile", + }, + ["DivergentLinkedMinionsStealRareModsUnique_1"] = { + "The Hallowed Monarch", + }, + ["DivergentLocalArmourAndEvasionAndEnergyShieldUniqueBodyStrDexInt"] = { + "Atziri's Splendour", + }, + ["DivergentLocalIncreaseSocketedActiveSkillGemLevelUnique__1"] = { + "Pragmatism", + }, + ["DivergentLocalIncreaseSocketedAuraGemLevelUnique___3"] = { + "March of the Legion", + }, + ["DivergentLocalIncreaseSocketedElementalGemUniqueGlovesInt6"] = { + "Voidbringer", + }, + ["DivergentLocalIncreaseSocketedGemLevelUnique__8"] = { + "Honourhome", + }, + ["DivergentLocalIncreaseSocketedHeraldLevelUnique__2"] = { + "Replica Alpha's Howl", + }, + ["DivergentLocalIncreaseSocketedMovementGemLevelUniqueBodyDex5"] = { + "Bronn's Lithe", + }, + ["DivergentLocalIncreaseSocketedProjectileGemLevelUnique__1"] = { + "Black Zenith", + }, + ["DivergentManaLeechPermyriadUniqueGlovesStrDex1"] = { + "Slitherpinch", + }, + ["DivergentManaRegenerationAuraUnique__1"] = { + "Replica Leer Cast", + }, + ["DivergentManaReservationEfficiencyPerAttributeUnique__1"] = { + "Mask of the Tribunal", + }, + ["DivergentManaReservationEfficiencyUniqueHelmetDex5_"] = { + "Replica Alpha's Howl", + }, + ["DivergentMaximumCrabBarriersUnique__1"] = { + "Craiceann's Carapace", + }, + ["DivergentMaximumFortificationUnique__1"] = { + "The Celestial Brace", + }, + ["DivergentMaximumFrenzyChargesUniqueBootsStrDex2"] = { + "Darkray Vectors", + }, + ["DivergentMaximumLifeConvertedToEnergyShieldUnique__2"] = { + "Ghostwrithe", + }, + ["DivergentMaximumLifePer10DexterityUnique__1"] = { + "Garukhan's Flight", + }, + ["DivergentMaximumLifeUniqueBodyStrDex1"] = { + "Belly of the Beast", + }, + ["DivergentMaximumMinionCountUniqueBootsInt4"] = { + "Bones of Ullr", + }, + ["DivergentMaximumResistanceWithNoEnduranceChargesUnique__1__"] = { + "Ahn's Heritage", + }, + ["DivergentMaximumResistancesOverrideUnique__1"] = { + "Loreweave", + }, + ["DivergentMaximumResistancesWhilePoisonedUnique__1"] = { + "Apep's Slumber", + }, + ["DivergentMeleePhysicalDamagePerDexterityUnique__1_"] = { + "Shaper's Touch", + }, + ["DivergentMeleeSplashUnique__1"] = { + "Meginord's Vise", + }, + ["DivergentMeleeWeaponCriticalStrikeMultiplierReplicaUniqueHelmetStr3"] = { + "Replica Abyssus", + }, + ["DivergentMeleeWeaponCriticalStrikeMultiplierUniqueHelmetStr3"] = { + "Abyssus", + }, + ["DivergentMineDamageLeechedToYouUnique__1"] = { + "Machina Mitts", + }, + ["DivergentMinimumEnduranceChargesUnique__1"] = { + "Ralakesh's Impatience", + }, + ["DivergentMinimumFrenzyChargesUnique__1"] = { + "Ralakesh's Impatience", + }, + ["DivergentMinimumPowerChargesUnique__1"] = { + "Ralakesh's Impatience", + }, + ["DivergentMinionAttackBlockChanceUnique__2"] = { + "Skullhead", + }, + ["DivergentMinionAttackSpeedPerXDexUnique__1"] = { + "Speaker's Wreath", + }, + ["DivergentMinionChanceToFreezeShockIgnite"] = { + "Triad Grip", + }, + ["DivergentMinionCriticalStrikeChanceMaximumPowerChargeUnique__1"] = { + "Ancient Skull", + }, + ["DivergentMinionElementalDamageAddedAsChaosUnique__1"] = { + "Vis Mortis", + }, + ["DivergentMinionEnergyShieldRechargeDelayUnique__1"] = { + "Fleshcrafter", + }, + ["DivergentMinionLargerAggroRadiusUnique__1"] = { + "Maw of Mischief", + }, + ["DivergentMinionLifeAlsoAffectsYouUnique__1"] = { + "Rigwald's Hunt", + }, + ["DivergentMinionLifeIncreasedByOvercappedFireResistanceUnique__1"] = { + "The Formless Inferno", + }, + ["DivergentMinionPhysicalDamageAddedAsColdUnique__1_"] = { + "Grip of the Council", + }, + ["DivergentMinionPhysicalDamageAddedAsFireUnique__1"] = { + "Replica Grip of the Council", + }, + ["DivergentMinionSpellBlockChanceUnique__2"] = { + "Skullhead", + }, + ["DivergentMinionsGainYourStrengthUnique__1"] = { + "The Baron", + }, + ["DivergentModifyableWhileCorruptedUnique__2"] = { + "Hands of the High Templar", + }, + ["DivergentMovementSpeedPerPoisonOnSelfUnique__1"] = { + "Temptation Step", + }, + ["DivergentMovementVelocityOnFullLifeUniqueBootsInt3"] = { + "Shavronne's Pace", + }, + ["DivergentMovementVelocityOverrideUnique__1"] = { + "The Stampede", + }, + ["DivergentMovementVelocityOverrideUnique__2"] = { + "Replica Stampede", + }, + ["DivergentMovementVelocityPerEvasionLesserUnique__1"] = { + "Queen of the Forest", + }, + ["DivergentMovementVelocityPerFrenzyChargeUniqueBootsDex4"] = { + "The Blood Dance", + }, + ["DivergentMovementVelocityPerFrenzyChargeUnique__2"] = { + "Replica Restless Ward", + }, + ["DivergentMovementVelocityUniqueHelmetStrDex2"] = { + "Devoto's Devotion", + }, + ["DivergentMovementVelocityUnique___6"] = { + "Seven-League Step", + }, + ["DivergentMovementVelocityWhileOnFullEnergyShieldUniqueBootsDex8"] = { + "Nomic's Storm", + }, + ["DivergentNearbyEnemiesAreScorchedUnique__1"] = { + "Legacy of Fury", + }, + ["DivergentNearbyEnemiesCannotCritUnique__1"] = { + "Garb of the Ephemeral", + }, + ["DivergentNearbyEnemiesHaveReducedAllResistancesUnique__1"] = { + "Crown of the Tyrant", + }, + ["DivergentNearbyEnemyReservesLifeUnique__1"] = { + "Blood Price", + }, + ["DivergentNearbyStationaryEnemiesGainVinesUnique__1"] = { + "Inextricable Fate", + }, + ["DivergentNoExtraBleedDamageWhileMovingUnique__1"] = { + "The Infinite Pursuit", + }, + ["DivergentNonInstantManaRecoveryAlsoAffectsLifeUnique__1"] = { + "Indigon", + }, + ["DivergentOnslaughtBuffOnKillUniqueHelmet1"] = { + "Thrillsteel", + }, + ["DivergentOnslaughtEffectUnique__1"] = { + "Daresso's Defiance", + }, + ["DivergentOnslaughtOnVaalSkillUseUniqueGlovesStrDex4"] = { + "Vaal Caress", + }, + ["DivergentOnslaughtWhileNotOnLowManaUnique__1_"] = { + "Dance of the Offered", + }, + ["DivergentPainAttunement"] = { + "Crown of Thorns", + }, + ["DivergentPercentDexterityIfStrengthHigherThanIntelligenceUnique__1"] = { + "Fractal Thoughts", + }, + ["DivergentPercentageDexterityUniqueHelmetStrDex6"] = { + "Black Sun Crest", + }, + ["DivergentPercentageIntelligenceUniqueHelmetStrDex6"] = { + "Black Sun Crest", + }, + ["DivergentPercentageStrengthUniqueHelmetStrDex6"] = { + "Black Sun Crest", + }, + ["DivergentPerfectAgonyIfCritRecentlyUnique__1"] = { + "Replica Atziri's Acuity", + }, + ["DivergentPetrificationStatueUnique__1"] = { + "Gorgon's Gaze", + }, + ["DivergentPhasingIfBlockedRecentlyReplicaUnique__1"] = { + "Replica Mistwall", + }, + ["DivergentPhasingIfBlockedRecentlyUnique__1"] = { + "Mistwall", + }, + ["DivergentPhysAddedAsChaosWithMaxPowerChargesUnique__1"] = { + "Ahn's Contempt", + }, + ["DivergentPhysicalAddedAsColdUnique__2"] = { + "Kaltenhalt", + }, + ["DivergentPhysicalDamageConvertToChaosBodyStrInt4"] = { + "Lightbane Raiment", + }, + ["DivergentPhysicalDamageOnSkillUseUniqueHelmetInt8"] = { + "Scold's Bridle", + }, + ["DivergentPhysicalDamageReductionWhileNotMovingUnique__1"] = { + "The Red Trail", + }, + ["DivergentPhysicalDamageTakenAsLightningPercentUniqueBodyStrDex2"] = { + "Lightning Coil", + }, + ["DivergentPhysicalDamageTakenPercentToReflectUniqueBodyStr2"] = { + "Bramblejack", + }, + ["DivergentPhysicalHitAndDoTDamageTakenAsFireUnique__2"] = { + "Cloak of Flame", + }, + ["DivergentPlaceAdditionalMineWith600DexterityUnique__1"] = { + "Curtain Call", + }, + ["DivergentPlaceAdditionalMineWith600IntelligenceUnique__1"] = { + "Curtain Call", + }, + ["DivergentPoisonDotMultiplierPerFrenzyChargeUniqueGlovesDexInt5"] = { + "Snakebite", + }, + ["DivergentPowerChargeOnCriticalStrikeChanceUnique__1"] = { + "Skyforth", + }, + ["DivergentPowerChargeOnHitWebbedEnemyUnique__1"] = { + "Fenumus' Toxins", + }, + ["DivergentPowerChargeOnTrapThrowChanceUniqueShieldDexInt1"] = { + "Jaws of Agony", + }, + ["DivergentPowerFrenzyOrEnduranceChargeOnKillUnique__1"] = { + "Lochtonial Caress", + }, + ["DivergentProfaneGroundInsteadOfConsecratedGround__1_"] = { + "Broken Faith", + }, + ["DivergentProjectileAvoidUnique"] = { + "Azadi Crest", + }, + ["DivergentProjectileSpeedUnique__8"] = { + "The Fledgling", + }, + ["DivergentProjectileSpeedUnique___1"] = { + "Winds of Change", + }, + ["DivergentProjectilesChainWhilePhasingUnique__1"] = { + "Replica Voidwalker", + }, + ["DivergentPunishmentOnMeleeBlockUniqueShieldInt4"] = { + "Sentari's Answer", + }, + ["DivergentPurityOfFireUnique__6"] = { + "Doryani's Delusion", + }, + ["DivergentPurityOfIceUnique__6"] = { + "Doryani's Delusion", + }, + ["DivergentPurityOfLightningUnique__6"] = { + "Doryani's Delusion", + }, + ["DivergentQuicksilverFlaskAppliesToAlliesUnique__1"] = { + "Victario's Flight", + }, + ["DivergentRageCasterStats50PercentValueUnique__1"] = { + "Ravenous Passion", + }, + ["DivergentRagingSpiritFireSplashDamageUnique__1"] = { + "Mark of the Red Covenant", + }, + ["DivergentRandomCurseWhenHitChanceUnique__1"] = { + "Ylfeban's Trickery", + }, + ["DivergentRandomMovementVelocityWhenHitUnique__1"] = { + "Gamblesprint", + }, + ["DivergentRangedAttackDamageReducedUniqueShieldStr1"] = { + "Lioneye's Remorse", + }, + ["DivergentRangedWeaponPhysicalDamagePlusPercentUnique__1"] = { + "Ashrend", + }, + ["DivergentRecoverLifeOnSuppressUnique__1"] = { + "Elevore", + }, + ["DivergentReducedReservationForSocketedCurseGemsUnique__1"] = { + "Heretic's Veil", + }, + ["DivergentReflectDamageToAttackersOnBlockUniqueShieldDex5"] = { + "Thousand Teeth Temu", + }, + ["DivergentRegenerateLifeNotUnhingedUnique__1"] = { + "Doppelganger Guise", + }, + ["DivergentRepeatingShockwaveUnique__1"] = { + "Abberath's Hooves", + }, + ["DivergentResistancesOfWebbedEnemiesUnique__1"] = { + "Fenumus' Shroud", + }, + ["DivergentRetaliateSkillUseWindowDuration_1"] = { + "Bitter Instinct", + }, + ["DivergentReviveEnemiesOnKillUnique__1"] = { + "Breathstealer", + }, + ["DivergentSacrificeLifeToGainESUnique__1"] = { + "Demon Stitcher", + }, + ["DivergentSacrificialZealOnSkillUseUnique__1_"] = { + "Hand of the Fervent", + }, + ["DivergentSavageBarnacleMod_1"] = { + "Seablister", + }, + ["DivergentScorchOnEnemiesOnBlockUnique__1"] = { + "Dawnbreaker", + }, + ["DivergentSelfOfferingEffectUnique__2"] = { + "The Queen's Hunger", + }, + ["DivergentSetElementalResistancesUniqueHelmetStrInt4"] = { + "Veil of the Night", + }, + ["DivergentShareEnduranceChargesWithParty"] = { + "Ambu's Charge", + }, + ["DivergentSharedSufferingUnique__1"] = { + "Leper's Alms", + }, + ["DivergentShockEffectUnique__2"] = { + "Stormcharger", + }, + ["DivergentShockProliferationUnique__1"] = { + "Storm's Gift", + }, + ["DivergentShockProliferationUnique__2"] = { + "Esh's Mirror", + }, + ["DivergentShockedEnemiesExplodeUnique__1_"] = { + "Inpulsa's Broken Heart", + }, + ["DivergentShockedGroundWhileMovingUnique__1"] = { + "Wake of Destruction", + }, + ["DivergentShrineBuffEffectUniqueHelmetDexInt3"] = { + "The Gull", + }, + ["DivergentSimulatedRampageDexInt6"] = { + "Shadows and Dust", + }, + ["DivergentSimulatedRampageStrDex5"] = { + "Null and Void", + }, + ["DivergentSimulatedRampageStrInt2"] = { + "Flesh and Spirit", + }, + ["DivergentSkeletonWarriorsPermanentMinionUnique__1"] = { + "Alberon's Warpath", + }, + ["DivergentSkillsExertAttacksDoNotCountChanceUnique__1"] = { + "Deidbell", + }, + ["DivergentSocketedCursesAreReflectedUniqueGlovesStrInt1"] = { + "Shackles of the Wretched", + }, + ["DivergentSocketedGemQualityUnique__1"] = { + "Crest of Desire", + }, + ["DivergentSocketedGemsGetElementalProliferationUniqueBodyInt5"] = { + "Thousand Ribbons", + }, + ["DivergentSocketedGemsHaveAddedChaosDamageUnique__3"] = { + "The Covenant", + }, + ["DivergentSocketedGemsHaveReducedManaCostUniqueHelmetDexInt5"] = { + "The Vertex", + }, + ["DivergentSocketedGemsInBlueSocketEffectUnique__1"] = { + "Dialla's Malefaction", + }, + ["DivergentSocketedGemsInGreenSocketEffectUnique__1"] = { + "Dialla's Malefaction", + }, + ["DivergentSocketedGemsInRedSocketEffectUnique__1"] = { + "Dialla's Malefaction", + }, + ["DivergentSocketedGemsSupportedByBlasphemyUnique__3"] = { + "Heretic's Veil", + }, + ["DivergentSocketedGemsSupportedByCastOnDeathUniqueHelmetStrInt5"] = { + "The Broken Crown", + }, + ["DivergentSocketedGemsSupportedByPierceUniqueBodyStr6"] = { + "Lioneye's Vision", + }, + ["DivergentSocketedItemsHaveReducedReservationUniqueBodyDexInt4"] = { + "Victario's Influence", + }, + ["DivergentSocketedItemsHaveReducedReservationUniqueShieldStrInt2"] = { + "Prism Guardian", + }, + ["DivergentSocketedWarcryCooldownCountUnique__1"] = { + "Echoes of Creation", + }, + ["DivergentSpellBlockPercentageOnLowLifeUniqueShieldStrDex1_"] = { + "Daresso's Courage", + }, + ["DivergentSpellBlockPercentageUniqueBootsInt5"] = { + "Rainbowstride", + }, + ["DivergentSpellCriticalStrikeChancePerLifeUnique__1"] = { + "Rathpith Globe", + }, + ["DivergentSpellCriticalStrikeChancePerSpectreUnique__1_"] = { + "Bitterbind Point", + }, + ["DivergentSpellCriticalStrikeChanceUniqueBootsStrDex5"] = { + "Mutewind Whispersteps", + }, + ["DivergentSpellDamageFromMainHandWeaponDamageUnique__1"] = { + "Sandstorm Visage", + }, + ["DivergentSpellDamageModifiersApplyToAttackDamageUniqueHelmetInt7"] = { + "Crown of Eyes", + }, + ["DivergentSpellDamageUniqueGlovesInt2"] = { + "Doedre's Tenure", + }, + ["DivergentSpellDodgeUniqueBootsDex7New"] = { + "Atziri's Step", + }, + ["DivergentSpellImpaleOnCritChanceUnique__1"] = { + "Entropic Devastation", + }, + ["DivergentSpellsCriticalChanceFinalRepeatUnique__1"] = { + "Plume of Pursuit", + }, + ["DivergentSpellsDoubleDamageChanceUnique__1"] = { + "Malachai's Simula", + }, + ["DivergentSpiritMinionRefreshOnUniqueHitUnique__1"] = { + "Replica Bones of Ullr", + }, + ["DivergentStealChargesOnHitPercentUniqueGlovesStrDex6"] = { + "Surgebinders", + }, + ["DivergentStrUniqueShieldTriggerShieldShatterOnBlock"] = { + "Shattershard", + }, + ["DivergentStunAvoidancePerHeraldUnique__1"] = { + "The Coming Calamity", + }, + ["DivergentSupportedByFasterCastUnique__1"] = { + "Kalisa's Grace", + }, + ["DivergentSupportedByLesserPoisonUnique__1"] = { + "Dendrobate", + }, + ["DivergentSupportedByRageUnique__1__"] = { + "Hateforge", + }, + ["DivergentSupportedByVileToxinsUnique__1"] = { + "The Embalmer", + }, + ["DivergentTakeNoExtraDamageFromCriticalStrikesUnique__1"] = { + "The Brass Dome", + }, + ["DivergentTemporalChainsOnProjectileBlockUniqueShieldInt4"] = { + "Sentari's Answer", + }, + ["DivergentTotemLeechLifeToYouUnique__1"] = { + "Trolltimber Spire", + }, + ["DivergentTotemReflectFireDamageUnique__1_"] = { + "Torchoak Step", + }, + ["DivergentTouchedByTormentedSpiritsUnique__1"] = { + "Fairgraves' Tricorne", + }, + ["DivergentTransfigurationOfBodyUnique__1"] = { + "Crown of the Inward Eye", + }, + ["DivergentTransfigurationOfMindUnique__1"] = { + "Crown of the Inward Eye", + }, + ["DivergentTransfigurationOfSoulUnique__1_"] = { + "Crown of the Inward Eye", + }, + ["DivergentTrapThrowSpeedUniqueBootsDex6"] = { + "Deerstalker", + }, + ["DivergentTreatResistancesAsMaxChanceUnique__1"] = { + "Kiloava's Bluster", + }, + ["DivergentTriggerFeastOfFleshSkillUnique__1_"] = { + "The Devouring Diadem", + }, + ["DivergentTriggerRainOfArrowsOnBowAttackUnique__1"] = { + "Lioneye's Paws", + }, + ["DivergentTriggerShadeFormWhenHitUnique__1"] = { + "Replica Eternity Shroud", + }, + ["DivergentTriggerSocketedCurseSkillsOnCurseUnique__1_"] = { + "Vixen's Entrapment", + }, + ["DivergentTriggerSocketedElementalSpellOnBlockUnique__1"] = { + "Svalinn", + }, + ["DivergentTriggerSocketedSpellOnBowAttackUnique__2"] = { + "Asenath's Mark", + }, + ["DivergentTriggerToxicRainOnBowAttackUnique__1"] = { + "Replica Lioneye's Paws", + }, + ["DivergentTriggeredColdAegisSkillUnique__1"] = { + "Vix Lunaris", + }, + ["DivergentTriggeredElementalAegisSkillUnique__1_"] = { + "Magna Eclipsis", + }, + ["DivergentTriggeredFireAegisSkillUnique__1_"] = { + "Invictus Solaris", + }, + ["DivergentTriggeredLightningAegisSkillUnique__1"] = { + "Perepiteia", + }, + ["DivergentTriggeredPhysicalAegisSkillUnique__1"] = { + "The Ghastly Theatre", + }, + ["DivergentUnaffectedByChillLeechingManaUnique__1"] = { + "Stormseeker", + }, + ["DivergentUnaffectedByCursesUnique__1"] = { + "Atziri's Reflection", + }, + ["DivergentUnaffectedByDamagingAilmentsUnique__1"] = { + "Kahuturoa's Certainty", + }, + ["DivergentUnaffectedByPoisonUnique__1_"] = { + "Maw of Conquest", + }, + ["DivergentUnaffectedByShockLeechingESUnique__1"] = { + "Stormseeker", + }, + ["DivergentUnwaveringStanceUnique_2"] = { + "Cowards' Wail", + }, + ["DivergentVaalPactIfCritRecentlyUnique__1"] = { + "Atziri's Acuity", + }, + ["DivergentVulnerabilityOnBlockUniqueShieldStrDex3"] = { + "The Deep One's Hide", + }, + ["DivergentWarcryAreaOfEffectUnique__2"] = { + "Howlcrack", + }, + ["DivergentWarcryCooldownSpeedUnique__1"] = { + "The Eternal Apple", + }, + ["DivergentWarcryCooldownSpeedUnique__2"] = { + "Redblade Banner", + }, + ["DivergentWarcryCorpseExplosionUnique__1"] = { + "Kaom's Command", + }, + ["DivergentWarcryGrantsArcaneSurgeUnique__1"] = { + "Brinerot Flag", + }, + ["DivergentWarcrySpeedUnique__1"] = { + "Akoya's Gaze", + }, + ["DivergentWintertideBrandChillEffectUnique__1_"] = { + "Replica Allelopathy", + }, + ["DivergentWitherOnHitChanceUnique__1"] = { + "Abhorrent Interrogation", + }, + ["DivergentZealotsOathUnique__1"] = { + "Geofri's Sanctuary", + }, + ["DivergentZombiesNeedNoCorpsesUnique__1"] = { + "Aukuna's Will", + }, +} diff --git a/src/Export/Scripts/vestigial.lua b/src/Export/Scripts/vestigial.lua new file mode 100644 index 0000000000..547a56c69a --- /dev/null +++ b/src/Export/Scripts/vestigial.lua @@ -0,0 +1,123 @@ +local utils = LoadModule("../Modules/Utils") + +local vestigialUniqueBaseTypes = { + Helmet = LoadModule("Uniques/helmet"), + ["Body Armour"] = LoadModule("Uniques/body"), + Gloves = LoadModule("Uniques/gloves"), + Boots = LoadModule("Uniques/boots"), + Shield = LoadModule("Uniques/shield"), +} +local output = {} + +local mods = LoadModule("../Data/ModItemExclusive") + +for id, mod in pairs(mods) do + if id:find("^Divergent") then + output[id] = {} + for baseType, itemList in pairs(vestigialUniqueBaseTypes) do + for _, itemText in ipairs(itemList) do + if itemText:find("[\n}]" .. id:gsub("^Divergent", "")) then + -- first row should be unique title + local title = itemText:match("([^\n]+)\n") + -- äöå are too powerful for pob (ascii only) + :gsub("ä", "a"):gsub("ö", "o"):gsub("å", "a") + table.insert(output[id], title) + break + end + end + end + end +end + +-- pob's unique ids aren't perfect and are originally automatically generated, +-- which means many items have the wrong id despite the mod itself being +-- correct. these have been cross-referenced with the wiki, which is manually +-- confirmed to be correct in most cases. some of these also have ids that +-- aren't the same as the original. usually in cases where the effect is nerfed +-- in some way +-- spell-checker: disable +local manualFixes = { + -- no clue and these are not important anyway + ["DivergentAbyssJewelSocketUnique__3"] = false, + ["DivergentAbyssJewelSocketUnique__5"] = false, + ["DivergentAbyssJewelSocketUnique__7"] = false, + -- this only seems to come from boots despite the item ID being on multiple base types + ["DivergentAdditionalCurseOnEnemiesUnique__1"] = { "Windscream" }, + ["DivergentAbyssJewelSocketUnique__10"] = { "Command of the Pit" }, + ["DivergentAbyssJewelSocketUnique__15"] = { "Shroud of the Lightless" }, + ["DivergentAbyssJewelSocketUnique__18"] = { "Hale Negator" }, + ["DivergentAllAttributesUnique__21"] = { "Forbidden Shako" }, + -- Skin of the Lords perhaps? The item can't actually be used as it is always corrupted + ["DivergentAllDefencesUnique__3"] = false, + ["DivergentAreaOfEffectPerEnemyKilledRecentlyCapped25Unique__1"] = { "Zeel's Amplifier" }, + ["DivergentArmourAppliesToChaosDamagePercentUnique__1"] = { "The Fourth Vow" }, + ["DivergentArmourAppliesToLightningDamagePercentUnique__1"] = { "Doryani's Prototype" }, + ["DivergentBleedingImmunityUnique__1"] = { "Death's Door" }, + ["DivergentCannotBeFrozenUnique__1"] = { "Vix Lunaris" }, + -- Complete mystery + ["DivergentCannotBeFrozenUnique__6"] = false, + ["DivergentChaosDamageDoesNotBypassEnergyShieldPercentUnique__2"] = { "Shavronne's Wrappings" }, + ["DivergentFireDamageCanPoisonAndLessDurationUnique__1"] = { "Volkuur's Guidance" }, + ["DivergentColdDamageCanPoisonAndLessDurationUnique__1"] = { "Volkuur's Guidance" }, + ["DivergentLightningDamageCanPoisonAndLessDurationUnique__1"] = { "Volkuur's Guidance" }, + ["DivergentConvertFireToChaosUniqueBodyInt4Updated"] = { "Infernal Mantle" }, + ["DivergentCorpseWalkUnique__1"] = { "Corpsewalker" }, + ["DivergentCurseOnHitCriticalWeaknessUniqueNewUnique__1"] = { "Oskarm" }, + ["DivergentCurseOnHitTemporalChainsUnique__1"] = { "Asenath's Gentle Touch" }, + ["DivergentEnemyExtraDamageRollsOnFullLifeUnique__2"] = { "Foxshade" }, + ["DivergentEvasionIncreasedByUncappedColdResistanceUnique__2"] = { "The Perfect Form" }, + ["DivergentGhostFurnace1"] = { "The Draugur's Lantern" }, + ["DivergentIncreasedItemRarityUniqueShieldStrDex2"] = { "Wheel of the Stormsail" }, + ["DivergentItemFoundRarityIncreaseUnique__7"] = { "Sadima's Touch" }, + ["DivergentItemHasSixLinkedWhiteSocketsUniqueBodyInt6"] = { "Tabula Rasa" }, + ["DivergentKeystoneAncestralBondUnique__2"] = { "Wilma's Requital" }, + ["DivergentKeystoneCallToArmsUnique__2_"] = { "Mutewind Pennant" }, + ["DivergentKeystoneCorruptedSoulUnique__2_"] = { "Mahuxotl's Machination" }, + ["DivergentKeystoneEternalYouthUnique__2_"] = { "Mahuxotl's Machination" }, + ["DivergentKeystoneSoulTetherUnique__2"] = { "Mahuxotl's Machination" }, + ["DivergentKeystoneVaalPactUnique__2"] = { "Mahuxotl's Machination" }, + ["DivergentLifeFromEnergyShieldArmourPercentUnique__1"] = { "The Apostate" }, + ["DivergentLocalIncreaseSocketedGemLevelUnique__8"] = { "Honourhome" }, + ["DivergentLocalIncreaseSocketedProjectileGemLevelUnique__1"] = { "Black Zenith" }, + ["DivergentOnslaughtBuffOnKillUniqueHelmet1"] = { "Thrillsteel" }, + ["DivergentPetrificationStatueUnique__1"] = { "Gorgon's Gaze" }, + ["DivergentEnemiesCantLifeLeechUnique__1"] = { "Sin Trek" }, + ["DivergentGrantsSummonArbalistsSkillUnique__1_"] = { "Vorana's March" }, + ["DivergentMeleeWeaponCriticalStrikeMultiplierReplicaUniqueHelmetStr3"] = { "Replica Abyssus" }, + ["DivergentMinimumEnduranceChargesUnique__1"] = { "Ralakesh's Impatience" }, + ["DivergentMinimumFrenzyChargesUnique__1"] = { "Ralakesh's Impatience" }, + ["DivergentMinimumPowerChargesUnique__1"] = { "Ralakesh's Impatience" }, + ["DivergentZealotsOathUnique__1"] = { "Geofri's Sanctuary" }, + ["DivergentSpellsCriticalChanceFinalRepeatUnique__1"] = { "Plume of Pursuit" }, + ["DivergentSpellDamageFromMainHandWeaponDamageUnique__1"] = { "Sandstorm Visage" }, + ["DivergentSocketedGemsSupportedByBlasphemyUnique__3"] = { "Heretic's Veil" }, + ["DivergentSelfOfferingEffectUnique__2"] = { "The Queen's Hunger" }, + ["DivergentSavageBarnacleMod_1"] = { "Seablister" }, + ["DivergentRepeatingShockwaveUnique__1"] = { "Abberath's Hooves" }, + ["DivergentRageCasterStats50PercentValueUnique__1"] = { "Ravenous Passion" }, + ["DivergentPurityOfFireUnique__6"] = { "Doryani's Delusion" }, + ["DivergentPurityOfIceUnique__6"] = { "Doryani's Delusion" }, + ["DivergentPurityOfLightningUnique__6"] = { "Doryani's Delusion" }, + ["DivergentProjectileSpeedUnique___1"] = { "Winds of Change" }, + ["DivergentPhasingIfBlockedRecentlyReplicaUnique__1"] = { "Replica Mistwall" }, + ["DivergentMovementVelocityPerEvasionLesserUnique__1"] = { "Queen of the Forest" }, + ["DivergentMovementVelocityOverrideUnique__2"] = { "Replica Stampede" }, + ["DivergentModifyableWhileCorruptedUnique__2"] = { "Hands of the High Templar" }, + -- No clue, but looks like a dupe anyyway + ["DivergentCannotBeFrozenOrChilledUnique__2"] = false, +} +-- spell-checker: enable + +for k, v in pairs(manualFixes) do + output[k] = v and v or nil +end +for k, v in pairs(output) do + if #v > 1 then + print(string.format("Mod id %s has ambiguous mapping. Check and fix manually", k)) + elseif #v == 0 then + print(string.format("Mod id %s has no mapping. Check and fix manually", k)) + end +end +local vestigialDescription = "This file describes which item each mod ID comes from." +print("Vestigial mappings exported.") +utils.saveTableToFile("../Data/Vestigial.lua", output, vestigialDescription) diff --git a/src/Export/Uniques/body.lua b/src/Export/Uniques/body.lua index 1fc5d9f1c5..548b896c83 100644 --- a/src/Export/Uniques/body.lua +++ b/src/Export/Uniques/body.lua @@ -180,6 +180,7 @@ Allow2ActiveBannersUnique__1 Pragmatism Colosseum Plate League: Affliction +Source: unique{The King in the Mists} in the normal{Crux of Nothingness} Requires Level 49, 134 Str LocalIncreaseSocketedActiveSkillGemLevelUnique__1 LocalIncreasedPhysicalDamageReductionRatingPercentUnique__19 @@ -663,7 +664,7 @@ Implicits: 1 CriticalStrikeChanceUniqueBodyInt4 {variant:1,2}LocalIncreasedEnergyShieldUniqueBodyInt4[190,230] {variant:3,4,5}LocalIncreasedEnergyShieldUniqueBodyInt4 -ConvertFireToChaosUniqueBodyInt4 +ConvertFireToChaosUniqueBodyInt4Updated {variant:1,2,5}SpellDamageTakenOnLowManaUniqueBodyInt4[100,100] {variant:3}SpellDamageTakenOnLowManaUniqueBodyInt4[25,25] {variant:4}SpellDamageTakenOnLowManaUniqueBodyInt4[15,15] @@ -1149,6 +1150,7 @@ AddPowerChargeOnCrit1__ Waxen Soul Saint's Hauberk League: Ritual +Source: Reward from Nameless Ritual, and rarely a regular Ritual MaximumLifeUnique__28 ChaosResistUnique__39 CurseSkillsCostAndReserveLifeUnique__1 diff --git a/src/Export/Uniques/boots.lua b/src/Export/Uniques/boots.lua index 4a4cc7f233..19c472373a 100644 --- a/src/Export/Uniques/boots.lua +++ b/src/Export/Uniques/boots.lua @@ -133,6 +133,7 @@ KeystoneUnwaveringStanceUnique__1 Redblade Tramplers Ancient Greaves League: Warbands +Source: Drops from Redblade Mercenary monsters Variant: Pre 2.6.0 Variant: Current Requires Level 46, 82 Str @@ -603,6 +604,7 @@ StunThresholdBasedOnManaUnique__1 Steppan Eard Sorcerer Boots League: Warbands +Source: Drops from Renegade Warband monsters Variant: Pre 3.0.0 Variant: Current Requires Level 67, 123 Int @@ -774,6 +776,7 @@ LoseAdrenalineFireTouchedLossUnique__1 Gamblesprint Hydrascale Boots League: Affliction +Source: Reward from Ultimatum encounters Requires Level 59, 56 Str, 56 Dex DexterityUniqueBootsDex4_ LocalIncreasedArmourAndEvasionUnique__24 @@ -940,6 +943,7 @@ LifeGainedFromEnemyDeathUniqueBootsStrInt1 Brinerot Whalers Trapper Boots League: Warbands +Source: Drops from Brinerot Warband monsters Variant: Pre 2.6.0 Variant: Pre 3.0.0 Variant: Current @@ -1158,6 +1162,7 @@ CelestialFootprintsUnique__1_ Olroth's Charge Runic Sollerets League: Expedition +Source: Drops from Expedition monsters Requires Level 48, 37 Str, 37 Dex, 37 Int LocalIncreasedWardPercentUnique__4_ WardDelayRecoveryUnique__2 diff --git a/src/Export/Uniques/fishing.lua b/src/Export/Uniques/fishing.lua index a7cfa9b1e6..883e8b2de5 100644 --- a/src/Export/Uniques/fishing.lua +++ b/src/Export/Uniques/fishing.lua @@ -17,6 +17,7 @@ FishDetectionUnique__1_ Song of the Sirens Fishing Rod Requires 8 Str, 8 Dex +Source: Fishing Implicits: 0 FishingLureTypeUniqueFishingRod1 FishingRarityUniqueFishingRod1 diff --git a/src/Export/Uniques/gloves.lua b/src/Export/Uniques/gloves.lua index dc8d68b130..ba7bab05ee 100644 --- a/src/Export/Uniques/gloves.lua +++ b/src/Export/Uniques/gloves.lua @@ -6,6 +6,7 @@ return { Admiral's Arrogance Antique Gauntlets League: Settlers of Kalguur +Source: Drops from unique{Admiral Valerius} in normal{Shipping encounters} Requires Level 39, 58 Str IncreasedAttackSpeedUnique__7 LocalIncreasedPhysicalDamageReductionRatingPercentUnique__1 @@ -484,7 +485,7 @@ LocalIncreasedEnergyShieldUniqueGlovesInt1 {variant:1}ItemFoundQuantityIncreaseUniqueGlovesInt1[18,24] {variant:2}ItemFoundQuantityIncreaseUniqueGlovesInt1[12,16] {variant:3}ItemFoundQuantityIncreaseUniqueGlovesInt1 -{variant:4}ItemFoundRarityIncreaseUniqueGlovesStrDex2[10,15] +{variant:4}ItemFoundRarityIncreaseUnique__7[10,15] ]],[[ Voidbringer Conjurer Gloves @@ -874,6 +875,7 @@ UniqueVolkuursGuidanceIgniteDurationFinal Hand of Heresy Martyr Gloves League: Mercenaries of Trarthus +Source: Reward from Mercenary duel Variant: Pre 3.28.0 Variant: Current Requires Level 77, 70 Str, 70 Int @@ -908,7 +910,6 @@ UnaffectedByShockLeechingESUnique__1 Algor Mortis Carnal Mitts League: Delirium -Source: Drops from the Simulacrum Encounter Requires Level 50, 39 Dex, 39 Int IncreasedEnergyShieldUnique__9 ColdAndLightningResistUnique__2 @@ -1050,6 +1051,7 @@ Requires Level 5 ]],[[ Malachai's Mark Murder Mitts +Source: Drops from unique{Nightmare of the Depraved Trinity} in normal{Abomination Map} Requires Level 67, 51 Dex, 51 Int LocalIncreasedEvasionAndEnergyShieldUnique__8 IncreasedLifeUniqueGlovesInt3 @@ -1133,6 +1135,7 @@ Medved's Challenge Runic Gauntlets Requires Level 69, 38 Str, 38 Dex, 38 Int League: Expedition +Source: Drops from Expedition monsters IncreasedLocalAttributeRequirementsUnique__1 LocalIncreasedWardPercentUnique__3 AllResistancesUnique__23__ @@ -1145,6 +1148,7 @@ Variant: Pre 3.16.0 Variant: Pre 3.25.0 Variant: Current League: Expedition +Source: Drops from Expedition monsters Requires Level 48, 31 Str, 31 Dex, 31 Int LocalIncreasedWardPercentUnique__1_ ChaosResistUnique__10 diff --git a/src/Export/Uniques/helmet.lua b/src/Export/Uniques/helmet.lua index 0e427623a1..3a178b2245 100644 --- a/src/Export/Uniques/helmet.lua +++ b/src/Export/Uniques/helmet.lua @@ -131,6 +131,7 @@ ColdResistUniqueStrHelmet2 Kaom's Command Siege Helmet League: Settlers of Kalguur +Source: Kingsmarch Shipping to normal{Ngakanu} or normal{Te Onui} Requires Level 48, 101 Str IncreasedLifeUnique__3 WarcrySpeedUnique__2 @@ -770,6 +771,7 @@ Bone Circlet Variant: Pre 3.19.0 Variant: Pre 3.24.0 Variant: Current +Source: Drops from unique{Nightmare of Catarina} in normal{Ziggurat Map} Requires Level: 34, 73 Int {variant:3}AbyssJewelSocketUnique__17 {variant:1,2}LocalIncreaseSocketedMinionGemLevelUnique__3 @@ -996,6 +998,7 @@ LocalIncreasedArmourAndEvasionUniqueHelmetStrDex5 El'Abin's Visage Fencer Helm League: Crucible +Source: Drops from Crucible monsters StrengthUnique__23 DexterityUnique__28 LocalIncreasedArmourAndEvasionUnique__23 @@ -1005,6 +1008,7 @@ ItemCanHaveShieldWeaponTreeUnique1 The Trickster's Smile Visored Sallet League: Affliction +Source: Drops from Viridian Wildwood and Ritual monsters Requires Level 23, 28 Str, 28 Dex LocalIncreasedArmourAndEvasionUnique__21 AttackerTakesColdDamageUnique__1 @@ -1470,10 +1474,11 @@ ChaosResistanceIsZeroUnique__1 Corrupted ]],[[ Gorgon's Gaze +Source: Drops from unique{Talin, Faithbreaker} in normal{Pillars of Arun} Regicide Mask Requires Level 52, 58 Dex, 58 Int Implicits: 0 -Grants Level 20 Summon Petrification Statue Skill +PetrificationStatueUnique__1 LocalIncreasedEnergyShieldPercentUnique__15_ IncreasedLifeUnique__121 AttackAndCastSpeedUnique__2 @@ -1676,6 +1681,7 @@ LosePowerChargesOnBlockUnique__1 Faithguard Runic Helm League: Expedition +Source: Drops from Expedition monsters Variant: Pre 3.19.0 Variant: Current IntelligenceUniqueHelmetInt9 diff --git a/src/Export/Uniques/jewel.lua b/src/Export/Uniques/jewel.lua index 355cc73ac2..f94c63fad9 100644 --- a/src/Export/Uniques/jewel.lua +++ b/src/Export/Uniques/jewel.lua @@ -822,16 +822,19 @@ SoulTattooEffectUnique__1 [[ Amanamu's Gaze Ghastly Eye Jewel +Source: Drops from unique{Abyssal Liches} in normal{Abyssal Depths} AllAttributesUnique__23 MinionDamageOverTimeMultiplierPerMinionAbyssJewelUnique__1 ]],[[ Kurgal's Gaze Hypnotic Eye Jewel +Source: Drops from unique{Abyssal Liches} in normal{Abyssal Depths} IntelligenceUnique__28 ArcaneSurgeEffectPerCasterAbyssJewelUnique__1 ]],[[ Tecrod's Gaze Murderous Eye Jewel +Source: Drops from unique{Abyssal Liches} in normal{Abyssal Depths} Variant: Pre 3.21.0 Variant: Current Requires Level 40 @@ -843,6 +846,7 @@ StrengthUnique__21 ]],[[ Ulaman's Gaze Searching Eye Jewel +Source: Drops from unique{Abyssal Liches} in normal{Abyssal Depths} Requires Level 40 DexterityUnique__21_ ChainOffTerrainChancePerRangedAbyssJewelUnique__1__ diff --git a/src/Export/Uniques/quiver.lua b/src/Export/Uniques/quiver.lua index a01b63e9b0..1336a2d028 100644 --- a/src/Export/Uniques/quiver.lua +++ b/src/Export/Uniques/quiver.lua @@ -294,6 +294,7 @@ Broadhead Arrow Quiver Variant: Pre 3.17.0 Variant: Current LevelReq: 52 +Source: Labyrinth Implicits: 2 {variant:1}AddedPhysicalDamageImplicitQuiver11 {variant:2}IncreasedAttackSpeedImplicitQuiver10New diff --git a/src/Export/Uniques/shield.lua b/src/Export/Uniques/shield.lua index 00868a1be8..49c5655738 100644 --- a/src/Export/Uniques/shield.lua +++ b/src/Export/Uniques/shield.lua @@ -134,6 +134,7 @@ LocalFlatIncreasedEvasionAndEnergyShieldUnique__1 Redblade Banner Painted Tower Shield League: Warbands +Source: Drops from Redblade Mercenary monsters Variant: Pre 2.6.0 Variant: Pre 3.0.0 Variant: Pre 3.11.0 @@ -155,6 +156,7 @@ AdditionalBlockChanceUniqueShieldDex1 Svalinn Girded Tower Shield League: Settlers of Kalguur +Source: Drops from unique{The Black Knight} in a normal{Starfall Crater} Requires Level 51, 123 Str Implicits: 1 IncreasedLifeImplicitShield1 @@ -390,6 +392,7 @@ PhasingIfBlockedRecentlyUnique__1 Mutewind Pennant Enameled Buckler League: Warbands +Source: Drop from Mutewind Mercenary monsters Variant: Pre 2.6.0 Variant: Pre 3.0.0 Variant: Pre 3.11.0 @@ -534,6 +537,7 @@ SpectresGainArcaneSurgeWhenYouDoUnique__1_ Brinerot Flag Tarnished Spirit Shield League: Warbands +Source: Drops from Brinerot Warband monsters Variant: Pre 2.6.0 Variant: Pre 3.0.0 Variant: Pre 3.11.0 @@ -670,6 +674,7 @@ ShockOnMaxPowerChargesUnique__1 Manastorm {variant:1}Fossilised Spirit Shield {variant:2,3}Lacewood Spirit Shield +Source: Drops from unique{Nightmare of Uhtred} in normal{Citadel Map} Variant: Pre 3.19.0 Variant: Pre 3.24.0 Variant: Current @@ -745,6 +750,7 @@ MaximumLifeShieldInt1 ]],[[ The Scales of Justice Chiming Spirit Shield +Source: Labyrinth Implicits: 1 SpellDamageImplicitShield2 NoEnergyShieldUnique__1 @@ -773,6 +779,7 @@ ElementalWeaknessOnSpellBlockUniqueShieldInt4 The Flawed Refuge Maple Round Shield League: Affliction +Source: Drops from Viridian Wildwood and Ritual monsters Requires Level 39, 52 Str, 52 Dex Implicits: 1 BlockRecoveryImplicitShield3 @@ -823,6 +830,7 @@ Teak Round Shield Variant: Pre 3.16.0 Variant: Current League: Heist +Source: Reward from Mercenary duel Implicits: 1 BlockRecoveryImplicitShield3 LocalIncreaseSocketedSupportGemLevelUnique__1 @@ -882,6 +890,7 @@ AdditionalBlockChanceUniqueShieldStrDex3__ ]],[[ Vix Lunaris Cardinal Round Shield +Source: Drops from unique{Selenia, the Endless Night} in normal{The Twilight Temple} Implicits: 0 LocalIncreaseSocketedGemLevelUnique__11_ TriggeredColdAegisSkillUnique__1 @@ -938,6 +947,7 @@ WeaponElementalDamageUniqueShieldStrInt4 Broken Faith Archon Kite Shield League: Warbands +Source: Drops from Renegade Warband monsters Variant: Pre 2.6.0 Variant: Pre 3.11.0 Variant: Current @@ -970,6 +980,7 @@ KeystoneGlancingBlowsUnique__1___ ]],[[ Invictus Solaris Archon Kite Shield +Source: Drops from unique{Helial, the Day Unending} Implicits: 1 AllResistancesImplicitShield3 LocalIncreaseSocketedGemLevelUnique__1 @@ -1208,7 +1219,6 @@ PhysicalAttackDamageReducedUniqueShieldDexInt1 ]],[[ Leper's Alms Mirrored Spiked Shield -Source: Drops from unique{The Eradicator} Variant: Pre 3.5.0 Variant: Current Implicits: 1 diff --git a/src/Export/Uniques/staff.lua b/src/Export/Uniques/staff.lua index d5246cd6bc..dc415f5db3 100644 --- a/src/Export/Uniques/staff.lua +++ b/src/Export/Uniques/staff.lua @@ -776,6 +776,7 @@ Highborn Staff Variant: Pre 3.25.0 Variant: Current League: Crucible +Source: Drops from Crucible monsters Implicits: 2 {variant:1}StaffBlockPercentImplicitStaff1[18,18] {variant:2}StaffBlockPercentImplicitStaff2 diff --git a/src/Export/Uniques/sword.lua b/src/Export/Uniques/sword.lua index d2ab4d412f..b93692a2e9 100644 --- a/src/Export/Uniques/sword.lua +++ b/src/Export/Uniques/sword.lua @@ -491,6 +491,7 @@ LocalAddedPhysicalDamageUnique__7_ The Redblade Gladius League: Crucible +Source: Drops from Crucible monsters Implicits: 1 AccuracyPercentImplicitSword1 LocalIncreasedPhysicalDamagePercentUnique__46 diff --git a/src/Modules/AddImplicitPopup.lua b/src/Modules/AddImplicitPopup.lua new file mode 100644 index 0000000000..38fd99dd51 --- /dev/null +++ b/src/Modules/AddImplicitPopup.lua @@ -0,0 +1,412 @@ +local m_max = math.max +local t_insert = table.insert + +local M = {} + +local function buildModSortList() + local sortList = { { label = "Default", stat = nil } } + local sortStats = {} + for _, entry in ipairs(data.powerStatList) do + if entry.stat and not entry.ignoreForNodes then + t_insert(sortList, { label = entry.label, stat = entry.stat }) + sortStats[entry.stat] = entry + end + end + return sortList, sortStats +end + +-- Opens the custom Implicit popup +---@param itemsTab ItemsTab +---@param displayItem Item +function M.AddImplicitToDisplayItem(itemsTab, displayItem) + local controls = {} + local sourceList = {} + local modList = {} + local modGroups = {} + local sortList, sortStats = buildModSortList() + if not displayItem then return end + -- these closures should probably be refactored to be outside this function + -- at some point + local function setDefaultSortOrder() + for groupIndex, group in ipairs(modGroups) do + group.defaultSortOrder = groupIndex + group.sortValue = nil + end + for _, listMods in ipairs(modList) do + for index, listMod in ipairs(listMods) do + listMod.defaultSortOrder = index + listMod.sortValue = nil + listMod.sortValues = nil + end + end + end + ---Mutates modList to contain mods from the specified source + ---@param sourceId string @The crafting source id to build the list of mods for + local function buildMods(sourceId) + wipeTable(modList) + wipeTable(modGroups) + local groupIndexes = {} + if sourceId == "EXARCH" or sourceId == "EATER" then + for i, mod in pairs(displayItem.affixes) do + if displayItem:GetModSpawnWeight(mod) > 0 and sourceId:lower() == mod.type:lower() then + local modLabel = table.concat(mod, "/") + local group = mod.group:gsub("PinnaclePresence", ""):gsub("UniquePresence", "") + if not groupIndexes[group] then + t_insert(modList, {}) + t_insert(modGroups, { + label = modLabel, + mod = mod, + modListIndex = #modList, + defaultOrder = i, + }) + groupIndexes[group] = #modGroups + end + t_insert(modList[groupIndexes[group]], { + label = modLabel, + mod = mod, + affixType = mod.type, + type = sourceId:lower(), + defaultOrder = i, + }) + end + end + table.sort(modGroups, 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) + for i, _ in pairs(modList) do + table.sort(modList[i], function(a, b) + local modA = a.mod + local modB = b.mod + if modA.group ~= modB.group then + if modA.group:match("PinnaclePresence") then + return false + elseif modB.group:match("PinnaclePresence") then + return true + elseif modA.group:match("UniquePresence") then + return false + else + return true + end + end + for j = 1, m_max(#modA, #modB) do + if not modA[j] then + return true + elseif not modB[j] then + return false + elseif modA.statOrder[j] ~= modB.statOrder[j] then + return modA.statOrder[j] < modB.statOrder[j] + else + local modAVal = tonumber(a.defaultOrder:match("%d+$")) + local modBVal = tonumber(b.defaultOrder:match("%d+$")) + return modAVal < modBVal + end + end + return modA.level > modB.level + end) + end + for i, _ in pairs(modGroups) do + modGroups[i].label = modList[modGroups[i].modListIndex][1].label:gsub("%([%d%.]+%-[%d%.]+%)", "#"):gsub("[%d%.]+", "#") + end + elseif sourceId == "VESTIGIAL" then + for id, uniqueTitle in pairs(data.vestigialModMappings) do + local titleLower = uniqueTitle:lower() + local unique = main.uniqueDB.byTitle[titleLower] + if not unique + -- vestigial implicits can only end up on the same item type + or (unique.base.type ~= displayItem.type) + -- avoid adding the item's own mods as vestigial + or (displayItem.title:lower() == titleLower) then + goto vestigialContinue + end + local mod = copyTable(data.itemMods.Vestigial[id]) + local modLabel = colorCodes.VESTIGIAL .. table.concat(mod, "/") + t_insert(modList, { { + label = modLabel, + mod = mod, + type = "vestigial", + defaultOrder = id, + uniqueTitle = uniqueTitle, + } }) + t_insert(modGroups, { + label = modLabel, + mod = mod, + modListIndex = #modList, + defaultOrder = id, + uniqueTitle = uniqueTitle, + }) + groupIndexes[mod.group] = #modGroups + ::vestigialContinue:: + end + for i, _ in pairs(modList) do + table.sort(modList[i], function(a, b) + return a.defaultOrder < b.defaultOrder + end) + end + end + setDefaultSortOrder() + end + local titleLower = displayItem.title and displayItem.title:lower() + local displayDBUnique = main.uniqueDB.byTitle[titleLower] + if displayItem.rarity == "UNIQUE" and displayDBUnique + and data.vestigialUniqueBaseTypes[displayItem.base.type] + -- the source field should mean that the item comes from a specific + -- mechanic, which usually means it is not in the core drop pool + and (not displayDBUnique.source + -- this is the only exception to the above, as it occasionally drops + -- instead of other body armours in legion + or titleLower == "stasis prison") then + t_insert(sourceList, { label = "Vestigial", sourceId = "VESTIGIAL" }) + end + if (displayItem.rarity ~= "UNIQUE" and displayItem.rarity ~= "RELIC") and (displayItem.type == "Helmet" or displayItem.type == "Body Armour" or displayItem.type == "Gloves" or displayItem.type == "Boots") then + if displayItem.cleansing then + t_insert(sourceList, { label = "Searing Exarch", sourceId = "EXARCH" }) + end + if displayItem.tangle then + t_insert(sourceList, { label = "Eater of Worlds", sourceId = "EATER" }) + end + end + t_insert(sourceList, { label = "Custom", sourceId = "CUSTOM" }) + buildMods(sourceList[1].sourceId) + ---Applies a candidate listMod to the item, mirroring the mutation addModifier() + ---performs at click-time. Eldritch (exarch/eater) sources replace an existing + ---implicit of the same type when present; other sources append. + local function applyCandidateMod(item, listMod) + if listMod.type == "exarch" or listMod.type == "eater" then + local index + for i, implicitMod in ipairs(item.implicitModLines) do + if implicitMod[listMod.type] then + index = i + break + end + end + if index then + for i, line in ipairs(listMod.mod) do + item.implicitModLines[index + i - 1] = { line = line, modTags = listMod.mod.modTags, [listMod.type] = true } + end + return + end + elseif listMod.type == "vestigial" then + item.implicitModLines = {} + end + for _, line in ipairs(listMod.mod) do + local modLine = { line = line, modTags = listMod.mod.modTags } + if listMod.type then + modLine[listMod.type] = true + end + t_insert(item.implicitModLines, modLine) + end + 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", displayItem:BuildRaw()) + item.id = displayItem.id + applyCandidateMod(item, listMod) + item:BuildAndParseRaw() + local output = calcFunc({ repSlotName = slotName, repItem = item }, useFullDPS) + local value = data.powerStatList.GetFromOutput(output, sortStats[stat]) + listMod.sortValues[stat] = value + return value + end + local function applySort(stat, selectFirst) + if not controls.modSelect or not controls.modGroupSelect or not controls.modGroupSelect:IsShown() then + return + end + local selectedGroup = not selectFirst and modGroups[controls.modGroupSelect.selIndex] or nil + local selectedMod = not selectFirst and controls.modSelect.list and controls.modSelect.list[controls.modSelect.selIndex] or nil + if stat then + local slotName = displayItem:GetPrimarySlot() + local calcFunc = itemsTab.build.calcsTab:GetMiscCalculator() + local useFullDPS = stat == "FullDPS" + for _, listMods in ipairs(modList) do + for _, listMod in ipairs(listMods) do + listMod.sortValue = getSortValue(listMod, stat, calcFunc, slotName, useFullDPS) + end + table.sort(listMods, 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) + end + for _, group in ipairs(modGroups) do + local best + for _, listMod in ipairs(modList[group.modListIndex] or {}) do + if not best or listMod.sortValue > best then + best = listMod.sortValue + end + end + group.sortValue = best or 0 + end + table.sort(modGroups, 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 + for _, listMods in ipairs(modList) do + table.sort(listMods, function(a, b) + return (a.defaultSortOrder or 0) < (b.defaultSortOrder or 0) + end) + end + table.sort(modGroups, function(a, b) + return (a.defaultSortOrder or 0) < (b.defaultSortOrder or 0) + end) + end + controls.modGroupSelect:UpdateSearch() + if selectedGroup then + for index, group in ipairs(modGroups) do + if group == selectedGroup then + controls.modGroupSelect.selIndex = index + break + end + end + else + controls.modGroupSelect:SetSel(1, true) + end + controls.modSelect.list = modList[modGroups[controls.modGroupSelect.selIndex].modListIndex] + controls.modSelect:UpdateSearch() + if selectedMod then + for index, listMod in ipairs(controls.modSelect.list) do + if listMod == selectedMod then + controls.modSelect.selIndex = index + break + end + end + else + controls.modSelect:SetSel(1, true) + end + end + local function addModifier() + local item = new("Item", displayItem:BuildRaw()) + item.id = displayItem.id + local sourceId = sourceList[controls.source.selIndex].sourceId + if sourceId == "CUSTOM" then + if controls.custom.buf:match("%S") then + t_insert(item.implicitModLines, { line = controls.custom.buf, custom = true }) + end + else + applyCandidateMod(item, modList[modGroups[controls.modGroupSelect.selIndex].modListIndex][controls.modSelect.selIndex]) + end + item:BuildAndParseRaw() + return item + end + controls.sourceLabel = new("LabelControl", { "TOPRIGHT", nil, "TOPLEFT" }, { 95, 20, 0, 16 }, "^7Source:") + controls.source = new("DropDownControl", { "TOPLEFT", nil, "TOPLEFT" }, { 100, 20, 150, 18 }, sourceList, function(index, value) + if value.sourceId ~= "CUSTOM" then + controls.modSelectLabel.y = 70 + buildMods(value.sourceId) + controls.modGroupSelect:SetSel(1) + controls.modSelect.list = modList[modGroups[1].modListIndex] + controls.modSelect:SetSel(1) + if controls.sort then + applySort(controls.sort.list[controls.sort.selIndex].stat, true) + end + else + controls.modSelectLabel.y = 45 + end + end) + controls.source.enabled = #sourceList > 1 + controls.sortLabel = new("LabelControl", { "TOPRIGHT", nil, "TOPLEFT" }, { 350, 20, 0, 16 }, "^7Sort by:") + controls.sortLabel.shown = function() + return sourceList[controls.source.selIndex].sourceId ~= "CUSTOM" + end + controls.sort = new("DropDownControl", { "TOPLEFT", nil, "TOPLEFT" }, { 355, 20, 240, 18 }, sortList, function(index, value) + applySort(value.stat, true) + end) + controls.sort.shown = function() + return sourceList[controls.source.selIndex].sourceId ~= "CUSTOM" + end + controls.modGroupSelectLabel = new("LabelControl", { "TOPRIGHT", nil, "TOPLEFT" }, { 95, 45, 0, 16 }, function () + if controls.modSelect:IsShown() then + return "^7Type:" + else + return "^7Modifier:" + end + end) + controls.modGroupSelect = new("DropDownControl", { "TOPLEFT", nil, "TOPLEFT" }, { 100, 45, 600, 18 }, modGroups, function(index, value) + controls.modSelect.list = modList[value.modListIndex] + controls.modSelect:SetSel(1) + end) + controls.modGroupSelectLabel.shown = function() + if sourceList[controls.source.selIndex].sourceId == "CUSTOM" then + controls.modSelectLabel.y = 45 + end + return sourceList[controls.source.selIndex].sourceId ~= "CUSTOM" + end + controls.modGroupSelect.shown = function() + return sourceList[controls.source.selIndex].sourceId ~= "CUSTOM" + end + controls.modGroupSelect.tooltipFunc = function(tooltip, mode, index, value) + tooltip:Clear() + if mode ~= "OUT" and value then + for _, line in ipairs(value.mod) do + tooltip:AddLine(16, "^7" .. line) + end + if value.uniqueTitle then + tooltip:AddLine(16, "^7Source: " .. colorCodes.UNIQUE .. value.uniqueTitle .. "^7") + end + itemsTab:AddModComparisonTooltip(tooltip, value.mod) + end + end + controls.modSelectLabel = new("LabelControl", { "TOPRIGHT", nil, "TOPLEFT" }, { 95, 70, 0, 16 }, "^7Modifier:") + controls.modSelect = new("DropDownControl", { "TOPLEFT", nil, "TOPLEFT" }, { 100, 70, 600, 18 }, sourceList[controls.source.selIndex].sourceId ~= "CUSTOM" and modList[modGroups[1].modListIndex] or {}) + local modSelectHidden = { + CUSTOM = true, + -- vestigial implicits aren't grouped together, and the type selector + -- will act as the mod selector + VESTIGIAL = true + } + controls.modSelect.shown = function() + return not modSelectHidden[sourceList[controls.source.selIndex].sourceId] + end + controls.modSelectLabel.shown = controls.modSelect.shown + controls.modSelect.tooltipFunc = function(tooltip, mode, index, value) + tooltip:Clear() + if mode ~= "OUT" and value then + for _, line in ipairs(value.mod) do + tooltip:AddLine(16, "^7" .. line) + end + if value.uniqueTitle then + tooltip:AddLine(16, "^7Source: " .. colorCodes.UNIQUE .. value.uniqueTitle .. "^7") + end + itemsTab:AddModComparisonTooltip(tooltip, value.mod) + end + end + controls.custom = new("EditControl", { "TOPLEFT", nil, "TOPLEFT" }, { 100, 45, 440, 18 }) + controls.custom.shown = function() + return sourceList[controls.source.selIndex].sourceId == "CUSTOM" + end + controls.save = new("ButtonControl", { "BOTTOMRIGHT", nil, "BOTTOM" }, { -4, -8, 80, 20 }, "Add", function() + itemsTab:SetDisplayItem(addModifier()) + main:ClosePopup() + end) + controls.save.tooltipFunc = function(tooltip) + tooltip:Clear() + itemsTab:AddItemTooltip(tooltip, addModifier()) + end + controls.close = new("ButtonControl", { "BOTTOMLEFT", nil, "BOTTOM" }, { 4, -8, 80, 20 }, "Cancel", function() + main:ClosePopup() + end) + local popupHeight = 130 + if not controls.modSelect.shown() then + popupHeight = popupHeight - 20 + end + main:OpenPopup(710, popupHeight, "Add Implicit to Item", controls, "save", sourceList[controls.source.selIndex].sourceId == "CUSTOM" and "custom") +end + +return M diff --git a/src/Modules/Data.lua b/src/Modules/Data.lua index fd4fa2e137..e0b93fe92b 100644 --- a/src/Modules/Data.lua +++ b/src/Modules/Data.lua @@ -660,7 +660,13 @@ data.itemMods = { JewelCluster = LoadModule("Data/ModJewelCluster"), JewelCharm = LoadModule("Data/ModJewelCharm"), Foulborn = LoadModule("Data/ModFoulborn"), + Vestigial = {} } +for modId, mod in pairs(data.itemMods.ItemExclusive) do + if modId:find("^Divergent") then + data.itemMods.Vestigial[modId] = mod + end +end data.masterMods = LoadModule("Data/ModMaster") data.enchantments = { ["Helmet"] = LoadModule("Data/EnchantmentHelmet"), @@ -843,6 +849,23 @@ data.itemTagSpecialExclusionPattern = { }, } +-- Table of which slots can have vestigial uniques +data.vestigialUniqueBaseTypes = { + Helmet = true, + ["Body Armour"] = true, + Gloves = true, + Boots = true, + Shield = true, +} +-- map from mod ID to what item it *should* come from +---@type table +data.vestigialModMappings = LoadModule("Data/Vestigial") +for k, v in pairs(data.vestigialModMappings) do + data.vestigialModMappings[k] = v[1] + -- if launch.devMode then + -- assert(v[1], "Data/Vestigial is malformed") + -- end +end -- Cluster jewel data data.clusterJewels = LoadModule("Data/ClusterJewels") diff --git a/src/Modules/Main.lua b/src/Modules/Main.lua index 0e7b0d48c1..d390f6b503 100644 --- a/src/Modules/Main.lua +++ b/src/Modules/Main.lua @@ -149,7 +149,7 @@ function main:Init() self:ChangeUserPath(self.userPath, ignoreBuild) end - self.uniqueDB = { list = { }, loading = true } + self.uniqueDB = { list = { }, byTitle = {}, loading = true } self.rareDB = { list = { }, loading = true } local function loadItemDBs() @@ -158,6 +158,7 @@ function main:Init() local newItem = new("Item", raw, "UNIQUE", true) if newItem.base then self.uniqueDB.list[newItem.name] = newItem + self.uniqueDB.byTitle[newItem.title:lower()] = newItem elseif launch.devMode then ConPrintf("Unique DB unrecognised item of type '%s':\n%s", type, raw) end