Files
alchemist-accessibility/accessibility/states/_itemgrid.lua
T
Accessibility ModandClaude Opus 5 50b226620e Phase 4 remainder: crafting screens, slider, config options
Game-file footprint unchanged: still one line in main.lua.

The slider turned out to be genuinely generic: modules/slider.lua is a factory,
so one wrapper on it narrates all four users -- craft, refine, trade and
ingame_wait (the wait-N-turns screen). Same leverage as the console.print and
inventoryCursorPopup patches.

The options screens do NOT share it, though: config_menu changes values through
config.increase/config.decrease, so it needed its own descriptor. It reports tab,
option name and value, and its focus key includes the value so left/right
re-announce even though the focused option has not moved.

states/_itemgrid.lua is now shared by inventory, craft, refine and trade, all of
which build a views/inventoryWindow. It stays silent while
confirmationWindowEnabled is set so the slider owns speech during quantity
selection instead of the two fighting.

testbed gains walkTo(), which navigates using the game's own pathfinder rather
than hardcoded direction sequences -- those drift as soon as anything moves the
player. The config test only adjusts a value when the focused option is
demonstrably safe, and puts it straight back.

The slider patch is applied and confirmed by the self-test but not exercised
live: ingame_wait is unreachable in the prologue because tutorial_bed overrides
bed's tryInteractFunction with an empty function by design, and the crafting
screens need an alchemy table and real items. Recorded as a NOTE rather than a
failing check, since it is a property of the game and not of the mod.

25/25 testbed checks, history unit tests passing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-01 22:12:56 +02:00

79 lines
2.4 KiB
Lua

-- 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