Skip to content

Commit b563ee0

Browse files
committed
Prevent weapon set A node allocation in weapon set B path
1 parent 6443edd commit b563ee0

1 file changed

Lines changed: 109 additions & 43 deletions

File tree

src/Classes/PassiveTreeView.lua

Lines changed: 109 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -271,42 +271,59 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents)
271271

272272
local hotkeyPressed = IsKeyDown("1") or IsKeyDown("I") or IsKeyDown("2") or IsKeyDown("S") or IsKeyDown("3") or IsKeyDown("D")
273273

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
274+
-- Helper function to check if a path crosses between different weapon sets
275+
local function pathCrossesWeaponSets(node)
276+
return self:PathCrossesWeaponSets(node, spec)
277+
end
277278

278-
if not isGlobalNode or node.alloc or not node.path then
279+
-- Unified helper function to determine if node allocation should be blocked
280+
local function shouldBlockNodeAllocation(node)
281+
if not node.path or node.alloc then
279282
return false
280283
end
281284

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)
293285
local isGlobalNode = node.type == "Keystone" or node.type == "Socket" or node.containJewelSocket
286+
local isAttributeNode = node.isAttribute
287+
288+
-- Fold early - handle global nodes first
289+
if isGlobalNode then
290+
local weaponSetMode = spec.allocMode > 0
291+
local connectedToWeaponSetNodes = self:IsConnectedToWeaponSetNodes(node)
292+
return weaponSetMode or connectedToWeaponSetNodes
293+
elseif isAttributeNode then
294+
-- Attribute nodes follow same rules as regular nodes for weapon set crossing
295+
return pathCrossesWeaponSets(node)
296+
else
297+
-- Regular nodes - check for weapon set path crossing
298+
return pathCrossesWeaponSets(node)
299+
end
300+
end
294301

295-
if not isGlobalNode or not node.alloc then
302+
-- Unified helper function to determine if node deallocation should be blocked
303+
local function shouldBlockNodeDeallocation(node)
304+
if not node.alloc then
296305
return false
297306
end
298307

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
308+
local isGlobalNode = node.type == "Keystone" or node.type == "Socket" or node.containJewelSocket
309+
local isAttributeNode = node.isAttribute
310+
311+
-- Fold early - handle global nodes first
312+
if isGlobalNode then
313+
return node.allocMode == 0 and spec.allocMode > 0
314+
elseif isAttributeNode then
315+
-- Attribute nodes follow same rules as regular nodes
316+
return node.allocMode ~= spec.allocMode and node.allocMode ~= 0
317+
else
318+
-- Regular nodes
319+
return node.allocMode ~= spec.allocMode and node.allocMode ~= 0
320+
end
304321
end
305322

