Skip to content

Commit fe83ace

Browse files
committed
1 parent a3d1562 commit fe83ace

File tree

4 files changed

+168
-9
lines changed

4 files changed

+168
-9
lines changed

src/Classes/PassiveSpec.lua

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -680,6 +680,80 @@ function PassiveSpecClass:IsClassConnected(classId)
680680
return false
681681
end
682682

683+
-- Find and allocate the shortest path to connect to a target class's starting node
684+
function PassiveSpecClass:ConnectToClass(classId)
685+
local classData = self.tree.classes[classId]
686+
if not classData then
687+
return false
688+
end
689+
local targetStartNode = self.nodes[classData.startNodeId]
690+
if not targetStartNode then
691+
return false
692+
end
693+
694+
local function isMainTreeNode(node)
695+
return node
696+
and not node.isProxy
697+
and not node.ascendancyName
698+
and node.type ~= "ClassStart"
699+
and node.type ~= "AscendClassStart"
700+
end
701+
702+
local visited = {}
703+
local prev = {}
704+
local queue = { targetStartNode }
705+
visited[targetStartNode] = true
706+
local head = 1
707+
local foundNode = nil
708+
709+
while queue[head] and not foundNode do
710+
local node = queue[head]
711+
head = head + 1
712+
713+
if node ~= targetStartNode and node.alloc and node.connectedToStart and node.type ~= "ClassStart" and node.type ~= "AscendClassStart" then
714+
foundNode = node
715+
break
716+
end
717+
718+
for _, linked in ipairs(node.linked) do
719+
if isMainTreeNode(linked) and not visited[linked] then
720+
visited[linked] = true
721+
prev[linked] = node
722+
queue[#queue + 1] = linked
723+
end
724+
end
725+
end
726+
727+
if not foundNode then
728+
return false
729+
end
730+
731+
local pathBack = {}
732+
local current = foundNode
733+
while current do
734+
t_insert(pathBack, current)
735+
if current == targetStartNode then
736+
break
737+
end
738+
current = prev[current]
739+
end
740+
741+
if pathBack[#pathBack] ~= targetStartNode then
742+
return false
743+
end
744+
745+
local altPath = { pathBack[1] }
746+
for idx = 2, #pathBack - 1 do
747+
altPath[idx] = pathBack[idx]
748+
local node = pathBack[idx]
749+
if not node.alloc then
750+
self:AllocNode(node, altPath)
751+
end
752+
end
753+
754+
return true
755+
end
756+
683757
-- Clear the allocated status of all non-class-start nodes
684758
function PassiveSpecClass:ResetNodes()
685759
for id, node in pairs(self.nodes) do
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
diff a/src/Classes/PassiveTreeView.lua b/src/Classes/PassiveTreeView.lua (rejected hunks)
2+
@@ -295,6 +295,7 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents)
3+
if bloodlineData.id == hoverNode.ascendancyName then
4+
spec:SelectSecondaryAscendClass(bloodlineId)
5+
spec:AddUndoState()
6+
+ spec:SetWindowTitleWithBuildClass()
7+
build.buildFlag = true
8+
break
9+
end
10+
@@ -322,6 +323,7 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents)
11+
-- Same-class switching - always allowed
12+
spec:SelectAscendClass(targetAscendClassId)
13+
spec:AddUndoState()
14+
+ spec:SetWindowTitleWithBuildClass()
15+
build.buildFlag = true
16+
else
17+
-- Cross-class switching - search all classes
18+
@@ -356,6 +358,7 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents)
19+
spec:SelectAscendClass(targetAscendClassId)
20+
allocateClickedAscendancy()
21+
spec:AddUndoState()
22+
+ spec:SetWindowTitleWithBuildClass()
23+
build.buildFlag = true
24+
else
25+
-- Tree has points but isn't connected to target class
26+
@@ -364,6 +367,7 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents)
27+
spec:SelectAscendClass(targetAscendClassId)
28+
allocateClickedAscendancy()
29+
spec:AddUndoState()
30+
+ spec:SetWindowTitleWithBuildClass()
31+
build.buildFlag = true
32+
end, "Connect Path", function()
33+
if spec:ConnectToClass(targetBaseClassId) then
34+
@@ -371,6 +375,7 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents)
35+
spec:SelectAscendClass(targetAscendClassId)
36+
allocateClickedAscendancy()
37+
spec:AddUndoState()
38+
+ spec:SetWindowTitleWithBuildClass()
39+
build.buildFlag = true
40+
end
41+
end)

