Files
alchemist-accessibility/accessibility/patches/popups.lua
T

77 lines
2.1 KiB
Lua
Raw Normal View History

2026-08-01 21:26:35 +02:00
-- Patch: views/levelCursorPopup.lua and views/inventoryCursorPopup.lua
--
-- `inventoryCursorPopup.set` is the convergence point for focus text in four
-- screens: inventory, craft, refine and trade. Patching it narrates all four
-- without touching any state file.
--
-- inventoryCursorPopup.set(lines, x, y, alignX, alignY) -- lines is a TABLE
-- of {text=, icon=}
--
-- NOTE: levelCursorPopup (the examine cursor) is deliberately NOT handled here.
-- It is set from an animation-completion callback, so its text lands a keypress
-- late unless the player enables the game's "quickExaminationPopup" option.
-- accessibility/states/ingame_observe.lua polls the cursor position instead,
-- which is immediate and setting-independent.
local speech = require("accessibility.speech")
-- Suppress repeats: the setter is called on every mouse move, often with
-- unchanged content.
local lastInventoryText
local function linesToText(lines)
if type(lines) ~= "table" then
return nil
end
local parts = {}
for _, line in ipairs(lines) do
if type(line) == "table" and line.text then
parts[#parts + 1] = line.text
elseif type(line) == "string" then
parts[#parts + 1] = line
end
end
if #parts == 0 then
return nil
end
return table.concat(parts, ". ")
end
return function()
----------------------------------------------------------------------------
-- inventoryCursorPopup: inventory, craft, refine, trade
----------------------------------------------------------------------------
local inventoryPopup = require("views.inventoryCursorPopup")
local realInventorySet = inventoryPopup.set
if not realInventorySet then
error("views.inventoryCursorPopup has no set function -- game structure changed")
end
inventoryPopup.set = function(lines, ...)
local result = realInventorySet(lines, ...)
pcall(function()
local text = linesToText(lines)
if not text then
lastInventoryText = nil
return
end
text = speech.normalise(text)
if not text or text == lastInventoryText then
return
end
lastInventoryText = text
speech.say(text, true)
end)
return result
end
end