-- states/narration.lua -- -- The intro and interlude screens. Text is revealed one line at a time: pressing -- enter advances `currentLoadedLine` within `displayData[currentPage]`, and rolls -- over to the next page at the end. -- -- Not a list menu, so this uses a custom read(). The "focus" is the most recently -- revealed line, keyed by page:line so each newly revealed line is announced once. return { read = function(stateTable, menus) -- Two-level probe. narration.keypressed does not touch these locals -- directly -- it just calls continueNarration(), so they are upvalues of -- THAT function. We reach continueNarration as an upvalue of keypressed, -- then read through it. local probeFn = menus.getUpvalue(stateTable.keypressed, "continueNarration") if type(probeFn) ~= "function" then return nil, nil end local displayData = menus.getUpvalue(probeFn, "displayData") local page = menus.getUpvalue(probeFn, "currentPage") local line = menus.getUpvalue(probeFn, "currentLoadedLine") if type(displayData) ~= "table" or type(page) ~= "number" or type(line) ~= "number" then return nil, nil end local pageData = displayData[page] if type(pageData) ~= "table" then return nil, nil end local entry = pageData[line] if type(entry) ~= "table" or not entry.text then return nil, nil end return entry.text, page .. ":" .. line end, }