src/Modules/Build.lua.rej

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
diff a/src/Modules/Build.lua b/src/Modules/Build.lua (rejected hunks)
2+
@@ -251,6 +251,13 @@ function buildMode:Init(dbFileName, buildName, buildXML, convertBuild, importLin
3+
self.spec:AddUndoState()
4+
self.spec:SetWindowTitleWithBuildClass()
5+
self.buildFlag = true
6+
+ end, "Connect Path", function()
7+
+ if self.spec:ConnectToClass(value.classId) then
8+
+ self.spec:SelectClass(value.classId)
9+
+ self.spec:AddUndoState()
10+
+ self.spec:SetWindowTitleWithBuildClass()
11+
+ self.buildFlag = true
12+
+ end
13+
end)
14+
end
15+
end

src/Modules/Main.lua

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1536,22 +1536,51 @@ function main:OpenMessagePopup(title, msg)
15361536
return self:OpenPopup(m_max(DrawStringWidth(16, "VAR", msg) + 30, 190), 70 + numMsgLines * 16, title, controls, "close")
15371537
end
15381538

1539-
function main:OpenConfirmPopup(title, msg, confirmLabel, onConfirm)
1539+
function main:OpenConfirmPopup(title, msg, confirmLabel, onConfirm, extraLabel, onExtra)
15401540
local controls = { }
15411541
local numMsgLines = 0
15421542
for line in string.gmatch(msg .. "\n", "([^\n]*)\n") do
15431543
t_insert(controls, new("LabelControl", nil, {0, 20 + numMsgLines * 16, 0, 16}, line))
15441544
numMsgLines = numMsgLines + 1
15451545
end
15461546
local confirmWidth = m_max(80, DrawStringWidth(16, "VAR", confirmLabel) + 10)
1547-
controls.confirm = new("ButtonControl", nil, {-5 - m_ceil(confirmWidth/2), 40 + numMsgLines * 16, confirmWidth, 20}, confirmLabel, function()
1548-
main:ClosePopup()
1549-
onConfirm()
1550-
end)
1551-
t_insert(controls, new("ButtonControl", nil, {5 + m_ceil(confirmWidth/2), 40 + numMsgLines * 16, confirmWidth, 20}, "Cancel", function()
1552-
main:ClosePopup()
1553-
end))
1554-
return self:OpenPopup(m_max(DrawStringWidth(16, "VAR", msg) + 30, 190), 70 + numMsgLines * 16, title, controls, "confirm")
1547+
1548+
if extraLabel and onExtra then
1549+
-- Three button layout: Continue (left), Connect Path (center), Cancel (right)
1550+
local extraWidth = m_max(80, DrawStringWidth(16, "VAR", extraLabel) + 10)
1551+
local cancelWidth = 80
1552+
local spacing = 10
1553+
local totalWidth = confirmWidth + extraWidth + cancelWidth + (spacing * 2)
1554+
local leftEdge = -totalWidth / 2
1555+
local buttonY = 40 + numMsgLines * 16
1556+
local function placeButton(width, label, onClick, isConfirm)
1557+
local centerX = leftEdge + width / 2
1558+
local ctrl = new("ButtonControl", nil, {centerX, buttonY, width, 20}, label, function()
1559+
main:ClosePopup()
1560+
onClick()
1561+
end)
1562+
if isConfirm then
1563+
controls.confirm = ctrl
1564+
else
1565+
t_insert(controls, ctrl)
1566+
end
1567+
leftEdge = leftEdge + width + spacing
1568+
end
1569+
placeButton(confirmWidth, confirmLabel, onConfirm, true)
1570+
placeButton(extraWidth, extraLabel, onExtra)
1571+
placeButton(cancelWidth, "Cancel", function() end)
1572+
return self:OpenPopup(m_max(DrawStringWidth(16, "VAR", msg) + 30, totalWidth + 40), 70 + numMsgLines * 16, title, controls, "confirm")
1573+
else
1574+
-- Two button layout (original)
1575+
controls.confirm = new("ButtonControl", nil, {-5 - m_ceil(confirmWidth/2), 40 + numMsgLines * 16, confirmWidth, 20}, confirmLabel, function()
1576+
main:ClosePopup()
1577+
onConfirm()
1578+
end)
1579+
t_insert(controls, new("ButtonControl", nil, {5 + m_ceil(confirmWidth/2), 40 + numMsgLines * 16, confirmWidth, 20}, "Cancel", function()
1580+
main:ClosePopup()
1581+
end))
1582+
return self:OpenPopup(m_max(DrawStringWidth(16, "VAR", msg) + 30, 190), 70 + numMsgLines * 16, title, controls, "confirm")
1583+
end
15551584
end
15561585

15571586
function main:OpenNewFolderPopup(path, onClose)

0 commit comments

Comments
 (0)