Skip to content

Commit 0496ed2

Browse files
author
justjuangui
committed
Refactor attribute handling in PassiveSpec and related classes for improved flexibility and maintainability
1 parent 18bc6c1 commit 0496ed2

File tree

4 files changed

+175
-42
lines changed

4 files changed

+175
-42
lines changed

src/Classes/ImportTab.lua

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -691,18 +691,11 @@ function ImportTabClass:ImportPassiveTreeAndJewels(charData)
691691
self.build.treeTab.controls.versionSelect.selIndex = #self.build.treeTab.treeVersions
692692
-- attributes nodes
693693
for skillId, nodeInfo in pairs(charPassiveData.skill_overrides) do
694-
local changeAttributeId = 0
695-
if nodeInfo.name == "Intelligence" then
696-
changeAttributeId = 3
697-
elseif nodeInfo.name == "Dexterity" then
698-
changeAttributeId = 2
699-
elseif nodeInfo.name == "Strength" then
700-
changeAttributeId = 1
701-
end
702-
703-
if changeAttributeId > 0 then
704-
local id = tonumber(skillId)
705-
self.build.spec:SwitchAttributeNode(id, changeAttributeId)
694+
local id = tonumber(skillId)
695+
local changeAttributeIndex = self.build.spec:GetAttributeIndexForNodeId(id, nodeInfo.name)
696+
697+
if changeAttributeIndex > 0 then
698+
self.build.spec:SwitchAttributeNode(id, changeAttributeIndex)
706699
local node = self.build.spec.nodes[id]
707700

708701
if node then

src/Classes/PassiveSpec.lua

Lines changed: 159 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -190,14 +190,30 @@ function PassiveSpecClass:Load(xml, dbFileName)
190190
for _, child in ipairs(node) do
191191
if child.elem == "AttributeOverride" then
192192
for strengthId in child.attrib.strNodes:gmatch("%d+") do
193-
self:SwitchAttributeNode(tonumber(strengthId), 1)
193+
local strengthNumberId = tonumber(strengthId)
194+
local atributeIndex = self:GetAttributeIndexForNodeId(strengthNumberId, "Strength")
195+
self:SwitchAttributeNode(strengthNumberId, atributeIndex)
194196
end
195197
for dexterityId in child.attrib.dexNodes:gmatch("%d+") do
196-
self:SwitchAttributeNode(tonumber(dexterityId), 2)
198+
local dexterityNumberId = tonumber(dexterityId)
199+
local atributeIndex = self:GetAttributeIndexForNodeId(dexterityNumberId, "Dexterity")
200+
self:SwitchAttributeNode(dexterityNumberId, atributeIndex)
197201
end
198202
for intelligenceId in child.attrib.intNodes:gmatch("%d+") do
199-
self:SwitchAttributeNode(tonumber(intelligenceId), 3)
203+
local intelligenceNumberId = tonumber(intelligenceId)
204+
local atributeIndex = self:GetAttributeIndexForNodeId(intelligenceNumberId, "Intelligence")
205+
self:SwitchAttributeNode(intelligenceNumberId, atributeIndex)
200206
end
207+
-- check if have child elems for other attribute types
208+
for _, other in ipairs(child) do
209+
if other.elem == "other" then
210+
local otherId = tonumber(other.attrib.id)
211+
local dn = other.attrib.dn
212+
local atributeIndex = self:GetAttributeIndexForNodeId(otherId, dn)
213+
self:SwitchAttributeNode(otherId, atributeIndex)
214+
end
215+
end
216+
201217
else
202218
ConPrintf("[PassiveSpecClass:Load] Unexpected element found in Overrides: " .. child.elem)
203219
end
@@ -281,7 +297,7 @@ function PassiveSpecClass:Save(xml)
281297
elem = "Overrides"
282298
}
283299
if self.hashOverrides then
284-
local strList, dexList, intList = { }, { }, { }
300+
local strList, dexList, intList, others = { }, { }, { }, { }
285301
for nodeId, node in pairs(self.hashOverrides) do
286302
if node.isAttribute then
287303
if node.dn == "Strength" then
@@ -290,10 +306,18 @@ function PassiveSpecClass:Save(xml)
290306
t_insert(dexList, nodeId)
291307
elseif node.dn == "Intelligence" then
292308
t_insert(intList, nodeId)
309+
else
310+
-- other attribute types not currently supported
311+
t_insert(others, { elem = "other", attrib = {id=tostring(nodeId), dn=tostring(node.dn)} })
293312
end
294313
end
295314
end
296315
local attributeOverride = { elem = "AttributeOverride", attrib = { strNodes = table.concat(strList, ","), dexNodes = table.concat(dexList, ","), intNodes = table.concat(intList, ",") } }
316+
if #others > 0 then
317+
for _, other in pairs(others) do
318+
t_insert(attributeOverride, other)
319+
end
320+
end
297321
t_insert(overrides, attributeOverride)
298322
end
299323
t_insert(xml, overrides)
@@ -1221,7 +1245,16 @@ function PassiveSpecClass:BuildAllDependsAndPaths()
12211245

