Skip to content

Commit 04529fe

Browse files
committed
Fix global node allocation rules and add direct connection validation
- Add proper allocation/deallocation blocking for global nodes from weapon sets - Implement IsConnectedToWeaponSetNodes() method with path and adjacency checks - Add comprehensive tooltip warnings for blocked actions - Ensure global nodes always use allocMode=0 regardless of allocation context - Fix tooltip cache invalidation when switching between weapon sets
1 parent 923c6df commit 04529fe

2 files changed

Lines changed: 107 additions & 7 deletions

File tree

src/Classes/PassiveSpec.lua

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -703,12 +703,12 @@ function PassiveSpecClass:AllocNode(node, altPath)
703703
-- Allocate all nodes along the path
704704
if #node.intuitiveLeapLikesAffecting > 0 then
705705
node.alloc = true
706-
node.allocMode = node.ascendancyName and 0 or self.allocMode
706+
node.allocMode = (node.ascendancyName or node.type == "Keystone" or node.type == "Socket" or node.containJewelSocket) and 0 or self.allocMode
707707
self.allocNodes[node.id] = node
708708
else
709709
for _, pathNode in ipairs(altPath or node.path) do
710710
pathNode.alloc = true
711-
pathNode.allocMode = node.ascendancyName and 0 or self.allocMode
711+
pathNode.allocMode = (node.ascendancyName or pathNode.type == "Keystone" or pathNode.type == "Socket" or pathNode.containJewelSocket) and 0 or self.allocMode
712712
-- set path attribute nodes to latest chosen attribute or default to Strength if allocating before choosing an attribute
713713
if pathNode.isAttribute then
714714
self:SwitchAttributeNode(pathNode.id, self.attributeIndex or 1)

src/Classes/PassiveTreeView.lua

Lines changed: 105 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -264,10 +264,44 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents)
264264
end
265265