306323
if treeClick == "LEFT" then
307324
if hoverNode then
308325
-- User left-clicked on a node
309-
if hoverNode.alloc and not shouldBlockGlobalNodeDeallocation(hoverNode) then
326+
if hoverNode.alloc and not shouldBlockNodeDeallocation(hoverNode) then
310327
-- Handle deallocation of allocated nodes
311328
if hoverNode.isAttribute then
312329
-- change to other attribute without needing to deallocate
@@ -323,7 +340,7 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents)
323340
end
324341
spec:AddUndoState()
325342
build.buildFlag = true
326-
elseif hoverNode.path and not shouldBlockGlobalNodeAllocation(hoverNode) then
343+
elseif hoverNode.path and not shouldBlockNodeAllocation(hoverNode) then
327344
-- Handle allocation of unallocated nodes
328345
if hoverNode.isAttribute and not hotkeyPressed then
329346
build.treeTab:ModifyAttributePopup(hoverNode)
@@ -350,7 +367,8 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents)
350367
build.itemsTab:SelectControl(slot)
351368
build.viewMode = "ITEMS"
352369
end
353-
else
370+
elseif not hoverNode.alloc and not shouldBlockNodeAllocation(hoverNode) then
371+
-- Only proceed with allocation if it's not blocked
354372
-- a way for us to bypass the popup when allocating attribute nodes, last used hotkey + RMB
355373
-- RMB + non attribute node logic
356374
-- RMB hot-swap logic
@@ -1179,7 +1197,7 @@ function PassiveTreeViewClass:AddNodeTooltip(tooltip, node, build, incSmallPassi
11791197
tooltip:AddLine(14, colorCodes.TIP.."Tip: Right click this socket to go to the items page and choose the jewel for this socket.")
11801198
end
11811199

1182-
self:AddGlobalNodeWarningsToTooltip(tooltip, node, build)
1200+
self:AddNodeWarningsToTooltip(tooltip, node, build)
11831201

11841202
tooltip:AddLine(14, colorCodes.TIP.."Tip: Hold Shift or Ctrl to hide this tooltip.")
11851203
return
@@ -1441,7 +1459,7 @@ function PassiveTreeViewClass:AddNodeTooltip(tooltip, node, build, incSmallPassi
14411459
tooltip:AddLine(14, colorCodes.TIP)
14421460
end
14431461

1444-
self:AddGlobalNodeWarningsToTooltip(tooltip, node, build)
1462+
self:AddNodeWarningsToTooltip(tooltip, node, build)
14451463

14461464
if node.type == "Socket" then
14471465
tooltip:AddLine(14, colorCodes.TIP.."Tip: Hold Shift or Ctrl to hide this tooltip.")
@@ -1477,31 +1495,79 @@ function PassiveTreeViewClass:IsConnectedToWeaponSetNodes(node)
14771495
return false
14781496
end
14791497

1480-
-- Helper function to add warnings in the tooltip for global nodes (keystones/jewel sockets)
1481-
function PassiveTreeViewClass:AddGlobalNodeWarningsToTooltip(tooltip, node, build)
1498+
-- Helper function to check if a node can be reached from current weapon set without crossing other weapon sets
1499+
function PassiveTreeViewClass:CanReachFromCurrentWeaponSet(node, spec)
1500+
if not node or node.alloc then
1501+
return true -- Already allocated nodes don't need path checking
1502+
end
1503+
1504+
-- Check if any directly linked allocated node belongs to current weapon set or main tree
1505+
local canReachFromCurrentSet = false
1506+
1507+
if node.linked then
1508+
for _, linkedNode in ipairs(node.linked) do
1509+
if linkedNode.alloc then
1510+
-- Can reach if linked node is from current weapon set or main tree
1511+
if linkedNode.allocMode == spec.allocMode or linkedNode.allocMode == 0 then
1512+
canReachFromCurrentSet = true
1513+
end
1514+
1515+
-- Block if linked node is from different weapon set
1516+
if linkedNode.allocMode ~= spec.allocMode and linkedNode.allocMode ~= 0 then
1517+
return false
1518+
end
1519+
end
1520+
end
1521+
end
1522+
1523+
return canReachFromCurrentSet
1524+
end
1525+
1526+
-- Helper function to check if a path crosses between different weapon sets
1527+
function PassiveTreeViewClass:PathCrossesWeaponSets(node, spec)
1528+
-- Use the new reachability check instead of path analysis
1529+
return not self:CanReachFromCurrentWeaponSet(node, spec)
1530+
end
1531+
1532+
-- Helper function to add warnings in the tooltip for nodes affected by weapon set rules
1533+
function PassiveTreeViewClass:AddNodeWarningsToTooltip(tooltip, node, build)
14821534
local isGlobalNode = node.type == "Keystone" or node.type == "Socket" or node.containJewelSocket
1535+
local isAttributeNode = node.isAttribute
1536+
local spec = build.spec
14831537

1484-
if not isGlobalNode then
1485-
return -- No warning needed for non-global nodes
1538+
-- Early fold - no warnings needed for these cases
1539+
if not isGlobalNode and not isAttributeNode and not self:PathCrossesWeaponSets(node, spec) then
1540+
return
14861541
end
14871542

1488-
local nodeTypeText = node.type == "Keystone" and "keystones" or "jewel sockets"
14891543
local warningText = ""
14901544
local tipText = ""
14911545

14921546
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
1547+
-- Unallocated node warnings
1548+
if isGlobalNode then
1549+
local nodeTypeText = node.type == "Keystone" and "keystones" or "jewel sockets"
1550+
if spec.allocMode > 0 then
1551+
warningText = "Cannot allocate " .. nodeTypeText .. " while weapon set " .. spec.allocMode .. " is selected"
1552+
tipText = "Tip: Switch to main tree (Alt+scroll) to allocate " .. nodeTypeText
1553+
elseif self:IsConnectedToWeaponSetNodes(node) then
1554+
warningText = "Cannot allocate " .. nodeTypeText .. " - connected to weapon set nodes"
1555+
tipText = "Tip: Deallocate weapon set nodes in the connection path to allow allocation"
1556+
end
1557+
elseif isAttributeNode or self:PathCrossesWeaponSets(node, spec) then
1558+
warningText = "Cannot allocate - path crosses between different weapon sets"
1559+
tipText = "Tip: Deallocate conflicting weapon set nodes in the path first"
1560+
end
1561+
elseif node.alloc then
1562+
-- Allocated node warnings
1563+
if isGlobalNode and node.allocMode == 0 and spec.allocMode > 0 then
1564+
local nodeTypeText = node.type == "Keystone" and "keystones" or "jewel sockets"
1565+
warningText = "Cannot deallocate global " .. nodeTypeText .. " from weapon set " .. spec.allocMode
1566+
tipText = "Tip: Switch to main tree (Alt+scroll) to deallocate " .. nodeTypeText
1567+
elseif (isAttributeNode or not isGlobalNode) and node.allocMode ~= spec.allocMode and node.allocMode ~= 0 then
1568+
warningText = "Cannot deallocate - node was allocated by weapon set " .. node.allocMode
1569+
tipText = "Tip: Switch to weapon set " .. node.allocMode .. " (Alt+scroll) to deallocate this node"
1570+
end
15051571
end
15061572

15071573
if warningText ~= "" then

0 commit comments

Comments
 (0)