Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
6556bbf
Amor Mandragora
Blitz54 Jan 11, 2026
6c1475a
Hysseg's Claw
Blitz54 Jan 11, 2026
89d4f56
The Flesh Poppet
Blitz54 Jan 11, 2026
bfe6ea1
Fury of the King
Blitz54 Jan 11, 2026
d56cc57
Atziri's Contempt
Blitz54 Jan 11, 2026
cc57f14
Atziri's Rule
Blitz54 Jan 11, 2026
7072f31
Drillneck
Blitz54 Jan 11, 2026
a772b8c
Atziri's Step
Blitz54 Jan 11, 2026
e22ba4b
Atziri's Splendour
Blitz54 Jan 11, 2026
b8e04e5
Lavianga's Spirits
Blitz54 Jan 11, 2026
a9eacec
Flesh Crucible
Blitz54 Jan 11, 2026
6c397a9
Atziri's Rule Mod
Blitz54 Jan 11, 2026
e07fa09
Hysseg's Claw Mod
Blitz54 Jan 11, 2026
1d21ddb
Amor Mandragora Hinder Mod
Blitz54 Jan 11, 2026
c905fed
Atziri Splendour soul core only, and export soulcore type
Blitz54 Jan 12, 2026
03e4638
Bringer of Rain augment as if a body armour
Blitz54 Jan 12, 2026
5b29a75
Darkness Enthroned rune support
Blitz54 Jan 12, 2026
49882e7
Merge branch 'dev' into uniques-0.4
Blitz54 Jan 13, 2026
1be7bd0
Rerun exporter
Blitz54 Jan 13, 2026
093501c
Atiziri's Splendour "as if also" adds lines from both body armour and…
Blitz54 Jan 13, 2026
157d39f
Fix error when backspacing rune number
Blitz54 Jan 13, 2026
e6e05bd
temp
Blitz54 Jan 13, 2026
e114122
Merge branch 'dev' into uniques-0.4
Jan 13, 2026
d9fc1ac
Merge branch 'uniques-0.4' of https://github.com/Blitz54/PathOfBuildi…
Blitz54 Jan 13, 2026
5265d66
Fix soul core scaling, and add copy logic for darkness enthroned
Blitz54 Jan 13, 2026
710298e
Some progress towards scaling runes
Blitz54 Jan 14, 2026
53088e8
Merge branch 'PathOfBuildingCommunity:dev' into uniques-0.4
Blitz54 Jan 14, 2026
eb09d7d
Bonded mods scale now
Blitz54 Jan 15, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 61 additions & 8 deletions src/Classes/Item.lua
Original file line number Diff line number Diff line change
Expand Up @@ -825,7 +825,7 @@ function ItemClass:ParseRaw(raw, rarity, highQuality)
end
-- this will need more advanced logic for jewel sockets in items to work properly but could just be removed as items like this was only introduced during development.
if self.base then
if self.base.weapon or self.base.armour or self.base.tags.wand or self.base.tags.staff or self.base.tags.sceptre then
if self.base.weapon or self.base.armour or self.base.tags.wand or self.base.tags.staff or self.base.tags.sceptre or self.title == "Darkness Enthroned" then
local shouldFixRunesOnItem = #self.runes == 0