266266
local hotkeyPressed = IsKeyDown("1") or IsKeyDown("I") or IsKeyDown("2") or IsKeyDown("S") or IsKeyDown("3") or IsKeyDown("D")
267+
268+
-- Helper function to determine if global node allocation should be blocked
269+
local function shouldBlockGlobalNodeAllocation(node)
270+
local isGlobalNode = node.type == "Keystone" or node.type == "Socket" or node.containJewelSocket
271+
272+
if not isGlobalNode or node.alloc or not node.path then
273+
return false
274+
end
275+
276+
local weaponSetMode = spec.allocMode > 0
277+
local connectedToWeaponSetNodes = self:IsConnectedToWeaponSetNodes(node)
278+
279+
-- Only allow allocation from main tree AND node must not be connected to weapon set nodes
280+
local shouldBlock = weaponSetMode or connectedToWeaponSetNodes
281+
282+
return shouldBlock
283+
end
284+
285+
-- Helper function to determine if global node deallocation should be blocked
286+
local function shouldBlockGlobalNodeDeallocation(node)
287+
local isGlobalNode = node.type == "Keystone" or node.type == "Socket" or node.containJewelSocket
288+
289+
if not isGlobalNode or not node.alloc then
290+
return false
291+
end
292+
293+
-- Main-tree global nodes can only be deallocated from main tree
294+
-- Legacy weapon-set global nodes can be deallocated from any mode
295+
local shouldBlock = node.allocMode == 0 and spec.allocMode > 0
296+
297+
return shouldBlock
298+
end
299+
267300
if treeClick == "LEFT" then
268301
if hoverNode then
269302
-- User left-clicked on a node
270-
if hoverNode.alloc then
303+
if hoverNode.alloc and not shouldBlockGlobalNodeDeallocation(hoverNode) then
304+
-- Handle deallocation of allocated nodes
271305
if hoverNode.isAttribute then
272306
-- change to other attribute without needing to deallocate
273307
if hotkeyPressed then
@@ -283,9 +317,8 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents)
283317
end
284318
spec:AddUndoState()
285319
build.buildFlag = true
286-
elseif hoverNode.path then
287-
-- Node is unallocated and can be allocated, so allocate it
288-
-- attribute switching, unallocated to allocated
320+
elseif hoverNode.path and not shouldBlockGlobalNodeAllocation(hoverNode) then
321+
-- Handle allocation of unallocated nodes
289322
if hoverNode.isAttribute and not hotkeyPressed then
290323
build.treeTab:ModifyAttributePopup(hoverNode)
291324
else
@@ -301,6 +334,7 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents)
301334
end
302335
end
303336
elseif treeClick == "RIGHT" then
337+
-- User right-clicked on a node
304338
if hoverNode then
305339
if hoverNode.alloc and (hoverNode.type == "Socket" or hoverNode.containJewelSocket) then
306340
local slot = build.itemsTab.sockets[hoverNode.id]
@@ -834,7 +868,7 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents)
834868
-- Draw tooltip
835869
SetDrawLayer(nil, 100)
836870
local size = m_floor(node.size * scale)
837-
if self.tooltip:CheckForUpdate(node, self.showStatDifferences, self.tracePath, launch.devModeAlt, build.outputRevision) then
871+
if self.tooltip:CheckForUpdate(node, self.showStatDifferences, self.tracePath, launch.devModeAlt, build.outputRevision, build.spec.allocMode) then
838872
self:AddNodeTooltip(self.tooltip, node, build, incSmallPassiveSkillEffect)
839873
end
840874
self.tooltip.center = true
@@ -1138,6 +1172,9 @@ function PassiveTreeViewClass:AddNodeTooltip(tooltip, node, build, incSmallPassi
11381172
if socket ~= nil and socket:IsEnabled() then
11391173
tooltip:AddLine(14, colorCodes.TIP.."Tip: Right click this socket to go to the items page and choose the jewel for this socket.")
11401174
end
1175+
1176+
self:AddGlobalNodeWarningsToTooltip(tooltip, node, build)
1177+
11411178
tooltip:AddLine(14, colorCodes.TIP.."Tip: Hold Shift or Ctrl to hide this tooltip.")
11421179
return
11431180
end
@@ -1397,13 +1434,76 @@ function PassiveTreeViewClass:AddNodeTooltip(tooltip, node, build, incSmallPassi
13971434
tooltip:AddLine(14, "^7"..#node.depends .. " points gained from unallocating these nodes")
13981435
tooltip:AddLine(14, colorCodes.TIP)
13991436
end
1437+
1438+
self:AddGlobalNodeWarningsToTooltip(tooltip, node, build)
1439+
14001440
if node.type == "Socket" then
14011441
tooltip:AddLine(14, colorCodes.TIP.."Tip: Hold Shift or Ctrl to hide this tooltip.")
14021442
else
14031443
tooltip:AddLine(14, colorCodes.TIP.."Tip: Hold Ctrl to hide this tooltip.")
14041444
end
14051445
end
14061446

1447+
-- Helper function to check if a node is connected to weapon set nodes
1448+
function PassiveTreeViewClass:IsConnectedToWeaponSetNodes(node)
1449+
-- First check the path for weapon set nodes
1450+
if node.path and #node.path > 1 then
1451+
-- Check all nodes in the path (except the first element since it's the target node itself)
1452+
for i = 2, #node.path do
1453+
local pathNode = node.path[i]
1454+
if pathNode.alloc and pathNode.allocMode > 0 then
1455+
return true
1456+
end
1457+
end
1458+
end
1459+
1460+
-- And finally check for direct connections when path is short or empty
1461+
-- (This handles cases where global nodes are directly adjacent to weapon set nodes)
1462+
if node.linked then
1463+
for _, linkedNode in ipairs(node.linked) do
1464+
if linkedNode.alloc and linkedNode.allocMode and linkedNode.allocMode > 0 then
1465+
return true
1466+
end
1467+
end
1468+
end
1469+
1470+
return false
1471+
end
1472+
1473+
-- Helper function to add warnings in the tooltip for global nodes (keystones/jewel sockets)
1474+
function PassiveTreeViewClass:AddGlobalNodeWarningsToTooltip(tooltip, node, build)
1475+
local isGlobalNode = node.type == "Keystone" or node.type == "Socket" or node.containJewelSocket
1476+
1477+
if not isGlobalNode then
1478+
return -- No warning needed for non-global nodes
1479+
end
1480+
1481+
local nodeTypeText = node.type == "Keystone" and "keystones" or "jewel sockets"
1482+
local warningText = ""
1483+
local tipText = ""
1484+
1485+
if not node.alloc and node.path then
1486+
-- Unallocated global node - check allocation conditions
1487+
if build.spec.allocMode > 0 then
1488+
warningText = "Cannot allocate " .. nodeTypeText .. " while weapon set " .. build.spec.allocMode .. " is selected"
1489+
tipText = "Tip: Switch to main tree (Alt+scroll) to allocate " .. nodeTypeText
1490+
elseif self:IsConnectedToWeaponSetNodes(node) then
1491+
warningText = "Cannot allocate " .. nodeTypeText .. " - connected to weapon set nodes"
1492+
tipText = "Tip: Deallocate weapon set nodes in the connection path to allow allocation"
1493+
end
1494+
elseif node.alloc and node.allocMode == 0 and build.spec.allocMode > 0 then
1495+
-- Allocated main-tree global node viewed from weapon set
1496+
warningText = "Cannot deallocate global " .. nodeTypeText .. " from weapon set " .. build.spec.allocMode
1497+
tipText = "Tip: Switch to main tree (Alt+scroll) to deallocate " .. nodeTypeText
1498+
end
1499+
1500+
if warningText ~= "" then
1501+
tooltip:AddSeparator(14)
1502+
tooltip:AddLine(14, colorCodes.WARNING .. warningText)
1503+
tooltip:AddLine(14, colorCodes.TIP .. tipText)
1504+
end
1505+
end
1506+
14071507
function PassiveTreeViewClass:DrawAllocMode(allocMode, viewPort)
14081508
local rgbColor
14091509
if allocMode == 0 then

0 commit comments

Comments
 (0)