From b7b83405c3d6d69576b35d1b4f0799de6d3df9a6 Mon Sep 17 00:00:00 2001 From: Alexander Wilson Date: Wed, 22 Apr 2026 21:21:57 -0700 Subject: [PATCH 1/7] Add support for Baryanic Leylines (Disciple of Varashta) Parse "Non-Unique Time-Lost Jewels have X% increased radius" into a NonUniqueTimeLostJewelRadius modifier. When the build has the modifier, non-unique Time-Lost Jewels swap to a precomputed +40% radius tier for the in-radius passive computation and for the socket ring drawn on the tree. Regenerated ModCache.lua accordingly. --- spec/System/TestBaryanicLeylines_spec.lua | 33 +++++++++++++++++++ src/Classes/PassiveTreeView.lua | 40 +++++++++++++++++++++-- src/Data/ModCache.lua | 2 +- src/Modules/CalcSetup.lua | 13 ++++++-- src/Modules/Data.lua | 33 +++++++++++++++++++ src/Modules/ModParser.lua | 2 +- 6 files changed, 116 insertions(+), 7 deletions(-) create mode 100644 spec/System/TestBaryanicLeylines_spec.lua diff --git a/spec/System/TestBaryanicLeylines_spec.lua b/spec/System/TestBaryanicLeylines_spec.lua new file mode 100644 index 0000000000..58a66017ae --- /dev/null +++ b/spec/System/TestBaryanicLeylines_spec.lua @@ -0,0 +1,33 @@ +describe("BaryanicLeylines", function() + before_each(function() + newBuild() + end) + + teardown(function() + -- newBuild() takes care of resetting everything in setup() + end) + + it("parses Non-Unique Time-Lost Jewel radius modifier", function() + build.configTab.input.customMods = "\z + Non-Unique Time-Lost Jewels have 40% increased radius\n\z + " + build.configTab:BuildModList() + runCallback("OnFrame") + + assert.are.equals(40, build.calcsTab.mainEnv.modDB:Sum("INC", nil, "NonUniqueTimeLostJewelRadius")) + end) + + it("resolveTimeLostRadiusIndex returns upgraded tier at 40% and falls back otherwise", function() + -- Each base tier (Small..Very Large) maps to a +40% counterpart whose outer + -- radius is base * 1.4 (Small 1000 -> 1400). + assert.are.equals(1400, data.jewelRadius[data.resolveTimeLostRadiusIndex(1, 40)].outer) + assert.are.equals(1610, data.jewelRadius[data.resolveTimeLostRadiusIndex(2, 40)].outer) + assert.are.equals(1820, data.jewelRadius[data.resolveTimeLostRadiusIndex(3, 40)].outer) + assert.are.equals(2100, data.jewelRadius[data.resolveTimeLostRadiusIndex(4, 40)].outer) + + -- No upgrade tier exists below 40%, so the base index is returned unchanged. + assert.are.equals(1, data.resolveTimeLostRadiusIndex(1, 0)) + assert.are.equals(1, data.resolveTimeLostRadiusIndex(1, 39)) + assert.are.equals(1, data.resolveTimeLostRadiusIndex(1, nil)) + end) +end) diff --git a/src/Classes/PassiveTreeView.lua b/src/Classes/PassiveTreeView.lua index f6bd5fe56c..d5c3a39773 100644 --- a/src/Classes/PassiveTreeView.lua +++ b/src/Classes/PassiveTreeView.lua @@ -1270,7 +1270,15 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents) -- Draw ring overlays for jewel sockets local function drawJewelRadius(jewel, scrX, scrY, tint) - local radData = build.data.jewelRadius[jewel.jewelRadiusIndex] + local effectiveRadiusIndex = jewel.jewelRadiusIndex + -- (check for Time-Lost upgrades such as Baryanic Leylines) -- + local effectiveRadiusIndex = jewel.jewelRadiusIndex + if effectiveRadiusIndex and jewel.base and jewel.base.subType == "Radius" + and jewel.rarity ~= "UNIQUE" and jewel.rarity ~= "RELIC" + and build.calcsTab and build.calcsTab.mainEnv and build.calcsTab.mainEnv.modDB then + effectiveRadiusIndex = data.resolveTimeLostRadiusIndex(effectiveRadiusIndex, build.calcsTab.mainEnv.modDB:Sum("INC", nil, "NonUniqueTimeLostJewelRadius")) + end + local radData = build.data.jewelRadius[effectiveRadiusIndex] local outerSize = radData.outer * data.gameConstants["PassiveTreeJewelDistanceMultiplier"] * scale local innerSize = radData.inner * data.gameConstants["PassiveTreeJewelDistanceMultiplier"] * scale * 1.06 SetDrawColor(tint[1], tint[2], tint[3], tint[4]) @@ -1307,6 +1315,7 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents) self:DrawImageRotated(self.jewelShadedInnerRingFlipped, scrX, scrY, innerSize * 2, innerSize * 2, 0.7) end end + SetDrawLayer(nil, 25) for nodeId in pairs(tree.sockets) do local node = spec.nodes[nodeId] @@ -1887,11 +1896,38 @@ function PassiveTreeViewClass:AddNodeTooltip(tooltip, node, build, incSmallPassi -- we only want to run the timeLost function on a node that can could be in a jewel socket radius of up to Large -- essentially trying to avoid calling ProcessStats for a Normal/Notable node that can't possibly be affected -- loops potentially every socket (24) until itemsTab is loaded or a jewel socket is hovered, then it will only loop the allocated sockets + -- Radius indexes to probe: Very Large (4) plus any Time-Lost upgrade tiers (e.g. Baryanic Leylines' + -- "Very Large +40%" at 16) so nodes only reachable via an increased radius still show jewel mods. + local radiusProbeIndexes = { 4 } + if data.nonUniqueTimeLostJewelRadiusUpgrades then + for _, map in pairs(data.nonUniqueTimeLostJewelRadiusUpgrades) do + for _, upgradedIndex in pairs(map) do + local seen = false + for _, existing in ipairs(radiusProbeIndexes) do + if existing == upgradedIndex then + seen = true + break + end + end + if not seen then + t_insert(radiusProbeIndexes, upgradedIndex) + end + end + end + end local function isNodeInARadius(node) local isInRadius = false for id, socket in pairs(build.itemsTab.sockets) do if build.itemsTab.activeSocketList and socket.inactive == false or socket.inactive == nil then - isInRadius = isInRadius or (build.spec.nodes[id] and build.spec.nodes[id].nodesInRadius and build.spec.nodes[id].nodesInRadius[4][node.id] ~= nil) + local socketNode = build.spec.nodes[id] + if socketNode and socketNode.nodesInRadius then + for _, radiusIndex in ipairs(radiusProbeIndexes) do + if socketNode.nodesInRadius[radiusIndex] and socketNode.nodesInRadius[radiusIndex][node.id] ~= nil then + isInRadius = true + break + end + end + end if isInRadius then break end end end diff --git a/src/Data/ModCache.lua b/src/Data/ModCache.lua index 50484e61c0..685d0287dc 100644 --- a/src/Data/ModCache.lua +++ b/src/Data/ModCache.lua @@ -8828,7 +8828,7 @@ c["Non-Keystone Passive Skills in Medium Radius of allocated Keystone Passive Sk c["Non-Minion Skills have 50% less Reservation Efficiency"]={{[1]={[1]={neg=true,skillType=6,type="SkillType"},flags=0,keywordFlags=0,name="ReservationEfficiency",type="MORE",value=-50}},nil} c["Non-Unique Life Flasks apply their Effects constantly"]={nil,"Non-Unique Life Flasks apply their Effects constantly "} c["Non-Unique Life Flasks apply their Effects constantly Recovery from Life Flasks cannot be Instant"]={nil,"Non-Unique Life Flasks apply their Effects constantly Recovery from Life Flasks cannot be Instant "} -c["Non-Unique Time-Lost Jewels have 40% increased radius"]={nil,"Non-Unique Time-Lost Jewels have 40% increased radius "} +c["Non-Unique Time-Lost Jewels have 40% increased radius"]={{[1]={flags=0,keywordFlags=0,name="NonUniqueTimeLostJewelRadius",type="INC",value=40}},nil} c["Non-instant Recovery from Mana Flasks also applies to Life"]={nil,"Non-instant Recovery from Mana Flasks also applies to Life "} c["Nova Spells have 20% less Area of Effect"]={{[1]={[1]={skillType=85,type="SkillType"},flags=0,keywordFlags=0,name="AreaOfEffect",type="MORE",value=-20}},nil} c["Oasis"]={{[1]={flags=0,keywordFlags=0,name="Keystone",type="LIST",value="Oasis"},[2]={flags=0,keywordFlags=0,name="Condition:HaveOasis",type="FLAG",value=true}},nil} diff --git a/src/Modules/CalcSetup.lua b/src/Modules/CalcSetup.lua index 95b78f6bc9..17f33d96e0 100644 --- a/src/Modules/CalcSetup.lua +++ b/src/Modules/CalcSetup.lua @@ -1291,23 +1291,30 @@ function calcs.initEnv(build, mode, override, specEnv) end end if item and not (node and node.sinister) and ( item.jewelRadiusIndex or (override and override.extraJewelFuncs and #override.extraJewelFuncs > 0) ) then + -- Non-unique Time-Lost Jewels use an upgraded radius tier when the build + -- has e.g. Baryanic Leylines allocated. + local effectiveRadiusIndex = item.jewelRadiusIndex + if effectiveRadiusIndex and item.base and item.base.subType == "Radius" + and item.rarity ~= "UNIQUE" and item.rarity ~= "RELIC" then + effectiveRadiusIndex = data.resolveTimeLostRadiusIndex(effectiveRadiusIndex, nodesModsList:Sum("INC", nil, "NonUniqueTimeLostJewelRadius")) + end -- Jewel has a radius, add it to the list local funcList = (item.jewelData and item.jewelData.funcList) or { { type = "Self", func = defaultRadiusJewelFunc } } for _, func in ipairs(funcList) do t_insert(env.radiusJewelList, { - nodes = node.nodesInRadius and node.nodesInRadius[item.jewelRadiusIndex] or { }, + nodes = node.nodesInRadius and node.nodesInRadius[effectiveRadiusIndex] or { }, func = func.func, type = func.type, item = item, nodeId = slot.nodeId, - attributes = node.attributesInRadius and node.attributesInRadius[item.jewelRadiusIndex] or { }, + attributes = node.attributesInRadius and node.attributesInRadius[effectiveRadiusIndex] or { }, data = { }, -- store this to compare with cache later jewelHash = getHashFromString(item.modSource..item.raw) }) if func.type ~= "Self" and node.nodesInRadius then -- Add nearby unallocated nodes to the extra node list - for nodeId, node in pairs(node.nodesInRadius[item.jewelRadiusIndex]) do + for nodeId, node in pairs(node.nodesInRadius[effectiveRadiusIndex]) do if not env.allocNodes[nodeId] then env.extraRadiusNodeList[nodeId] = env.spec.nodes[nodeId] end diff --git a/src/Modules/Data.lua b/src/Modules/Data.lua index d94d05a320..20ca60c7b5 100644 --- a/src/Modules/Data.lua +++ b/src/Modules/Data.lua @@ -680,9 +680,42 @@ data.jewelRadii = { { inner = 1400, outer = 1700, col = "^xFFCC00", label = "Variable" }, { inner = 1650, outer = 1950, col = "^xFF6600", label = "Variable" }, { inner = 1800, outer = 2100, col = "^x0099FF", label = "Variable" }, + + -- Baryanic Leylines (Disciple of Varashta): non-unique Time-Lost radius +40% + { inner = 0, outer = 1400, col = "^xBB6600", label = "Small" }, + { inner = 0, outer = 1610, col = "^x66FFCC", label = "Medium" }, + { inner = 0, outer = 1820, col = "^x2222CC", label = "Large" }, + { inner = 0, outer = 2100, col = "^xC100FF", label = "Very Large" }, } } +-- Maps a base Time-Lost Jewel radius index to the upgraded index granted by +-- "Non-Unique Time-Lost Jewels have X% increased radius" effects. Keyed by +-- percentage so additional tiers can be added later. +data.nonUniqueTimeLostJewelRadiusUpgrades = { + [40] = { [1] = 13, [2] = 14, [3] = 15, [4] = 16 }, +} + +-- Returns the radius index that should be used for a non-unique Time-Lost Jewel +-- given the base index and the total "% increased radius" value in effect. +-- Picks the largest supported tier at or below upgradePct; returns baseIndex +-- unchanged when no tier applies. +function data.resolveTimeLostRadiusIndex(baseIndex, upgradePct) + if not baseIndex or not upgradePct or upgradePct <= 0 then + return baseIndex + end + local bestPct + for pct, map in pairs(data.nonUniqueTimeLostJewelRadiusUpgrades) do + if pct <= upgradePct and map[baseIndex] and (not bestPct or pct > bestPct) then + bestPct = pct + end + end + if bestPct then + return data.nonUniqueTimeLostJewelRadiusUpgrades[bestPct][baseIndex] + end + return baseIndex +end + data.jewelRadius = data.setJewelRadiiGlobally(latestTreeVersion) -- Stat descriptions diff --git a/src/Modules/ModParser.lua b/src/Modules/ModParser.lua index ff8a00f8fa..195830a676 100644 --- a/src/Modules/ModParser.lua +++ b/src/Modules/ModParser.lua @@ -5616,7 +5616,7 @@ local specialModList = { ["only affects passives in massive ring"] = { mod("JewelData", "LIST", { key = "radiusIndex", value = 12 }) }, ["upgrades radius to medium"] = { mod("JewelData", "LIST", { key = "timeLostJewelRadiusOverride", value = 2 })}, ["upgrades radius to large"] = { mod("JewelData", "LIST", { key = "timeLostJewelRadiusOverride", value = 3 })}, - ["upgrades radius to very large"] = { mod("JewelData", "LIST", { key = "timeLostJewelRadiusOverride", value = 4 })}, + ["non%-unique time%-lost jewels have (%d+)%% increased radius"] = function(num) return { mod("NonUniqueTimeLostJewelRadius", "INC", num) } end, ["primordial"] = { mod("Multiplier:PrimordialItem", "BASE", 1) }, ["spectres have a base duration of (%d+) seconds"] = { mod("SkillData", "LIST", { key = "duration", value = 6 }, { type = "SkillName", skillName = "Raise Spectre", includeTransfigured = true }) }, ["flasks applied to you have (%d+)%% increased effect"] = function(num) return { mod("FlaskEffect", "INC", num, { type = "ActorCondition", actor = "player"}) } end, From 554c8535e2ee90070a13890fbcf47ac2aef85703 Mon Sep 17 00:00:00 2001 From: Alexander Wilson Date: Fri, 8 May 2026 14:18:57 -0700 Subject: [PATCH 2/7] Polish Time-Lost jewel radius tooltip and probe set - Append "(+X% from tree)" to the jewel tooltip Radius line when a build has NonUniqueTimeLostJewelRadius active. - Skip Time-Lost upgrade radius indexes in the AddNodeTooltip probe set unless the build actually has access to them, avoiding unnecessary ProcessStats calls per hover. --- src/Classes/ItemsTab.lua | 11 ++++++++++- src/Classes/PassiveTreeView.lua | 28 ++++++++++++++++------------ 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/src/Classes/ItemsTab.lua b/src/Classes/ItemsTab.lua index 3b3a9bd60b..b718890c83 100644 --- a/src/Classes/ItemsTab.lua +++ b/src/Classes/ItemsTab.lua @@ -3965,7 +3965,16 @@ function ItemsTabClass:AddItemTooltip(tooltip, item, slot, dbMode, maxWidth) tooltip:AddLine(fontSizeBig, "^x7F7F7FRequires Class "..(self.build.spec.curClassName == item.classRestriction and colorCodes.POSITIVE or colorCodes.NEGATIVE)..item.classRestriction, "FONTIN SC") end if item.jewelRadiusLabel then - tooltip:AddLine(fontSizeBig, "^x7F7F7FRadius: ^7"..item.jewelRadiusLabel, "FONTIN SC") + local radiusLine = "^x7F7F7FRadius: ^7"..item.jewelRadiusLabel + if item.base and item.base.subType == "Radius" + and item.rarity ~= "UNIQUE" and item.rarity ~= "RELIC" + and self.build.calcsTab and self.build.calcsTab.mainEnv and self.build.calcsTab.mainEnv.modDB then + local upgradePct = self.build.calcsTab.mainEnv.modDB:Sum("INC", nil, "NonUniqueTimeLostJewelRadius") + if upgradePct > 0 then + radiusLine = radiusLine .. " ^x7F7F7F(+"..upgradePct.."% from tree)" + end + end + tooltip:AddLine(fontSizeBig, radiusLine, "FONTIN SC") end if item.jewelRadiusData and slot and item.jewelRadiusData[slot.nodeId] then local radiusData = item.jewelRadiusData[slot.nodeId] diff --git a/src/Classes/PassiveTreeView.lua b/src/Classes/PassiveTreeView.lua index d5c3a39773..8ceb274fb2 100644 --- a/src/Classes/PassiveTreeView.lua +++ b/src/Classes/PassiveTreeView.lua @@ -1897,20 +1897,24 @@ function PassiveTreeViewClass:AddNodeTooltip(tooltip, node, build, incSmallPassi -- essentially trying to avoid calling ProcessStats for a Normal/Notable node that can't possibly be affected -- loops potentially every socket (24) until itemsTab is loaded or a jewel socket is hovered, then it will only loop the allocated sockets -- Radius indexes to probe: Very Large (4) plus any Time-Lost upgrade tiers (e.g. Baryanic Leylines' - -- "Very Large +40%" at 16) so nodes only reachable via an increased radius still show jewel mods. + -- "Very Large +40%" at 16) that the current build actually has access to. local radiusProbeIndexes = { 4 } - if data.nonUniqueTimeLostJewelRadiusUpgrades then - for _, map in pairs(data.nonUniqueTimeLostJewelRadiusUpgrades) do - for _, upgradedIndex in pairs(map) do - local seen = false - for _, existing in ipairs(radiusProbeIndexes) do - if existing == upgradedIndex then - seen = true - break + local timeLostRadiusUpgrade = build.calcsTab and build.calcsTab.mainEnv and build.calcsTab.mainEnv.modDB + and build.calcsTab.mainEnv.modDB:Sum("INC", nil, "NonUniqueTimeLostJewelRadius") or 0 + if timeLostRadiusUpgrade > 0 and data.nonUniqueTimeLostJewelRadiusUpgrades then + for pct, map in pairs(data.nonUniqueTimeLostJewelRadiusUpgrades) do + if pct <= timeLostRadiusUpgrade then + for _, upgradedIndex in pairs(map) do + local seen = false + for _, existing in ipairs(radiusProbeIndexes) do + if existing == upgradedIndex then + seen = true + break + end + end + if not seen then + t_insert(radiusProbeIndexes, upgradedIndex) end - end - if not seen then - t_insert(radiusProbeIndexes, upgradedIndex) end end end From 63dd1af94cac959ee0f91748bcd87a7ad2a8e4ae Mon Sep 17 00:00:00 2001 From: Brendan Stassel Date: Fri, 19 Jun 2026 22:16:11 -0400 Subject: [PATCH 3/7] Fix missing ModParser line for Very-large radius jewels --- src/Modules/ModParser.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Modules/ModParser.lua b/src/Modules/ModParser.lua index 195830a676..06ae2ae787 100644 --- a/src/Modules/ModParser.lua +++ b/src/Modules/ModParser.lua @@ -5616,6 +5616,7 @@ local specialModList = { ["only affects passives in massive ring"] = { mod("JewelData", "LIST", { key = "radiusIndex", value = 12 }) }, ["upgrades radius to medium"] = { mod("JewelData", "LIST", { key = "timeLostJewelRadiusOverride", value = 2 })}, ["upgrades radius to large"] = { mod("JewelData", "LIST", { key = "timeLostJewelRadiusOverride", value = 3 })}, + ["upgrades radius to very large"] = { mod("JewelData", "LIST", { key = "timeLostJewelRadiusOverride", value = 4 })}, ["non%-unique time%-lost jewels have (%d+)%% increased radius"] = function(num) return { mod("NonUniqueTimeLostJewelRadius", "INC", num) } end, ["primordial"] = { mod("Multiplier:PrimordialItem", "BASE", 1) }, ["spectres have a base duration of (%d+) seconds"] = { mod("SkillData", "LIST", { key = "duration", value = 6 }, { type = "SkillName", skillName = "Raise Spectre", includeTransfigured = true }) }, From 5ea432daa1808097e68df9f83ae18d2d9006f514 Mon Sep 17 00:00:00 2001 From: Alex Wilson Date: Sat, 20 Jun 2026 19:43:58 -0700 Subject: [PATCH 4/7] Rebase onto current dev (0.5.3): regen ModCache, drop duplicate local - Regenerated the NonUniqueTimeLostJewelRadius entry in ModCache.lua against 0.5.3 data so it no longer carries the stale Offering SkillType enum from the pre-0.5.3 base. - Removed a duplicate `local effectiveRadiusIndex` declaration (and stray double space) in PassiveTreeView drawJewelRadius. --- src/Classes/PassiveTreeView.lua | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Classes/PassiveTreeView.lua b/src/Classes/PassiveTreeView.lua index 8ceb274fb2..c1a88f6d51 100644 --- a/src/Classes/PassiveTreeView.lua +++ b/src/Classes/PassiveTreeView.lua @@ -1270,10 +1270,9 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents) -- Draw ring overlays for jewel sockets local function drawJewelRadius(jewel, scrX, scrY, tint) - local effectiveRadiusIndex = jewel.jewelRadiusIndex -- (check for Time-Lost upgrades such as Baryanic Leylines) -- local effectiveRadiusIndex = jewel.jewelRadiusIndex - if effectiveRadiusIndex and jewel.base and jewel.base.subType == "Radius" + if effectiveRadiusIndex and jewel.base and jewel.base.subType == "Radius" and jewel.rarity ~= "UNIQUE" and jewel.rarity ~= "RELIC" and build.calcsTab and build.calcsTab.mainEnv and build.calcsTab.mainEnv.modDB then effectiveRadiusIndex = data.resolveTimeLostRadiusIndex(effectiveRadiusIndex, build.calcsTab.mainEnv.modDB:Sum("INC", nil, "NonUniqueTimeLostJewelRadius")) From 5f366ead14fc2ee4236502e72a808af7ca932e83 Mon Sep 17 00:00:00 2001 From: Jacul Date: Sat, 26 Sep 2026 22:21:53 -0400 Subject: [PATCH 5/7] Draw each compared tree's jewel ring with its own Time-Lost radius Rings were sized from the primary build's calculation, so comparing a tree that allocates Baryanic Leylines against one that doesn't showed a single ring at the same radius for both. Track the radius increase per spec and treat identical jewels with different effective radii as different rings. --- src/Classes/PassiveSpec.lua | 14 ++++++++++++++ src/Classes/PassiveTreeView.lua | 20 +++++++++----------- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/Classes/PassiveSpec.lua b/src/Classes/PassiveSpec.lua index 154ddf2bbe..4783fdc5b8 100644 --- a/src/Classes/PassiveSpec.lua +++ b/src/Classes/PassiveSpec.lua @@ -1471,6 +1471,18 @@ function PassiveSpecClass:BuildNodePathsToRootNodes(roots) ::continueBuildPath:: end end + +-- Returns the radius index a jewel uses in this spec, accounting for Time-Lost +-- radius upgrades from allocated passives (e.g. Baryanic Leylines) +function PassiveSpecClass:GetJewelRadiusIndex(item) + local radiusIndex = item.jewelRadiusIndex + if radiusIndex and item.base and item.base.subType == "Radius" + and item.rarity ~= "UNIQUE" and item.rarity ~= "RELIC" then + return data.resolveTimeLostRadiusIndex(radiusIndex, self.timeLostJewelRadiusIncrease) + end + return radiusIndex +end + -- Rebuilds dependencies and paths for all nodes function PassiveSpecClass:BuildAllDependsAndPaths() -- This table will keep track of which nodes have been visited during each path-finding attempt @@ -1493,6 +1505,7 @@ function PassiveSpecClass:BuildAllDependsAndPaths() end end wipeTable(intuitiveLeapLikeNodes) + self.timeLostJewelRadiusIncrease = 0 for id, node in pairs(self.allocNodes) do if node.ascendancyName then -- avoid processing potentially replaceable nodes self.tree:ProcessStats(node) @@ -1501,6 +1514,7 @@ function PassiveSpecClass:BuildAllDependsAndPaths() t_insert(intuitiveLeapLikeNodes, radius) end end + self.timeLostJewelRadiusIncrease = self.timeLostJewelRadiusIncrease + node.modList:Sum("INC", nil, "NonUniqueTimeLostJewelRadius") processed[id] = true end end diff --git a/src/Classes/PassiveTreeView.lua b/src/Classes/PassiveTreeView.lua index c1a88f6d51..b7611fdf84 100644 --- a/src/Classes/PassiveTreeView.lua +++ b/src/Classes/PassiveTreeView.lua @@ -1269,15 +1269,9 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents) end -- Draw ring overlays for jewel sockets - local function drawJewelRadius(jewel, scrX, scrY, tint) - -- (check for Time-Lost upgrades such as Baryanic Leylines) -- - local effectiveRadiusIndex = jewel.jewelRadiusIndex - if effectiveRadiusIndex and jewel.base and jewel.base.subType == "Radius" - and jewel.rarity ~= "UNIQUE" and jewel.rarity ~= "RELIC" - and build.calcsTab and build.calcsTab.mainEnv and build.calcsTab.mainEnv.modDB then - effectiveRadiusIndex = data.resolveTimeLostRadiusIndex(effectiveRadiusIndex, build.calcsTab.mainEnv.modDB:Sum("INC", nil, "NonUniqueTimeLostJewelRadius")) - end - local radData = build.data.jewelRadius[effectiveRadiusIndex] + local function drawJewelRadius(jewel, scrX, scrY, tint, jewelSpec) + -- Use the spec the ring belongs to, so compared trees can differ (e.g. Baryanic Leylines) + local radData = build.data.jewelRadius[jewelSpec:GetJewelRadiusIndex(jewel)] local outerSize = radData.outer * data.gameConstants["PassiveTreeJewelDistanceMultiplier"] * scale local innerSize = radData.inner * data.gameConstants["PassiveTreeJewelDistanceMultiplier"] * scale * 1.06 SetDrawColor(tint[1], tint[2], tint[3], tint[4]) @@ -1349,12 +1343,16 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents) local pHasRadius = jewel and jewel.jewelRadiusIndex local cHasRadius = cJewel and cJewel.jewelRadiusIndex local sameJewel = compareJewelsEqual(jewel, cJewel) + if sameJewel and pHasRadius and cHasRadius then + -- Identical jewels can have different radii when only one spec has a Time-Lost radius upgrade + sameJewel = spec:GetJewelRadiusIndex(jewel) == self.compareSpec:GetJewelRadiusIndex(cJewel) + end if pHasRadius then local tint = (not self.compareSpec or sameJewel) and JEWEL_RADIUS_TINT_NEUTRAL or JEWEL_RADIUS_TINT_PRIMARY_ONLY - drawJewelRadius(jewel, scrX, scrY, tint) + drawJewelRadius(jewel, scrX, scrY, tint, spec) end if cHasRadius and not sameJewel then - drawJewelRadius(cJewel, scrX, scrY, JEWEL_RADIUS_TINT_COMPARE_ONLY) + drawJewelRadius(cJewel, scrX, scrY, JEWEL_RADIUS_TINT_COMPARE_ONLY, self.compareSpec) end end end From ebc5e5a60615fca6b8e07ea3e777f6f4ad0420eb Mon Sep 17 00:00:00 2001 From: Jacul Date: Sat, 26 Sep 2026 22:22:13 -0400 Subject: [PATCH 6/7] Show only the radii that apply when previewing a jewel socket Hovering a jewel socket drew the four upgraded Time-Lost radii alongside the base ones, even without Baryanic Leylines. Mark the upgraded radii and show them in place of the base ones only when the socketed jewel is upgraded, for both the preview rings and the highlighted nodes. They also get their own labels so a jewel's "Radius: Small" can only match the base radius. --- src/Classes/PassiveTreeView.lua | 9 +++++++-- src/Modules/Data.lua | 9 +++++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/Classes/PassiveTreeView.lua b/src/Classes/PassiveTreeView.lua index b7611fdf84..2365315cf8 100644 --- a/src/Classes/PassiveTreeView.lua +++ b/src/Classes/PassiveTreeView.lua @@ -1146,8 +1146,10 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents) end else -- Jewel in socket is not Thread of Hope or similar + -- Use the increased radii instead of the base ones if the socketed jewel is upgraded + local isIncreased = jewel and spec:GetJewelRadiusIndex(jewel) ~= jewel.jewelRadiusIndex for index, data in ipairs(build.data.jewelRadius) do - if hoverNode.nodesInRadius[index][node.id] then + if (not data.increased) == (not isIncreased) and hoverNode.nodesInRadius[index][node.id] then -- Draw normal jewel radii if data.inner == 0 then SetDrawColor(data.col) @@ -1320,6 +1322,9 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents) if node == hoverNode then local effectiveJewel = jewel or cJewel local isThreadOfHope = effectiveJewel and effectiveJewel.jewelRadiusLabel == "Variable" + -- Preview the increased radii instead of the base ones if the socketed jewel is upgraded + local jewelSpec = jewel and spec or self.compareSpec + local isIncreased = effectiveJewel and jewelSpec and jewelSpec:GetJewelRadiusIndex(effectiveJewel) ~= effectiveJewel.jewelRadiusIndex for _, radData in ipairs(build.data.jewelRadius) do local outerSize = radData.outer * data.gameConstants["PassiveTreeJewelDistanceMultiplier"] * scale local innerSize = radData.inner * data.gameConstants["PassiveTreeJewelDistanceMultiplier"] * scale @@ -1332,7 +1337,7 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents) end else -- Standard jewel: draw the full-disc radii (inner == 0) - if innerSize == 0 then + if innerSize == 0 and (not radData.increased) == (not isIncreased) then SetDrawColor(radData.col) DrawImage(self.ring, scrX - outerSize, scrY - outerSize, outerSize * 2, outerSize * 2) end diff --git a/src/Modules/Data.lua b/src/Modules/Data.lua index 20ca60c7b5..ba67b329eb 100644 --- a/src/Modules/Data.lua +++ b/src/Modules/Data.lua @@ -682,10 +682,11 @@ data.jewelRadii = { { inner = 1800, outer = 2100, col = "^x0099FF", label = "Variable" }, -- Baryanic Leylines (Disciple of Varashta): non-unique Time-Lost radius +40% - { inner = 0, outer = 1400, col = "^xBB6600", label = "Small" }, - { inner = 0, outer = 1610, col = "^x66FFCC", label = "Medium" }, - { inner = 0, outer = 1820, col = "^x2222CC", label = "Large" }, - { inner = 0, outer = 2100, col = "^xC100FF", label = "Very Large" }, + -- `increased` keeps these out of the radius previews unless the jewel is upgraded + { inner = 0, outer = 1400, col = "^xBB6600", label = "Increased Small", increased = true }, + { inner = 0, outer = 1610, col = "^x66FFCC", label = "Increased Medium", increased = true }, + { inner = 0, outer = 1820, col = "^x2222CC", label = "Increased Large", increased = true }, + { inner = 0, outer = 2100, col = "^xC100FF", label = "Increased Very Large", increased = true }, } } From c6193e9ecc8603fe3d22fa87eb45888c0714c137 Mon Sep 17 00:00:00 2001 From: Jacul Date: Sat, 26 Sep 2026 22:22:21 -0400 Subject: [PATCH 7/7] Fit the jewel's radius ring inside the Items tab socket preview The socket preview uses a fixed zoom that clips larger rings, such as a Time-Lost jewel upgraded by Baryanic Leylines. Zoom out just enough for the socketed jewel's effective radius to fit. --- src/Modules/ItemSlotHelper.lua | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Modules/ItemSlotHelper.lua b/src/Modules/ItemSlotHelper.lua index 9d4502ae36..ed7bd03ca4 100644 --- a/src/Modules/ItemSlotHelper.lua +++ b/src/Modules/ItemSlotHelper.lua @@ -19,6 +19,15 @@ function M.DrawViewer(itemsTab, nodeId, x, y, w, h) local viewer = itemsTab.socketViewer viewer.zoom = 17 + -- Zoom out if needed so the socketed jewel's radius ring (including Time-Lost radius + -- upgrades such as Baryanic Leylines) fits inside the preview: the ring's diameter + -- must fit min(w,h), with ~5% margin so the ring stroke isn't clipped + local _, jewel = itemsTab:GetSocketAndJewelForNodeID(nodeId) + if jewel and jewel.jewelRadiusIndex then + local radData = data.jewelRadius[itemsTab.build.spec:GetJewelRadiusIndex(jewel)] + local ringSize = radData.outer * data.gameConstants["PassiveTreeJewelDistanceMultiplier"] + viewer.zoom = math.min(viewer.zoom, itemsTab.build.spec.tree.size / (2 * ringSize) / 1.05) + end local viewPortSize = math.min(w, h) local scale = itemsTab.build.spec.tree.size / (viewPortSize * viewer.zoom)