-- states/research.lua — the research tree. -- -- Not a list: a 2D graph of nodes navigated with the arrow keys, where up/down -- jump to the nearest node on the adjacent row. Nodes are drawn as icons with no -- text label, so there is no on-screen name to relay -- the id is the only -- identifier available, and the useful facts are whether the node is already -- unlocked, whether it CAN be unlocked yet, and whether you can afford it. -- -- Without that last part the screen is unusable by ear: pressing enter on an -- unaffordable node simply does nothing. local researchModel = require("models.research") -- "alchemy_basics_2" -> "alchemy basics 2" local function humanise(id) return (tostring(id):gsub("_", " ")) end return { read = function(stateTable, menus) local nodeId = menus.getAnyUpvalue(stateTable, "currentNodeId") if nodeId == nil then return nil, nil end local parts = {humanise(nodeId)} local unlocked = researchModel.unlockedNodes and researchModel.unlockedNodes[nodeId] if unlocked then parts[#parts + 1] = "researched" else local okUnlockable, unlockable = pcall(researchModel.isUnlockable, nodeId) local okAfford, affordable = pcall(researchModel.canAffordNode, nodeId) if okUnlockable and not unlockable then parts[#parts + 1] = "locked" elseif okAfford and not affordable then parts[#parts + 1] = "cannot afford" else parts[#parts + 1] = "available" end end return table.concat(parts, ", "), tostring(nodeId) .. ":" .. tostring(unlocked) end, }