@@ -270,10 +270,44 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents)
270270 end
271271
272272 local hotkeyPressed = IsKeyDown (" 1" ) or IsKeyDown (" I" ) or IsKeyDown (" 2" ) or IsKeyDown (" S" ) or IsKeyDown (" 3" ) or IsKeyDown (" D" )
273+
274+ -- Helper function to determine if global node allocation should be blocked
275+ local function shouldBlockGlobalNodeAllocation (node )
276+ local isGlobalNode = node .type == " Keystone" or node .type == " Socket" or node .containJewelSocket
277+
278+ if not isGlobalNode or node .alloc or not node .path then
279+ return false
280+ end
281+
282+ local weaponSetMode = spec .allocMode > 0
283+ local connectedToWeaponSetNodes = self :IsConnectedToWeaponSetNodes (node )
284+
285+ -- Only allow allocation from main tree AND node must not be connected to weapon set nodes
286+ local shouldBlock = weaponSetMode or connectedToWeaponSetNodes
287+
288+ return shouldBlock
289+ end
290+
291+ -- Helper function to determine if global node deallocation should be blocked
292+ local function shouldBlockGlobalNodeDeallocation (node )
293+ local isGlobalNode = node .type == " Keystone" or node .type == " Socket" or node .containJewelSocket
294+
295+ if not isGlobalNode or not node .alloc then
296+ return false
297+ end
298+
299+ -- Main-tree global nodes can only be deallocated from main tree
300+ -- Legacy weapon-set global nodes can be deallocated from any mode
301+ local shouldBlock = node .allocMode == 0 and spec .allocMode > 0
302+
303+ return shouldBlock
304+ end
305+
273306 if treeClick == " LEFT" then
274307 if hoverNode then
275308 -- User left-clicked on a node
276- if hoverNode .alloc then
309+ if hoverNode .alloc and not shouldBlockGlobalNodeDeallocation (hoverNode ) then
310+ -- Handle deallocation of allocated nodes
277311 if hoverNode .isAttribute then
278312 -- change to other attribute without needing to deallocate
279313 if hotkeyPressed then
@@ -289,9 +323,8 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents)
289323 end
290324 spec :AddUndoState ()
291325 build .buildFlag = true
292- elseif hoverNode .path then
293- -- Node is unallocated and can be allocated, so allocate it
294- -- attribute switching, unallocated to allocated
326+ elseif hoverNode .path and not shouldBlockGlobalNodeAllocation (hoverNode ) then
327+ -- Handle allocation of unallocated nodes
295328 if hoverNode .isAttribute and not hotkeyPressed then
296329 build .treeTab :ModifyAttributePopup (hoverNode )
297330 else
@@ -307,6 +340,7 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents)
307340 end
308341 end
309342 elseif treeClick == " RIGHT" then
343+ -- User right-clicked on a node
310344 if hoverNode then
311345 if hoverNode .alloc and (hoverNode .type == " Socket" or hoverNode .containJewelSocket ) then
312346 local slot = build .itemsTab .sockets [hoverNode .id ]
@@ -840,7 +874,7 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents)
840874 -- Draw tooltip
841875 SetDrawLayer (nil , 100 )
842876 local size = m_floor (node .size * scale )
843- if self .tooltip :CheckForUpdate (node , self .showStatDifferences , self .tracePath , launch .devModeAlt , build .outputRevision ) then
877+ if self .tooltip :CheckForUpdate (node , self .showStatDifferences , self .tracePath , launch .devModeAlt , build .outputRevision , build . spec . allocMode ) then
844878 self :AddNodeTooltip (self .tooltip , node , build , incSmallPassiveSkillEffect )
845879 end
846880 self .tooltip .center = true
@@ -1144,6 +1178,9 @@ function PassiveTreeViewClass:AddNodeTooltip(tooltip, node, build, incSmallPassi
11441178 if socket ~= nil and socket :IsEnabled () then
11451179 tooltip :AddLine (14 , colorCodes .TIP .. " Tip: Right click this socket to go to the items page and choose the jewel for this socket." )
11461180 end
1181+
1182+ self :AddGlobalNodeWarningsToTooltip (tooltip , node , build )
1183+
11471184 tooltip :AddLine (14 , colorCodes .TIP .. " Tip: Hold Shift or Ctrl to hide this tooltip." )
11481185 return
11491186 end
@@ -1403,6 +1440,9 @@ function PassiveTreeViewClass:AddNodeTooltip(tooltip, node, build, incSmallPassi
14031440 tooltip :AddLine (14 , " ^7" ..# node .depends .. " points gained from unallocating these nodes" )
14041441 tooltip :AddLine (14 , colorCodes .TIP )
14051442 end
1443+
1444+ self :AddGlobalNodeWarningsToTooltip (tooltip , node , build )
1445+
14061446 if node .type == " Socket" then
14071447 tooltip :AddLine (14 , colorCodes .TIP .. " Tip: Hold Shift or Ctrl to hide this tooltip." )
14081448 else
@@ -1411,6 +1451,66 @@ function PassiveTreeViewClass:AddNodeTooltip(tooltip, node, build, incSmallPassi
14111451 end
14121452end
14131453
1454+ -- Helper function to check if a node is connected to weapon set nodes
1455+ function PassiveTreeViewClass :IsConnectedToWeaponSetNodes (node )
1456+ -- First check the path for weapon set nodes
1457+ if node .path and # node .path > 1 then
1458+ -- Check all nodes in the path (except the first element since it's the target node itself)
1459+ for i = 2 , # node .path do
1460+ local pathNode = node .path [i ]
1461+ if pathNode .alloc and pathNode .allocMode > 0 then
1462+ return true
1463+ end
1464+ end
1465+ end
1466+
1467+ -- And finally check for direct connections when path is short or empty
1468+ -- (This handles cases where global nodes are directly adjacent to weapon set nodes)
1469+ if node .linked then
1470+ for _ , linkedNode in ipairs (node .linked ) do
1471+ if linkedNode .alloc and linkedNode .allocMode and linkedNode .allocMode > 0 then
1472+ return true
1473+ end
1474+ end
1475+ end
1476+
1477+ return false
1478+ end
1479+
1480+ -- Helper function to add warnings in the tooltip for global nodes (keystones/jewel sockets)
1481+ function PassiveTreeViewClass :AddGlobalNodeWarningsToTooltip (tooltip , node , build )
1482+ local isGlobalNode = node .type == " Keystone" or node .type == " Socket" or node .containJewelSocket
1483+
1484+ if not isGlobalNode then
1485+ return -- No warning needed for non-global nodes
1486+ end
1487+
1488+ local nodeTypeText = node .type == " Keystone" and " keystones" or " jewel sockets"
1489+ local warningText = " "
1490+ local tipText = " "
1491+
1492+ if not node .alloc and node .path then
1493+ -- Unallocated global node - check allocation conditions
1494+ if build .spec .allocMode > 0 then
1495+ warningText = " Cannot allocate " .. nodeTypeText .. " while weapon set " .. build .spec .allocMode .. " is selected"
1496+ tipText = " Tip: Switch to main tree (Alt+scroll) to allocate " .. nodeTypeText
1497+ elseif self :IsConnectedToWeaponSetNodes (node ) then
1498+ warningText = " Cannot allocate " .. nodeTypeText .. " - connected to weapon set nodes"
1499+ tipText = " Tip: Deallocate weapon set nodes in the connection path to allow allocation"
1500+ end
1501+ elseif node .alloc and node .allocMode == 0 and build .spec .allocMode > 0 then
1502+ -- Allocated main-tree global node viewed from weapon set
1503+ warningText = " Cannot deallocate global " .. nodeTypeText .. " from weapon set " .. build .spec .allocMode
1504+ tipText = " Tip: Switch to main tree (Alt+scroll) to deallocate " .. nodeTypeText
1505+ end
1506+
1507+ if warningText ~= " " then
1508+ tooltip :AddSeparator (14 )
1509+ tooltip :AddLine (14 , colorCodes .WARNING .. warningText )
1510+ tooltip :AddLine (14 , colorCodes .TIP .. tipText )
1511+ end
1512+ end
1513+
14141514function PassiveTreeViewClass :DrawAllocMode (allocMode , viewPort )
14151515 local rgbColor
14161516 if allocMode == 0 then
0 commit comments