12221246
-- set attribute nodes
12231247
if self.hashOverrides[node.id] then
1224-
self:ReplaceNode(node, self.hashOverrides[node.id])
1248+
-- before building path we need to check for hashOverrides still valid
1249+
local overrideNode = self.hashOverrides[node.id]
1250+
if self:IsUnlockedAttributeForNodeId(node.id, overrideNode.dn) then
1251+
-- valid override
1252+
self:ReplaceNode(node, self.hashOverrides[node.id])
1253+
else
1254+
-- invalid override, remove it
1255+
self.hashOverrides[node.id] = nil
1256+
self:ReplaceNode(node, self.tree.nodes[node.id])
1257+
end
12251258
end
12261259

12271260
-- If node is conquered, replace it or add mods
@@ -2352,14 +2385,126 @@ function PassiveSpecClass:NodeInKeystoneRadius(keystoneNames, nodeId, radiusInde
23522385
end
23532386

23542387
function PassiveSpecClass:SwitchAttributeNode(nodeId, attributeIndex)
2355-
if self.tree.nodes[nodeId] then --Make sure node exists on current tree
2356-
local newNode = copyTableSafe(self.tree.nodes[nodeId], false, true)
2357-
if not newNode.isAttribute then return end -- safety check
2358-
2359-
local option = newNode.options[attributeIndex]
2360-
self:ReplaceNode(newNode, option)
2361-
self.tree:ProcessStats(newNode)
2362-
2363-
self.hashOverrides[nodeId] = newNode
2388+
if not self.tree.nodes[nodeId] then --Make sure node exists on current tree
2389+
return
2390+
end
2391+
2392+
local newNode = copyTableSafe(self.tree.nodes[nodeId], false, true)
2393+
if not newNode.isAttribute then return end -- safety check
2394+
2395+
-- check if attributeIndex is valid
2396+
if attributeIndex < 1 or attributeIndex > #newNode.options then
2397+
return
23642398
end
2399+
2400+
local option = newNode.options[attributeIndex]
2401+
2402+
-- check if the option have "unlockedBy" and check in the spec if this is allocated
2403+
if option.unlockedBy then
2404+
local unlocked = false
2405+
for _, unlockNodeId in ipairs(option.unlockedBy) do
2406+
if self.allocNodes[unlockNodeId] then
2407+
unlocked = true
2408+
break
2409+
end
2410+
end
2411+
if not unlocked then
2412+
return
2413+
end
2414+
end
2415+
2416+
self:ReplaceNode(newNode, option)
2417+
self.tree:ProcessStats(newNode)
2418+
2419+
self.hashOverrides[nodeId] = newNode
23652420
end
2421+
2422+
function PassiveSpecClass:GetAttributeIndexForNodeId(nodeId, attributeName)
2423+
local node = self.tree.nodes[nodeId]
2424+
if not node then return 0 end --Make sure node exists on current tree
2425+
if not node.isAttribute then return 0 end -- safety check
2426+
for index, option in ipairs(node.options) do
2427+
if option.dn == attributeName then
2428+
return index
2429+
end
2430+
end
2431+
return 0
2432+
end
2433+
2434+
function PassiveSpecClass:GetUnlockedAttributeListForNodeId(nodeId)
2435+
local node = self.tree.nodes[nodeId]
2436+
if not node then return {} end --Make sure node exists on current tree
2437+
if not node.isAttribute then return {} end -- safety check
2438+
local attributeList = {}
2439+
for index, option in ipairs(node.options) do
2440+
if option.unlockedBy then
2441+
local unlocked = false
2442+
for _, unlockNodeId in ipairs(option.unlockedBy) do
2443+
if self.allocNodes[unlockNodeId] then
2444+
unlocked = true
2445+
break
2446+
end
2447+
end
2448+
if unlocked then
2449+
t_insert(attributeList, option.dn)
2450+
end
2451+
else
2452+
t_insert(attributeList, option.dn)
2453+
end
2454+
end
2455+
return attributeList
2456+
end
2457+
2458+
function PassiveSpecClass:IsUnlockedAttributeForNodeId(nodeId, attributeName)
2459+
local node = self.tree.nodes[nodeId]
2460+
if not node then return false end --Make sure node exists on current tree
2461+
if not node.isAttribute then return false end -- safety check
2462+
2463+
for index, option in ipairs(node.options) do
2464+
if option.dn == attributeName then
2465+
-- check if the option have "unlockedBy" and check in the spec if
2466+
if option.unlockedBy then
2467+
local unlocked = false
2468+
for _, unlockNodeId in ipairs(option.unlockedBy) do
2469+
if self.allocNodes[unlockNodeId] then
2470+
unlocked = true
2471+
break
2472+
end
2473+
end
2474+
return unlocked
2475+
end
2476+
return true
2477+
end
2478+
end
2479+
return false
2480+
end
2481+
2482+
function PassiveSpecClass:GetNextAttributeIndexForNodeId(nodeId, currentAttributeName)
2483+
local node = self.tree.nodes[nodeId]
2484+
if not node then return 1 end --Make sure node exists on current tree
2485+
if not node.isAttribute then return 1 end -- safety check
2486+
local foundCurrent = false
2487+
for index, option in ipairs(node.options) do
2488+
if foundCurrent then
2489+
-- check if the option have "unlockedBy" and check in the spec if this is allocated
2490+
if option.unlockedBy then
2491+
local unlocked = false
2492+
for _, unlockNodeId in ipairs(option.unlockedBy) do
2493+
if self.allocNodes[unlockNodeId] then
2494+
unlocked = true
2495+
break
2496+
end
2497+
end
2498+
if unlocked then
2499+
return index
2500+
end
2501+
else
2502+
return index
2503+
end
2504+
end
2505+
if option.dn == currentAttributeName then
2506+
foundCurrent = true
2507+
end
2508+
end
2509+
return 1
2510+
end

src/Classes/PassiveTreeView.lua

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -258,14 +258,14 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents)
258258
-- we always want to keep track of last used attribute
259259
local function processAttributeHotkeys(switchAttribute)
260260
if IsKeyDown("2") or IsKeyDown("S") then
261-
spec.attributeIndex = 1
262-
if switchAttribute then spec:SwitchAttributeNode(hoverNode.id, 1) end
261+
spec.attributeIndex = spec:GetAttributeIndexForNodeId(hoverNode.id, "strength")
262+
if switchAttribute then spec:SwitchAttributeNode(hoverNode.id, spec.attributeIndex) end
263263
elseif IsKeyDown("3") or IsKeyDown("D") then
264-
spec.attributeIndex = 2
265-
if switchAttribute then spec:SwitchAttributeNode(hoverNode.id, 2) end
264+
spec.attributeIndex = spec:GetAttributeIndexForNodeId(hoverNode.id, "dexterity")
265+
if switchAttribute then spec:SwitchAttributeNode(hoverNode.id, spec.attributeIndex) end
266266
elseif IsKeyDown("1") or IsKeyDown("I") then
267-
spec.attributeIndex = 3
268-
if switchAttribute then spec:SwitchAttributeNode(hoverNode.id, 3) end
267+
spec.attributeIndex = spec:GetAttributeIndexForNodeId(hoverNode.id, "intelligence")
268+
if switchAttribute then spec:SwitchAttributeNode(hoverNode.id, spec.attributeIndex) end
269269
end
270270
end
271271

