Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
178 changes: 168 additions & 10 deletions src/Classes/PassiveSpec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,17 @@ local PassiveSpecClass = newClass("PassiveSpec", "UndoHandler", function(self, b
-- Keys are mastery node IDs, values are mastery effect IDs
self.masterySelections = { }

-- List of node allocation order
-- Keys are order indexes, values are node IDs
self.allocationOrder = { }
self.ascendancyAllocationOrder = { }

-- Keys are mastery node IDs, values are mastery effect IDs
self.masterySelections = { }

--for postload handler
self.initialLoad = true

self:SelectClass(0)
end)

Expand Down Expand Up @@ -116,6 +127,16 @@ function PassiveSpecClass:Load(xml, dbFileName)
end
end
self:ImportFromNodeList(tonumber(xml.attrib.classId), tonumber(xml.attrib.ascendClassId), hashList, masteryEffects)
if xml.attrib.allocationOrder then
for nodeId in string.gmatch(xml.attrib.allocationOrder, ("%d+")) do
table.insert(self.allocationOrder, tonumber(nodeId))
end
end
if xml.attrib.ascendancyAllocationOrder then
for nodeId in string.gmatch(xml.attrib.ascendancyAllocationOrder, ("%d+")) do
table.insert(self.ascendancyAllocationOrder, tonumber(nodeId))
end
end
elseif url then
self:DecodeURL(url)
end
Expand Down Expand Up @@ -201,7 +222,9 @@ function PassiveSpecClass:Save(xml)
classId = tostring(self.curClassId),
ascendClassId = tostring(self.curAscendClassId),
nodes = table.concat(allocNodeIdList, ","),
masteryEffects = table.concat(masterySelections, ",")
masteryEffects = table.concat(masterySelections, ","),
allocationOrder = table.concat(self.allocationOrder, ","),
ascendancyAllocationOrder = table.concat(self.ascendancyAllocationOrder, ",")
}
t_insert(xml, {
-- Legacy format
Expand All @@ -226,6 +249,9 @@ end

function PassiveSpecClass:PostLoad()
self:BuildClusterJewelGraphs()
self:ReIndexNodeAllocationOrder("allocationOrder")
self:ReIndexNodeAllocationOrder("ascendancyAllocationOrder")
self.initialLoad = false
end

-- Import passive spec from the provided class IDs and node hash list
Expand Down Expand Up @@ -330,10 +356,10 @@ function PassiveSpecClass:SelectAscendClass(ascendClassId)
-- Deallocate any allocated ascendancy nodes that don't belong to the new ascendancy class
for id, node in pairs(self.allocNodes) do
if node.ascendancyName and node.ascendancyName ~= ascendClass.name then
node.alloc = false
self.allocNodes[id] = nil
self:DeallocNode(node)
end
end
self:ReIndexNodeAllocationOrder("ascendancyAllocationOrder")

if ascendClass.startNodeId then
-- Allocate the new ascendancy class's start node
Expand Down Expand Up @@ -376,10 +402,74 @@ function PassiveSpecClass:ResetNodes()
for id, node in pairs(self.nodes) do
if node.type ~= "ClassStart" and node.type ~= "AscendClassStart" then
node.alloc = false
node.allocationOrder = nil
node.ascendancyAllocationOrder = nil
self.allocNodes[id] = nil
end
end
wipeTable(self.masterySelections)
self.allocationOrder = { }
self.ascendancyAllocationOrder = { }
end

function PassiveSpecClass:SetAllocationOrder(node)
if node.ascendancyName then
t_insert(self.ascendancyAllocationOrder, node.id)
node.ascendancyAllocationOrder = #self.ascendancyAllocationOrder
else
t_insert(self.allocationOrder, node.id)
node.allocationOrder = #self.allocationOrder
end
end

function PassiveSpecClass:RemoveFromAllocationOrder(node)
if node.ascendancyName then
t_remove(self.ascendancyAllocationOrder, node.ascendancyAllocationOrder)
node.ascendancyAllocationOrder = nil
else
t_remove(self.allocationOrder, node.allocationOrder)
node.allocationOrder = nil
end
end

function PassiveSpecClass:ReIndexNodeAllocationOrder(allocationOrder)
for i=#self[allocationOrder],1,-1 do
nodeId = self[allocationOrder][i]
if self.nodes[nodeId] then
self.nodes[nodeId][allocationOrder] = i
else
t_remove(self[allocationOrder], i)
end
end
end

function PassiveSpecClass:SortNodesForRemovingFromAllocationOrder(node)
depNodes = node.depends
if node.ascendancyName then
table.sort(depNodes, function(a, b)
if a.ascendancyAllocationOrder == nil and b.ascendancyAllocationOrder == nil then
return false
elseif a.ascendancyAllocationOrder == nil then
return true
elseif b.ascendancyAllocationOrder == nil then
return false
else
return a.ascendancyAllocationOrder > b.ascendancyAllocationOrder
end
end)
else
table.sort(depNodes, function(a, b)
if a.allocationOrder == nil and b.allocationOrder == nil then
return false
elseif a.allocationOrder == nil then
return true
elseif b.allocationOrder == nil then
return false
else
return a.allocationOrder > b.allocationOrder
end
Comment on lines +462 to +470
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This logic can be simplified:

Suggested change
if a.allocationOrder == nil and b.allocationOrder == nil then
return false
elseif a.allocationOrder == nil then
return true
elseif b.allocationOrder == nil then
return false
else
return a.allocationOrder > b.allocationOrder
end
if b.allocationOrder == nil then
return false
elseif a.allocationOrder == nil then
return true
else
return a.allocationOrder > b.allocationOrder
end

end)
end
end

-- Allocate the given node, if possible, and all nodes along the path to the node
Expand All @@ -395,10 +485,14 @@ function PassiveSpecClass:AllocNode(node, altPath)
if node.dependsOnIntuitiveLeapLike then
node.alloc = true
self.allocNodes[node.id] = node
self:SetAllocationOrder(node)
else
for _, pathNode in ipairs(altPath or node.path) do
local path = altPath or node.path
for i = #(path), 1, -1 do
local pathNode = path[i]
pathNode.alloc = true
self.allocNodes[pathNode.id] = pathNode
self:SetAllocationOrder(pathNode)
end
end

Expand All @@ -407,8 +501,12 @@ function PassiveSpecClass:AllocNode(node, altPath)
local parent = node.linked[1]
for _, optNode in ipairs(parent.linked) do
if optNode.isMultipleChoiceOption and optNode.alloc and optNode ~= node then
optNode.alloc = false
self.allocNodes[optNode.id] = nil
self.DeallocSingleNode(optNode)
if optNode.ascendancyName then
self:ReIndexNodeAllocationOrder("ascendancyAllocationOrder")
else
self:ReIndexNodeAllocationOrder("allocationOrder")
end
end
end
end
Expand All @@ -424,14 +522,23 @@ function PassiveSpecClass:DeallocSingleNode(node)
self:AddMasteryEffectOptionsToNode(node)
self.masterySelections[node.id] = nil
end
if self.allocationOrder[node.allocationOrder] or self.ascendancyAllocationOrder[node.ascendancyAllocationOrder] then
self:RemoveFromAllocationOrder(node)
end
end

-- Deallocate the given node, and all nodes which depend on it (i.e. which are only connected to the tree through this node)
function PassiveSpecClass:DeallocNode(node)
local effect
self:SortNodesForRemovingFromAllocationOrder(node)

for _, depNode in ipairs(node.depends) do
self:DeallocSingleNode(depNode)
end
if node.ascendancyName then
self:ReIndexNodeAllocationOrder("ascendancyAllocationOrder")
else
self:ReIndexNodeAllocationOrder("allocationOrder")
end

-- Rebuild all paths and dependencies for all allocated nodes
self:BuildAllDependsAndPaths()
Expand Down Expand Up @@ -774,6 +881,7 @@ function PassiveSpecClass:BuildAllDependsAndPaths()
if not anyStartFound then
-- No start nodes were found through ANY nodes
-- Therefore this node and all nodes depending on it are orphans and should be pruned
self:SortNodesForRemovingFromAllocationOrder(node)
for _, depNode in ipairs(node.depends) do
local prune = true
for nodeId, itemId in pairs(self.jewels) do
Expand All @@ -797,9 +905,14 @@ function PassiveSpecClass:BuildAllDependsAndPaths()
end
end
if prune then
self:DeallocSingleNode(depNode)
self:DeallocNode(depNode)
end
end
if node.ascendancyName then
self:ReIndexNodeAllocationOrder("ascendancyAllocationOrder")
else
self:ReIndexNodeAllocationOrder("allocationOrder")
end
end
end

Expand Down Expand Up @@ -853,9 +966,27 @@ end

function PassiveSpecClass:BuildClusterJewelGraphs()
-- Remove old subgraphs
local reserverdAllocationOrders = {}
for id, subGraph in pairs(self.subGraphs) do
table.sort(subGraph.nodes, function(a, b)
if a.allocationOrder == nil and b.allocationOrder == nil then
return false
elseif a.allocationOrder == nil then
return true
elseif b.allocationOrder == nil then
return false
else
return a.allocationOrder > b.allocationOrder
end
end)
for _, node in ipairs(subGraph.nodes) do
if node.id then
if node.alloc then
if node.allocationOrder ~= nil then
reserverdAllocationOrders[node.id] = node.allocationOrder
node.allocationOrder = nil
end
end
self.nodes[node.id] = nil
if self.allocNodes[node.id] then
-- Reserve the allocation in case the node is regenerated
Expand Down Expand Up @@ -893,17 +1024,36 @@ function PassiveSpecClass:BuildClusterJewelGraphs()
end
end

ConPrintTable(reserverdAllocationOrders)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ConPrintTable(reserverdAllocationOrders)

-- (Re-)allocate subgraph nodes
for _, nodeId in ipairs(self.allocSubgraphNodes) do
local sortedAllocSubgraphNodes = {}
for i=#self.allocSubgraphNodes, 1, -1 do
sortedAllocSubgraphNodes[#sortedAllocSubgraphNodes+1] = self.allocSubgraphNodes[i]
end
for _, nodeId in ipairs(sortedAllocSubgraphNodes) do
local node = self.nodes[nodeId]
if node then
node.alloc = true
if not self.allocNodes[nodeId] then
self.allocNodes[nodeId] = node
t_insert(self.allocExtendedNodes, nodeId)
end
if not self.initialLoad then
if reserverdAllocationOrders[nodeId] then
self.allocationOrder[reserverdAllocationOrders[nodeId]] = nodeId
node.allocationOrder = reserverdAllocationOrders[nodeId]
reserverdAllocationOrders[nodeId] = nil
else
self:SetAllocationOrder(node)
end
end
end
end
for nodeId, unallocated in pairs(reserverdAllocationOrders) do
self:RemoveFromAllocationOrder(self.nodes[nodeId])
end
ConPrintTable(self.allocationOrder)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ConPrintTable(self.allocationOrder)

self:ReIndexNodeAllocationOrder("allocationOrder")
wipeTable(self.allocSubgraphNodes)

-- Rebuild paths to account for new/removed nodes
Expand Down Expand Up @@ -1319,16 +1469,24 @@ function PassiveSpecClass:CreateUndoState()
for mastery, effect in pairs(self.masterySelections) do
selections[mastery] = effect
end
local allocationOrder = copyTable(self.allocationOrder)
local ascendancyAllocationOrder = copyTable(self.ascendancyAllocationOrder)
return {
classId = self.curClassId,
ascendClassId = self.curAscendClassId,
hashList = allocNodeIdList,
masteryEffects = selections
masteryEffects = selections,
allocationOrder = allocationOrder,
ascendancyAllocationOrder = ascendancyAllocationOrder
}
end

function PassiveSpecClass:RestoreUndoState(state)
self:ImportFromNodeList(state.classId, state.ascendClassId, state.hashList, state.masteryEffects)
self.allocationOrder = state.allocationOrder
self.ascendancyAllocationOrder = state.ascendancyAllocationOrder
self:ReIndexNodeAllocationOrder("allocationOrder")
self:ReIndexNodeAllocationOrder("ascendancyAllocationOrder")
self:SetWindowTitleWithBuildClass()
end

Expand Down
18 changes: 18 additions & 0 deletions src/Classes/PassiveTreeView.lua
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ function PassiveTreeViewClass:Load(xml, fileName)
if xml.attrib.searchStr then
self.searchStr = xml.attrib.searchStr
end
if xml.attrib.showAllocationOrder then
self.showAllocationOrder = xml.attrib.showAllocationOrder == "true"
end
if xml.attrib.showHeatMap then
self.showHeatMap = xml.attrib.showHeatMap == "true"
end
Expand All @@ -89,6 +92,7 @@ function PassiveTreeViewClass:Save(xml)
zoomX = tostring(self.zoomX),
zoomY = tostring(self.zoomY),
searchStr = self.searchStr,
showAllocationOrder = tostring(self.showAllocationOrder),
showHeatMap = tostring(self.showHeatMap),
showStatDifferences = tostring(self.showStatDifferences),
}
Expand Down Expand Up @@ -670,6 +674,20 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents)
local size = 175 * scale / self.zoom ^ 0.4
DrawImage(self.highlightRing, scrX - size, scrY - size, size * 2, size * 2)
end
if self.showAllocationOrder and node.allocationOrder ~= nil then
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if self.showAllocationOrder and node.allocationOrder ~= nil then
if self.showAllocationOrder and node.allocationOrder then

SetDrawLayer(nile, 29)
SetDrawColor(1, 0, 0)
local size = 100 * scale
local offset = node.size * 1.8 * scale
DrawString(m_floor(scrX - offset), m_floor(scrY - offset), "LEFT", size, "VAR", tostring(node.allocationOrder))
end
if self.showAllocationOrder and node.ascendancyAllocationOrder ~= nil then
SetDrawLayer(nile, 29)
SetDrawColor(1, 0, 0)
local size = 100 * scale
local offset = node.size * 1.8 * scale
DrawString(m_floor(scrX - offset), m_floor(scrY - offset), "LEFT", size, "VAR", tostring(node.ascendancyAllocationOrder))
end
Comment on lines +678 to +690
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can all be combined into two calls to a local function

if node == hoverNode and (node.type ~= "Socket" or not IsKeyDown("SHIFT")) and (node.type ~= "Mastery" or node.masteryEffects) and not IsKeyDown("CTRL") and not main.popups[1] then
-- Draw tooltip
SetDrawLayer(nil, 100)
Expand Down
9 changes: 7 additions & 2 deletions src/Classes/TreeTab.lua
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,11 @@ local TreeTabClass = newClass("TreeTab", "ControlHost", function(self, build)
self.controls.treeSearch = new("EditControl", {"LEFT",self.controls.export,"RIGHT"}, 8, 0, main.portraitMode and 200 or 300, 20, "", "Search", "%c%(%)", 100, function(buf)
self.viewer.searchStr = buf
end)
self.controls.treeSearch.tooltipText = "Uses Lua pattern matching for complex searches"
self.controls.treeHeatMap = new("CheckBoxControl", {"LEFT",self.controls.treeSearch,"RIGHT"}, 130, 0, 20, "Show Node Power:", function(state)
self.controls.treeSearch.tooltipText = "Uses Lua pattern matching for complex searches"
self.controls.treeAllocationOrder = new("CheckBoxControl", {"LEFT",self.controls.treeSearch,"RIGHT"}, 194, 0, 20, "Show Node Allocation Order:", function(state)
self.viewer.showAllocationOrder = state
end)
self.controls.treeHeatMap = new("CheckBoxControl", {"LEFT",self.controls.treeAllocationOrder,"RIGHT"}, 130, 0, 20, "Show Node Power:", function(state)
self.viewer.showHeatMap = state
self.controls.treeHeatMapStatSelect.shown = state
end)
Expand Down Expand Up @@ -228,6 +231,8 @@ function TreeTabClass:Draw(viewPort, inputEvents)
self.controls.treeSearch:SetText(self.viewer.searchStr)
end

self.controls.treeAllocationOrder.state = self.viewer.showAllocationOrder

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

self.controls.treeHeatMap.state = self.viewer.showHeatMap
self.controls.treeHeatMapStatSelect.list = self.powerStatList
self.controls.treeHeatMapStatSelect.selIndex = 1
Expand Down