-- Form a key value table with the following format
Expand All @@ -835,6 +835,25 @@ function ItemClass:ParseRaw(raw, rarity, highQuality)
local statGroupedRunes = { }
local broadItemType = self.base.weapon and "weapon" or (self.base.tags.wand or self.base.tags.staff) and "caster" or "armour" -- minor optimisation
local specificItemType = self.base.type:lower()
local additionalType
local augmentOverride = {
BodyArmour = "body armour",
Helmet = "helmet",
Shield = "shield",
Boots = "boots",
Gloves = "gloves",
}
for flag, slot in pairs(augmentOverride) do
if self["augmentsAs" .. flag] then
specificItemType = slot
break
end
end
for flag, slot in pairs(augmentOverride) do -- Atziri's Splendour
if self["augmentsAlsoAs" .. flag] then
additionalType = slot
end
end
for runeName, runeMods in pairs(data.itemMods.Runes) do
local addModToGroupedRunes = function (modLine)
local runeValue = 1
Expand All @@ -848,7 +867,7 @@ function ItemClass:ParseRaw(raw, rarity, highQuality)
t_insert(statGroupedRunes[runeStrippedModLine], { runeName, runeValue });
end
for slotType, slotMod in pairs(runeMods) do
if slotType == broadItemType or slotType == specificItemType then
if slotType == broadItemType or slotType == specificItemType or slotType == additionalType then
for _, mod in ipairs(slotMod) do
addModToGroupedRunes(mod)
end
Expand Down Expand Up @@ -915,7 +934,7 @@ function ItemClass:ParseRaw(raw, rarity, highQuality)
return true
end
end

-- Incrementing is done first as to reach the target you will need to add a count as such it should be more efficient.
-- Try increasing (if it doesn't overshoot or exceed maximum number of remaining runes)
if sum + tonumber(v) <= target + 1e-9 and count < remainingRunes then
Expand Down Expand Up @@ -974,7 +993,7 @@ function ItemClass:ParseRaw(raw, rarity, highQuality)
remainingRunes = remainingRunes - numRunes
-- this code should probably be refactored to based off stored self.runes rather than the recomputed amounts off the runeModLines this
-- is too avoid having to run the relatively expensive recomputation every time the item is parsed even if we know the runes on the item already.
modLine.soulCore = groupedRunes[1][1]:match("Soul Core") ~= nil
modLine.soulCore = groupedRunes[1][1]:match("Soul Core") or groupedRunes[1][1]:match("Thesis") -- Should match by type
modLine.runeCount = numRunes

if shouldFixRunesOnItem then
Expand Down Expand Up @@ -1313,7 +1332,7 @@ end
-- Rebuild rune modifiers using the item's runes
function ItemClass:UpdateRunes()
wipeTable(self.runeModLines)
local getModRunesForTypes = function(runeName, baseType, specificType)
local getModRunesForTypes = function(runeName, baseType, specificType, additionalType)
local rune = data.itemMods.Runes[runeName]
local gatheredRuneMods = { }
if rune then
Expand All @@ -1322,11 +1341,16 @@ function ItemClass:UpdateRunes()
t_insert(gatheredRuneMods, rune[baseType])
-- end
end
if rune[specificType] then
if rune[specificType] then
-- for _, mod in pairs(rune[specificType]) do
t_insert(gatheredRuneMods, rune[specificType])
-- end
end
if rune[additionalType] then
-- for _, mod in pairs(rune[additionalType]) do
t_insert(gatheredRuneMods, rune[additionalType])
-- end
end
end
return gatheredRuneMods
end
Expand All @@ -1335,9 +1359,29 @@ function ItemClass:UpdateRunes()
for i = 1, self.itemSocketCount do
local name = self.runes[i]
if name and name ~= "None" then
local baseType = self.base.weapon and "weapon" or self.base.armour and "armour" or (self.base.tags.wand or self.base.tags.staff) and "caster"
local baseType = self.base.weapon and "weapon" or self.base.armour and "armour" or (self.base.tags.wand or self.base.tags.staff) and "caster" or self.title == "Darkness Enthroned" and "armour"
local specificType = self.base.type:lower()
local gatheredMods = getModRunesForTypes(name, baseType, specificType)
local additionalType
local augmentOverride = {
BodyArmour = "body armour",
Helmet = "helmet",
Shield = "shield",
Boots = "boots",
Gloves = "gloves",
}
for flag, slot in pairs(augmentOverride) do
if self["augmentsAs" .. flag] then
specificType = slot
break
end
end
for flag, slot in pairs(augmentOverride) do -- Atziri's Splendour
if self["augmentsAlsoAs" .. flag] then
additionalType = slot
break
end
end
local gatheredMods = getModRunesForTypes(name, baseType, specificType, additionalType)
for _, mod in ipairs(gatheredMods) do
for i, modLine in ipairs(mod) do
local order = mod.statOrder[i]
Expand Down Expand Up @@ -1871,6 +1915,14 @@ function ItemClass:BuildModList()
baseList:NewMod("ArmourData", "LIST", { key = "EnergyShield", value = 0 })
self.requirements.int = 0
end
for _, slot in ipairs({ "Shield", "BodyArmour", "Helmet", "Boots", "Gloves" }) do
if calcLocal(baseList, "AugmentsAsIf"..slot, "FLAG", 0) then
self["augmentsAs"..slot] = true
end
if calcLocal(baseList, "AugmentsAsIfAlso"..slot, "FLAG", 0) then
self["augmentsAlsoAs"..slot] = true
end
end
if calcLocal(baseList, "NoAttributeRequirements", "FLAG", 0) then
self.requirements.strMod = 0
self.requirements.dexMod = 0
Expand Down Expand Up @@ -1913,4 +1965,5 @@ function ItemClass:BuildModList()
self.modList = self:BuildModListForSlotNum(baseList)
end
self.socketedSoulCoreEffectModifier = calcLocal(baseList, "SocketedSoulCoreEffect", "INC", 0) / 100
self.socketedAugmentEffectModifier = calcLocal(baseList, "SocketedAugmentEffect", "INC", 0) / 100
end
44 changes: 37 additions & 7 deletions src/Classes/ItemsTab.lua
Original file line number Diff line number Diff line change
Expand Up @@ -376,13 +376,17 @@ holding Shift will put it in the second.]])

