-- Shared descriptor for the item-grid screens: inventory, craft, refine, trade. -- -- All four build a `views/inventoryWindow` and move a cursor over a grid of -- cells. The inventoryCursorPopup patch speaks item details, but ONLY when a cell -- actually holds an item -- so empty cells and empty tabs were silent and you -- could not tell the cursor had moved. This owns narration for these screens -- instead (patches/popups.lua stands down wherever a descriptor exists). -- -- Returns a descriptor; call with the state's window upvalue name. local itemCategories = require("modules.item.categories") return function(options) options = options or {} local windowName = options.window or "inventoryWindow" local lastTab return { read = function(stateTable, menus) -- While the quantity confirmation window is open, the slider owns -- speech (see patches/slider.lua). Announcing the grid cell over the -- top of it would fight the number the player is adjusting. local confirming = menus.getAnyUpvalue(stateTable, "confirmationWindowEnabled") if confirming then return nil, nil end local window = menus.getAnyUpvalue(stateTable, windowName) if type(window) ~= "table" or not window.getItemOnCursor then return nil, nil end local position = window.cursorPosition if type(position) ~= "number" then return nil, nil end -- activeTabIndex lives inside the window closure, not the state file, -- so reach it through one of the window's own methods. local tabIndex if window.adjustTab then tabIndex = menus.getUpvalue(window.adjustTab, "activeTabIndex") end local parts = {} if tabIndex and tabIndex ~= lastTab then lastTab = tabIndex local category = itemCategories[tabIndex] parts[#parts + 1] = (category and category.header) or ("tab " .. tabIndex) end local ok, item = pcall(window.getItemOnCursor) if ok and item then parts[#parts + 1] = item.name or item.templateId or "item" if item.quantity and item.quantity > 1 then parts[#parts + 1] = "x" .. item.quantity end if item.isUnavailable then parts[#parts + 1] = "unavailable" end else parts[#parts + 1] = "empty" end parts[#parts + 1] = "slot " .. position return table.concat(parts, ", "), table.concat({ tostring(tabIndex), tostring(position), tostring(ok and item and (item.name or "?")), }, ":") end, } end