@@ -449,13 +449,7 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents)
449449
processAttributeHotkeys(hoverNode.isAttribute)
450450
elseif hoverNode.isAttribute then
451451
-- If the attribute node is already set to str, int, or dex create a toggle effect between attrs
452-
if hoverNode.dn == "Intelligence" then
453-
spec.attributeIndex = 1
454-
elseif hoverNode.dn == "Dexterity" then
455-
spec.attributeIndex = 3
456-
elseif hoverNode.dn == "Strength" then
457-
spec.attributeIndex = 2
458-
end
452+
spec.attributeIndex = spec:GetNextAttributeIndexForNodeId(hoverNode.id, hoverNode.dn)
459453
spec:SwitchAttributeNode(hoverNode.id, spec.attributeIndex or 1)
460454
end
461455
spec:AllocNode(hoverNode, self.tracePath and hoverNode == self.tracePath[#self.tracePath] and self.tracePath)

src/Classes/TreeTab.lua

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -785,12 +785,13 @@ end
785785
function TreeTabClass:ModifyAttributePopup(hoverNode)
786786
local controls = { }
787787
local spec = self.build.spec
788-
local attributes = { "Strength", "Dexterity", "Intelligence" }
788+
local attributes = spec:GetUnlockedAttributeListForNodeId(hoverNode.id)
789789

790790
controls.attrSelect = new("DropDownControl", {"TOPLEFT",nil,"TOPLEFT"}, {225, 30, 100, 18}, attributes, nil)
791791
controls.save = new("ButtonControl", nil, {-50, 65, 80, 20}, "Allocate", function()
792-
spec:SwitchAttributeNode(hoverNode.id, controls.attrSelect.selIndex)
793-
spec.attributeIndex = controls.attrSelect.selIndex
792+
local attributeIndex = spec:GetAttributeIndexForNodeId(hoverNode.id, controls.attrSelect:GetSelValue())
793+
spec:SwitchAttributeNode(hoverNode.id, attributeIndex)
794+
spec.attributeIndex = attributeIndex
794795
spec:AllocNode(hoverNode, spec.tracePath and hoverNode == spec.tracePath[#spec.tracePath] and spec.tracePath)
795796
spec:AddUndoState()
796797
self.build.buildFlag = true

0 commit comments

Comments
 (0)