-- Section: Sockets and Links
self.controls.displayItemSectionSockets = new("Control", {"TOPLEFT",self.controls.displayItemSectionVariant,"BOTTOMLEFT"}, {0, 0, 0, function()
return self.displayItem and (self.displayItem.base.weapon or self.displayItem.base.armour or self.displayItem.base.tags.wand or self.displayItem.base.tags.staff or self.displayItem.base.tags.sceptre) and 28 or 0
return self.displayItem and (self.displayItem.base.weapon or self.displayItem.base.armour or self.displayItem.base.tags.wand or self.displayItem.base.tags.staff or self.displayItem.base.tags.sceptre or self.displayItem.title == "Darkness Enthroned") and 28 or 0
end})
self.controls.displayItemSocketRune = new("LabelControl", {"TOPLEFT",self.controls.displayItemSectionSockets,"TOPLEFT"}, {0, 0, 36, 20}, "^x7F7F7FS")
self.controls.displayItemSocketRune.shown = function()
return self.displayItem.base.weapon or self.displayItem.base.armour or self.displayItem.base.tags.wand or self.displayItem.base.tags.staff or self.displayItem.base.tags.sceptre
return self.displayItem.base.weapon or self.displayItem.base.armour or self.displayItem.base.tags.wand or self.displayItem.base.tags.staff or self.displayItem.base.tags.sceptre or self.displayItem.title == "Darkness Enthroned"
end
self.controls.displayItemSocketRuneEdit = new("EditControl", {"LEFT",self.controls.displayItemSocketRune,"RIGHT"}, {2, 0, 50, 20}, nil, nil, "%D", 1, function(buf)
if tonumber(buf) == nil then
self.controls.displayItemSocketRuneEdit:SetText(0)
return
end
if tonumber(buf) > 6 then
self.controls.displayItemSocketRuneEdit:SetText(6)
return
Expand Down Expand Up @@ -511,7 +515,7 @@ holding Shift will put it in the second.]])

