@@ -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
14051445end
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+
14071507function PassiveTreeViewClass :DrawAllocMode (allocMode , viewPort )
14081508 local rgbColor
14091509 if allocMode == 0 then
0 commit comments