Skip to content

Commit cab2876

Browse files
committed
Prevent weapon set A node allocation in weapon set B path
1 parent aeea3ce commit cab2876

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
@@ -1183,7 +1201,7 @@ function PassiveTreeViewClass:AddNodeTooltip(tooltip, node, build, incSmallPassi
11831201
tooltip:AddLine(14, colorCodes.TIP.."Tip: Right click this socket to go to the items page and choose the jewel for this socket.")
11841202
end
11851203

1186-
self:AddGlobalNodeWarningsToTooltip(tooltip, node, build)
1204+
self:AddNodeWarningsToTooltip(tooltip, node, build)
11871205

11881206
tooltip:AddLine(14, colorCodes.TIP.."Tip: Hold Shift or Ctrl to hide this tooltip.")
11891207
return
@@ -1448,7 +1466,7 @@ function PassiveTreeViewClass:AddNodeTooltip(tooltip, node, build, incSmallPassi
14481466
tooltip:AddLine(14, colorCodes.TIP)
14491467
end
14501468

1451-
self:AddGlobalNodeWarningsToTooltip(tooltip, node, build)
1469+
self:AddNodeWarningsToTooltip(tooltip, node, build)
14521470

14531471
if node.type == "Socket" then
14541472
tooltip:AddLine(14, colorCodes.TIP.."Tip: Hold Shift or Ctrl to hide this tooltip.")
@@ -1484,31 +1502,79 @@ function PassiveTreeViewClass:IsConnectedToWeaponSetNodes(node)
14841502
return false
14851503
end
14861504

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

1491-
if not isGlobalNode then
1492-
return -- No warning needed for non-global nodes
1545+
-- Early fold - no warnings needed for these cases
1546+
if not isGlobalNode and not isAttributeNode and not self:PathCrossesWeaponSets(node, spec) then
1547+
return
14931548
end
14941549

1495-
local nodeTypeText = node.type == "Keystone" and "keystones" or "jewel sockets"
14961550
local warningText = ""
14971551
local tipText = ""
14981552

14991553
if not node.alloc and node.path then
1500-
-- Unallocated global node - check allocation conditions
1501-
if build.spec.allocMode > 0 then
1502-
warningText = "Cannot allocate " .. nodeTypeText .. " while weapon set " .. build.spec.allocMode .. " is selected"
1503-
tipText = "Tip: Switch to main tree (Alt+scroll) to allocate " .. nodeTypeText
1504-
elseif self:IsConnectedToWeaponSetNodes(node) then
1505-
warningText = "Cannot allocate " .. nodeTypeText .. " - connected to weapon set nodes"
1506-
tipText = "Tip: Deallocate weapon set nodes in the connection path to allow allocation"
1507-
end
1508-
elseif node.alloc and node.allocMode == 0 and build.spec.allocMode > 0 then
1509-
-- Allocated main-tree global node viewed from weapon set
1510-
warningText = "Cannot deallocate global " .. nodeTypeText .. " from weapon set " .. build.spec.allocMode
1511-
tipText = "Tip: Switch to main tree (Alt+scroll) to deallocate " .. nodeTypeText
1554+
-- Unallocated node warnings
1555+
if isGlobalNode then
1556+
local nodeTypeText = node.type == "Keystone" and "keystones" or "jewel sockets"
1557+
if spec.allocMode > 0 then
1558+
warningText = "Cannot allocate " .. nodeTypeText .. " while weapon set " .. spec.allocMode .. " is selected"
1559+
tipText = "Tip: Switch to main tree (Alt+scroll) to allocate " .. nodeTypeText
1560+
elseif self:IsConnectedToWeaponSetNodes(node) then
1561+
warningText = "Cannot allocate " .. nodeTypeText .. " - connected to weapon set nodes"
1562+
tipText = "Tip: Deallocate weapon set nodes in the connection path to allow allocation"
1563+
end
1564+
elseif isAttributeNode or self:PathCrossesWeaponSets(node, spec) then
1565+
warningText = "Cannot allocate - path crosses between different weapon sets"
1566+
tipText = "Tip: Deallocate conflicting weapon set nodes in the path first"
1567+
end
1568+
elseif node.alloc then
1569+
-- Allocated node warnings
1570+
if isGlobalNode and node.allocMode == 0 and spec.allocMode > 0 then
1571+
local nodeTypeText = node.type == "Keystone" and "keystones" or "jewel sockets"
1572+
warningText = "Cannot deallocate global " .. nodeTypeText .. " from weapon set " .. spec.allocMode
1573+
tipText = "Tip: Switch to main tree (Alt+scroll) to deallocate " .. nodeTypeText
1574+
elseif (isAttributeNode or not isGlobalNode) and node.allocMode ~= spec.allocMode and node.allocMode ~= 0 then
1575+
warningText = "Cannot deallocate - node was allocated by weapon set " .. node.allocMode
1576+
tipText = "Tip: Switch to weapon set " .. node.allocMode .. " (Alt+scroll) to deallocate this node"
1577+
end
15121578
end
15131579

15141580
if warningText ~= "" then

0 commit comments

Comments
 (0)