-- Section: Rune Selection
self.controls.displayItemSectionRune = new("Control", {"TOPLEFT",self.controls.displayItemSectionClusterJewel,"BOTTOMLEFT"}, {0, 0, 0, function()
if not self.displayItem or self.displayItem.itemSocketCount == 0 or not (self.displayItem.base.weapon or self.displayItem.base.armour or self.displayItem.base.tags.wand or self.displayItem.base.tags.staff or self.displayItem.base.tags.sceptre) then
if not self.displayItem or self.displayItem.itemSocketCount == 0 or not (self.displayItem.base.weapon or self.displayItem.base.armour or self.displayItem.base.tags.wand or self.displayItem.base.tags.staff or self.displayItem.base.tags.sceptre or self.displayItem.title == "Darkness Enthroned") then
return 0
end
local h = 6
Expand Down Expand Up @@ -550,7 +554,7 @@ holding Shift will put it in the second.]])
end
end
drop.shown = function()
return self.displayItem and i <= self.displayItem.itemSocketCount and (self.displayItem.base.weapon or self.displayItem.base.armour or self.displayItem.base.tags.wand or self.displayItem.base.tags.staff or self.displayItem.base.tags.sceptre)
return self.displayItem and i <= self.displayItem.itemSocketCount and (self.displayItem.base.weapon or self.displayItem.base.armour or self.displayItem.base.tags.wand or self.displayItem.base.tags.staff or self.displayItem.base.tags.sceptre or self.displayItem.title == "Darkness Enthroned")
end

self.controls["displayItemRune"..i] = drop
Expand Down Expand Up @@ -1631,7 +1635,7 @@ local runeModLines = { { name = "None", label = "None", lines = { "None" }, orde
for name, runeMods in pairs(data.itemMods.Runes) do
-- Some runes have multiple mod lines; insert each as separate entry
for slotType, runeMod in pairs(runeMods) do
t_insert(runeModLines, { name = name, label = runeMod[1], lines = runeMod, req = runeMod.rank[1], order = runeMod.statOrder[1], slot = slotType, group = #runeMod })
t_insert(runeModLines, { name = name, label = runeMod[1], lines = runeMod, req = runeMod.rank[1], order = runeMod.statOrder[1], slot = slotType, type = runeMod.type, group = #runeMod })
end
end
table.sort(runeModLines, function(a, b)
Expand All @@ -1648,15 +1652,41 @@ function ItemsTabClass:UpdateRuneControls()
local item = self.displayItem
-- Build rune selection for item
local runes = { }
local alsoSlots = {}
for _, flagName in ipairs({ "BodyArmour", "Shield", "Helmet", "Boots", "Gloves" }) do
if item["augmentsAlsoAs" .. flagName] then
alsoSlots[flagName:gsub("([a-z])([A-Z])", "%1 %2"):lower()] = true
end
end

for _, rune in pairs(runeModLines) do
local augmentFlags = { "BodyArmour", "Shield", "Helmet", "Boots", "Gloves" }
for _, flagName in ipairs(augmentFlags) do
if item["augmentsAs" .. flagName] then
-- Convert BodyArmour -> "body armour"
local runeSlot = flagName:gsub("([a-z])([A-Z])", "%1 %2"):lower()
if rune.slot == "None" or rune.slot == "armour" or rune.slot == runeSlot then
table.insert(runes, rune)
end
goto continue
end
end
if rune.slot == "None" or -- Needed "None" for Items Tab
item.base.type:lower() == rune.slot or
item.base.type == rune.slot or
item.base.weapon and rune.slot == "weapon" or
item.base.armour and rune.slot == "armour" or
(item.base.tags.wand or item.base.tags.staff) and rune.slot == "caster" then
table.insert(runes, rune)
(item.base.tags.wand or item.base.tags.staff) and rune.slot == "caster" or
alsoSlots[rune.slot] then
if item.title == "Atziri's Splendour" then
if rune.slot == "None" or rune.type == "SoulCore" then
table.insert(runes, rune)
end
else
table.insert(runes, rune)
end
end
::continue::
end

for i = 1, item.itemSocketCount do
Expand Down
Loading