-- Patch: views/popupStack.lua -- -- Popups are the game's way of telling you something happened without -- interrupting play: loot found, a recipe learned, a quest updated, a new beast -- recorded, a tutorial offered. They fade in at the side of the screen and none -- of them go through console.print, so without this they are entirely silent. -- -- popupStack.add{...} is the single entry point for all of them. local speech = require("accessibility.speech") -- What each popup type is called out loud. Keys match the `popupType` field -- passed by states/ingame.lua and states/ingame_observe.lua. local typeNames = { loot = "Found", recipe = "Recipe", lore = "Lore", map = "Map", journal = "Quest", tutorial = "Tutorial", bestiary = "Bestiary", } local function describe(params) local parts = {} parts[#parts + 1] = typeNames[params.popupType] or params.popupType or "Notice" -- `header` is the human-readable line the popup itself displays -- ("You found:", a quest title), so prefer it over any id. if params.header and params.header ~= "" then parts[#parts + 1] = params.header end if params.loot then for _, entry in ipairs(params.loot) do local name = (type(entry) == "table") and (entry.name or entry.templateId) or tostring(entry) if name then local quantity = type(entry) == "table" and entry.quantity parts[#parts + 1] = (quantity and quantity > 1) and (name .. " x" .. quantity) or name end end end if params.quest and type(params.quest) == "table" and params.quest.title then parts[#parts + 1] = params.quest.title end if params.templateId and not params.header then parts[#parts + 1] = (tostring(params.templateId):gsub("_", " ")) end return table.concat(parts, ": ", 1, math.min(2, #parts)) .. (#parts > 2 and (". " .. table.concat(parts, ", ", 3)) or "") end return function() local popupStack = require("views.popupStack") local realAdd = popupStack.add if not realAdd then error("views.popupStack has no add function -- game structure changed") end popupStack.add = function(params) local result = realAdd(params) pcall(function() if type(params) ~= "table" then return end -- Queued, not interrupting: a popup is informational, and several can -- land in one turn (loot plus a quest update). speech.say(describe(params), false) end) return result end end