Skip to content

Commit 6d79e6c

Browse files
obokingLocalIdentity
andauthored
Fix inculsion of unique jewels when comparing passive trees (PathOfBuildingCommunity#1932)
* include jewel radiuses in comparison and show both the main build and the compared builds jewel when hovering * Match jewels by parse raw info instead of name Matching by name would fail on jewels that has different radius variants like Controller Metamorphosis --------- Co-authored-by: LocalIdentity <localidentity2@gmail.com>
1 parent c685ea5 commit 6d79e6c

1 file changed

Lines changed: 94 additions & 68 deletions

File tree

src/Classes/PassiveTreeView.lua

Lines changed: 94 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ local band = AND64 -- bit.band
1515
local b_rshift = bit.rshift
1616

1717
local gemTooltip = LoadModule("Classes/GemTooltip")
18+
local JEWEL_RADIUS_TINT_NEUTRAL = { 1, 1, 1, 0.7 }
19+
local JEWEL_RADIUS_TINT_PRIMARY_ONLY = { 1, 0, 0, 0.7 }
20+
local JEWEL_RADIUS_TINT_COMPARE_ONLY = { 0, 1, 0, 0.7 }
1821

1922
local PassiveTreeViewClass = newClass("PassiveTreeView", function(self)
2023
self.ring = NewImageHandle()
@@ -120,6 +123,13 @@ function PassiveTreeViewClass:GetJewelSocketOverlay(jewel, isExpansion)
120123
end
121124
end
122125

126+
local function compareJewelsEqual(a, b)
127+
if not a or not b then
128+
return a == b
129+
end
130+
return a:BuildRaw() == b:BuildRaw()
131+
end
132+
123133
-- Returns the draw color for a node when compare overlay is active.
124134
-- Handles diff coloring for allocated/unallocated, mastery changes, and jewel socket differences.
125135
function PassiveTreeViewClass:GetCompareNodeColor(node, compareNode, spec, build, nodeDefaultColor)
@@ -136,9 +146,7 @@ function PassiveTreeViewClass:GetCompareNodeColor(node, compareNode, spec, build
136146
local pJewelId = spec.jewels[node.id]
137147
local pJewel = pJewelId and build.itemsTab.items[pJewelId]
138148
local cJewel = self:GetCompareJewel(node.id)
139-
local pName = pJewel and pJewel.name or ""
140-
local cName = cJewel and cJewel.name or ""
141-
if pName ~= cName then
149+
if not compareJewelsEqual(pJewel, cJewel) then
142150
return 0, 0, 1
143151
end
144152
end
@@ -1125,8 +1133,8 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents)
11251133
self:AddNodeTooltip(self.tooltip, node, build, incSmallPassiveSkillEffect)
11261134
end
11271135
self.tooltip.center = true
1128-
local ttWidth, ttHeight = self.tooltip:GetDynamicSize()
1129-
local skillWidth, skillHeight = self.skillTooltip:GetDynamicSize()
1136+
local ttWidth, ttHeight = self.tooltip:GetDynamicSize(viewPort)
1137+
local skillWidth, skillHeight = self.skillTooltip:GetDynamicSize(viewPort)
11301138

11311139
local fatSkill = skillWidth > skillHeight*1.5
11321140

@@ -1183,76 +1191,84 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents)
11831191
end
11841192

11851193
-- Draw ring overlays for jewel sockets
1194+
local function drawJewelRadius(jewel, scrX, scrY, tint)
1195+
local radData = build.data.jewelRadius[jewel.jewelRadiusIndex]
1196+
local outerSize = radData.outer * data.gameConstants["PassiveTreeJewelDistanceMultiplier"] * scale
1197+
local innerSize = radData.inner * data.gameConstants["PassiveTreeJewelDistanceMultiplier"] * scale * 1.06
1198+
SetDrawColor(tint[1], tint[2], tint[3], tint[4])
1199+
if jewel.title == "From Nothing" then
1200+
-- From Nothing ring shows on the allocated Keystone
1201+
for keystoneName, _ in pairs(jewel.jewelData.fromNothingKeystones) do
1202+
local keystone = spec.tree.keystoneMap[keystoneName]
1203+
if keystone and keystone.x and keystone.y then
1204+
innerSize = 150 * scale
1205+
local keyX, keyY = treeToScreen(keystone.x, keystone.y)
1206+
self:DrawImageRotated(self.jewelShadedOuterRing, keyX, keyY, outerSize * 2, outerSize * 2, -0.7)
1207+
self:DrawImageRotated(self.jewelShadedOuterRingFlipped, keyX, keyY, outerSize * 2, outerSize * 2, 0.7)
1208+
self:DrawImageRotated(self.jewelShadedInnerRing, keyX, keyY, innerSize * 2, innerSize * 2, -0.7)
1209+
self:DrawImageRotated(self.jewelShadedInnerRingFlipped, keyX, keyY, innerSize * 2, innerSize * 2, 0.7)
1210+
end
1211+
end
1212+
elseif jewel.jewelData and jewel.jewelData.conqueredBy and jewel.jewelData.conqueredBy.conqueror and jewel.jewelData.conqueredBy.conqueror.type then
1213+
local conqueror = jewel.jewelData.conqueredBy.conqueror.type
1214+
if conqueror == "kalguur" then
1215+
conqueror = "kalguuran"
1216+
end
1217+
local circle1 = tree:GetAssetByName("art/textures/interface/2d/2dart/uiimages/ingame/passiveskillscreen".. conqueror .."jewelcircle1.dds")
1218+
local circle2 = tree:GetAssetByName("art/textures/interface/2d/2dart/uiimages/ingame/passiveskillscreen".. conqueror .."jewelcircle2.dds")
1219+
if conqueror == "abyss" then
1220+
circle1 = tree:GetAssetByName("art/textures/interface/2d/2dart/uiimages/ingame/".. conqueror .."/".. conqueror .."passiveskillscreenjewelcircle1.dds")
1221+
circle2 = circle1
1222+
end
1223+
self:DrawImageRotated(circle1.handle, scrX, scrY, outerSize * 2, outerSize * 2, -0.7, unpack(circle1))
1224+
self:DrawImageRotated(circle2.handle, scrX, scrY, outerSize * 2, outerSize * 2, 0.7, unpack(circle2))
1225+
else
1226+
self:DrawImageRotated(self.jewelShadedOuterRing, scrX, scrY, outerSize * 2, outerSize * 2, -0.7)
1227+
self:DrawImageRotated(self.jewelShadedOuterRingFlipped, scrX, scrY, outerSize * 2, outerSize * 2, 0.7)
1228+
self:DrawImageRotated(self.jewelShadedInnerRing, scrX, scrY, innerSize * 2, innerSize * 2, -0.7)
1229+
self:DrawImageRotated(self.jewelShadedInnerRingFlipped, scrX, scrY, innerSize * 2, innerSize * 2, 0.7)
1230+
end
1231+
end
11861232
SetDrawLayer(nil, 25)
11871233
for nodeId in pairs(tree.sockets) do
11881234
local node = spec.nodes[nodeId]
11891235
if node and node.name ~= "Charm Socket" and node.containJewelSocket ~= true and (not node.expansionJewel or node.expansionJewel.size == 2) then
11901236
local scrX, scrY = treeToScreen(node.x, node.y)
11911237
local socket, jewel = build.itemsTab:GetSocketAndJewelForNodeID(nodeId)
1238+
local compareNode = self.compareSpec and self.compareSpec.nodes[nodeId] or nil
1239+
local cJewel = self.compareSpec and self:GetCompareJewel(nodeId) or nil
11921240
if node == hoverNode then
1193-
local isThreadOfHope = jewel and jewel.jewelRadiusLabel == "Variable"
1194-
if isThreadOfHope then
1195-
for _, radData in ipairs(build.data.jewelRadius) do
1196-
local outerSize = radData.outer * data.gameConstants["PassiveTreeJewelDistanceMultiplier"] * scale
1197-
local innerSize = radData.inner * data.gameConstants["PassiveTreeJewelDistanceMultiplier"] * scale
1198-
-- Jewel in socket is Thread of Hope or similar, draw it's annulus
1241+
local effectiveJewel = jewel or cJewel
1242+
local isThreadOfHope = effectiveJewel and effectiveJewel.jewelRadiusLabel == "Variable"
1243+
for _, radData in ipairs(build.data.jewelRadius) do
1244+
local outerSize = radData.outer * data.gameConstants["PassiveTreeJewelDistanceMultiplier"] * scale
1245+
local innerSize = radData.inner * data.gameConstants["PassiveTreeJewelDistanceMultiplier"] * scale
1246+
if isThreadOfHope then
1247+
-- Thread of Hope-like: draw the annulus (only radii with a non-zero inner)
11991248
if innerSize ~= 0 then
12001249
SetDrawColor(radData.col)
12011250
DrawImage(self.ring, scrX - outerSize, scrY - outerSize, outerSize * 2, outerSize * 2)
12021251
DrawImage(self.ring, scrX - innerSize, scrY - innerSize, innerSize * 2, innerSize * 2)
12031252
end
1204-
end
1205-
else
1206-
for _, radData in ipairs(build.data.jewelRadius) do
1207-
local outerSize = radData.outer * data.gameConstants["PassiveTreeJewelDistanceMultiplier"] * scale
1208-
local innerSize = radData.inner * data.gameConstants["PassiveTreeJewelDistanceMultiplier"] * scale
1209-
-- Jewel in socket is not Thread of Hope or similar, draw normal jewel radius
1253+
else
1254+
-- Standard jewel: draw the full-disc radii (inner == 0)
12101255
if innerSize == 0 then
12111256
SetDrawColor(radData.col)
12121257
DrawImage(self.ring, scrX - outerSize, scrY - outerSize, outerSize * 2, outerSize * 2)
12131258
end
12141259
end
12151260
end
1216-
elseif node.alloc then
1217-
if jewel and jewel.jewelRadiusIndex then
1218-
-- Draw only the selected jewel radius
1219-
local radData = build.data.jewelRadius[jewel.jewelRadiusIndex]
1220-
local outerSize = radData.outer * data.gameConstants["PassiveTreeJewelDistanceMultiplier"] * scale
1221-
local innerSize = radData.inner * data.gameConstants["PassiveTreeJewelDistanceMultiplier"] * scale * 1.06
1222-
SetDrawColor(1,1,1,0.7)
1223-
if jewel.title == "From Nothing" then
1224-
-- From Nothing ring shows on the allocated Keystone
1225-
for keystoneName, _ in pairs(jewel.jewelData.fromNothingKeystones) do
1226-
local keystone = spec.tree.keystoneMap[keystoneName]
1227-
if keystone and keystone.x and keystone.y then
1228-
innerSize = 150 * scale
1229-
local keyX, keyY = treeToScreen(keystone.x, keystone.y)
1230-
self:DrawImageRotated(self.jewelShadedOuterRing, keyX, keyY, outerSize * 2, outerSize * 2, -0.7)
1231-
self:DrawImageRotated(self.jewelShadedOuterRingFlipped, keyX, keyY, outerSize * 2, outerSize * 2, 0.7)
1232-
self:DrawImageRotated(self.jewelShadedInnerRing, keyX, keyY, innerSize * 2, innerSize * 2, -0.7)
1233-
self:DrawImageRotated(self.jewelShadedInnerRingFlipped, keyX, keyY, innerSize * 2, innerSize * 2, 0.7)
1234-
end
1235-
end
1236-
elseif jewel.jewelData and jewel.jewelData.conqueredBy and jewel.jewelData.conqueredBy.conqueror and jewel.jewelData.conqueredBy.conqueror.type then
1237-
local conqueror = jewel.jewelData.conqueredBy.conqueror.type
1238-
if conqueror == "kalguur" then
1239-
conqueror = "kalguuran"
1240-
end
1241-
local circle1 = tree:GetAssetByName("art/textures/interface/2d/2dart/uiimages/ingame/passiveskillscreen".. conqueror .."jewelcircle1.dds")
1242-
local circle2 = tree:GetAssetByName("art/textures/interface/2d/2dart/uiimages/ingame/passiveskillscreen".. conqueror .."jewelcircle2.dds")
1243-
if conqueror == "abyss" then
1244-
circle1 = tree:GetAssetByName("art/textures/interface/2d/2dart/uiimages/ingame/".. conqueror .."/".. conqueror .."passiveskillscreenjewelcircle1.dds")
1245-
circle2 = circle1
1246-
end
1247-
self:DrawImageRotated(circle1.handle, scrX, scrY, outerSize * 2, outerSize * 2, -0.7, unpack(circle1))
1248-
self:DrawImageRotated(circle2.handle, scrX, scrY, outerSize * 2, outerSize * 2, 0.7, unpack(circle2))
1249-
else
1250-
self:DrawImageRotated(self.jewelShadedOuterRing, scrX, scrY, outerSize * 2, outerSize * 2, -0.7)
1251-
self:DrawImageRotated(self.jewelShadedOuterRingFlipped, scrX, scrY, outerSize * 2, outerSize * 2, 0.7)
1252-
1253-
self:DrawImageRotated(self.jewelShadedInnerRing, scrX, scrY, innerSize * 2, innerSize * 2, -0.7)
1254-
self:DrawImageRotated(self.jewelShadedInnerRingFlipped, scrX, scrY, innerSize * 2, innerSize * 2, 0.7)
1255-
end
1261+
end
1262+
if node.alloc or (compareNode and compareNode.alloc) then
1263+
local pHasRadius = jewel and jewel.jewelRadiusIndex
1264+
local cHasRadius = cJewel and cJewel.jewelRadiusIndex
1265+
local sameJewel = compareJewelsEqual(jewel, cJewel)
1266+
if pHasRadius then
1267+
local tint = (not self.compareSpec or sameJewel) and JEWEL_RADIUS_TINT_NEUTRAL or JEWEL_RADIUS_TINT_PRIMARY_ONLY
1268+
drawJewelRadius(jewel, scrX, scrY, tint)
1269+
end
1270+
if cHasRadius and not sameJewel then
1271+
drawJewelRadius(cJewel, scrX, scrY, JEWEL_RADIUS_TINT_COMPARE_ONLY)
12561272
end
12571273
end
12581274
end
@@ -1534,16 +1550,33 @@ function PassiveTreeViewClass:AddNodeTooltip(tooltip, node, build, incSmallPassi
15341550
local fontSizeBig = main.showFlavourText and 18 or 16
15351551
tooltip.center = true
15361552
tooltip.maxWidth = 800
1553+
-- Appends the compare spec's jewel tooltip if it has a jewel in this socket
1554+
local function addCompareJewelSection(socket, withLabel)
1555+
local cJewel = self.compareSpec and self:GetCompareJewel(node.id)
1556+
local cAllocated = self.compareSpec and self.compareSpec.allocNodes and self.compareSpec.allocNodes[node.id]
1557+
if not cJewel or not cAllocated then return false end
1558+
if withLabel then
1559+
tooltip:AddSeparator(14)
1560+
tooltip:AddLine(14, colorCodes.DEXTERITY .. "Compared build:")
1561+
end
1562+
self.compareSpec.build.itemsTab:AddItemTooltip(tooltip, cJewel, socket)
1563+
return true
1564+
end
1565+
15371566
-- Special case for sockets
15381567
if (node.type == "Socket" or node.containJewelSocket) and node.alloc then
15391568
local socket, jewel = build.itemsTab:GetSocketAndJewelForNodeID(node.id)
1569+
local cJewel = self.compareSpec and self:GetCompareJewel(node.id) or nil
15401570
if jewel then
15411571
build.itemsTab:AddItemTooltip(tooltip, jewel, socket)
1572+
if not compareJewelsEqual(jewel, cJewel) then
1573+
addCompareJewelSection(socket, true)
1574+
end
15421575
if node.distanceToClassStart and node.distanceToClassStart > 0 then
15431576
tooltip:AddSeparator(14)
15441577
tooltip:AddLine(16, string.format("^7Distance to start: %d", node.distanceToClassStart))
15451578
end
1546-
else
1579+
elseif not addCompareJewelSection(socket, false) then
15471580
self:AddNodeName(tooltip, node, build)
15481581
end
15491582
tooltip:AddSeparator(14)
@@ -1558,16 +1591,9 @@ function PassiveTreeViewClass:AddNodeTooltip(tooltip, node, build, incSmallPassi
15581591
end
15591592

15601593
-- For unallocated sockets, show compare build's jewel if it has one
1561-
if node.type == "Socket" and not node.alloc and self.compareSpec then
1562-
local cJewel = self:GetCompareJewel(node.id)
1563-
local cItemsTab = self.compareSpec.build and self.compareSpec.build.itemsTab
1564-
local cAllocated = self.compareSpec.allocNodes and self.compareSpec.allocNodes[node.id]
1565-
if cJewel and cAllocated then
1566-
-- Show the compare build's jewel tooltip instead of generic socket info
1567-
local socket = build.itemsTab:GetSocketAndJewelForNodeID(node.id)
1568-
cItemsTab:AddItemTooltip(tooltip, cJewel, socket)
1569-
tooltip:AddSeparator(14)
1570-
tooltip:AddLine(14, colorCodes.DEXTERITY .. "Jewel from compared build")
1594+
if node.type == "Socket" and not node.alloc then
1595+
local socket = build.itemsTab:GetSocketAndJewelForNodeID(node.id)
1596+
if addCompareJewelSection(socket, false) then
15711597
tooltip:AddLine(14, colorCodes.TIP.."Tip: Hold Shift or Ctrl to hide this tooltip.")
15721598
return
15731599
end

0 commit comments

Comments
 (0)