diff --git a/spec/System/TestPassiveSpec_spec.lua b/spec/System/TestPassiveSpec_spec.lua new file mode 100644 index 000000000..ac402294a --- /dev/null +++ b/spec/System/TestPassiveSpec_spec.lua @@ -0,0 +1,46 @@ +describe("TestPassiveSpec", function() + before_each(function() + newBuild() + end) + + local function firstLoadedSocketNode(spec) + for nodeId in pairs(spec.tree.sockets) do + if spec.nodes[nodeId] then + return nodeId + end + end + end + + it("ignores stale jewel socket item ids when loading saved builds", function() + local spec = new("PassiveSpec", build, latestTreeVersion) + local socketNodeId = firstLoadedSocketNode(spec) + + spec:Load({ + attrib = { title = "Stale Socket Test" }, + { + elem = "Sockets", + { + elem = "Socket", + attrib = { + nodeId = tostring(socketNodeId), + itemId = "999999", + } + } + } + }, "stale_socket.xml") + + assert.is_nil(spec.jewels[socketNodeId]) + end) + + it("does not crash when radius helpers see a stale jewel socket item id", function() + local spec = new("PassiveSpec", build, latestTreeVersion) + local socketNodeId = firstLoadedSocketNode(spec) + spec.jewels[socketNodeId] = 999999 + + local ok, err = pcall(function() + return spec:NodesInIntuitiveLeapLikeRadius(spec.nodes[socketNodeId]) + end) + + assert.is_true(ok, err) + end) +end) diff --git a/src/Classes/PassiveSpec.lua b/src/Classes/PassiveSpec.lua index 294782679..bb96c912e 100644 --- a/src/Classes/PassiveSpec.lua +++ b/src/Classes/PassiveSpec.lua @@ -117,11 +117,14 @@ function PassiveSpecClass:Load(xml, dbFileName) launch:ShowErrMsg("^1Error parsing '%s': 'Socket' element missing 'itemId' attribute", dbFileName) return true end - -- there are files which have been saved poorly and have empty jewel sockets saved as sockets with itemId zero. - -- this check filters them out to prevent dozens of invalid jewels - jewelIdNum = tonumber(child.attrib.itemId) - if jewelIdNum > 0 then - self.jewels[tonumber(child.attrib.nodeId)] = jewelIdNum + -- Some saved builds contain stale jewel socket item IDs after the + -- referenced item has been removed from the item list. Keep those + -- broken references out of the active tree state so later radius and + -- loadout code doesn't try to index a missing item. + local jewelIdNum = tonumber(child.attrib.itemId) + local nodeIdNum = tonumber(child.attrib.nodeId) + if nodeIdNum and jewelIdNum and jewelIdNum > 0 and self.build.itemsTab.items[jewelIdNum] then + self.jewels[nodeIdNum] = jewelIdNum end end end @@ -1075,9 +1078,12 @@ end function PassiveSpecClass:NodesInIntuitiveLeapLikeRadius(node) local result = { } if self.jewels[node.id] and self.jewels[node.id] > 0 then - local item = self.build.itemsTab.items[self.jewels[node.id]] + local item = self:GetJewel(self.jewels[node.id]) + if not item then + return result + end local radiusIndex = item.jewelRadiusIndex - if item and item.jewelData and item.jewelData.intuitiveLeapLike then + if item.jewelData.intuitiveLeapLike then local inRadius = self.nodes[node.id].nodesInRadius and self.nodes[node.id].nodesInRadius[radiusIndex] for affectedNodeId, affectedNode in pairs(inRadius or {}) do if self.nodes[affectedNodeId].alloc then