require("core/PlayAreaImageData") -- this fills the variable "PLAYAREA_IMAGE_DATA" local optionPanelApi = require("core/OptionPanelApi") local playAreaApi = require("core/PlayAreaApi") local typeIndex, selectionIndex, plainNameCache function onSave() return JSON.encode({ typeIndex = typeIndex, selectionIndex = selectionIndex }) end function onLoad(savedData) if savedData and savedData ~= "" then local loadedData = JSON.decode(savedData) or {} typeIndex = loadedData.typeIndex or 1 selectionIndex = loadedData.selectionIndex or 1 end self.createButton({ function_owner = self, click_function = "onClick_toggleGallery", tooltip = "Show Image Gallery", position = {0, 0.06, 0}, height = 1500, width = 1500, color = { 1, 1, 1, 0 } }) Wait.time(updatePlayAreaGallery, 0.5) math.randomseed(os.time()) end -- click function for main button function onClick_toggleGallery(_, playerColor) Global.call("togglePlayAreaGallery", playerColor) end function getDataSubTableByIndex(dataTable, index) local loopId = 1 for i, v in pairs(dataTable) do if index == loopId then return v end loopId = loopId + 1 end return {} end function updatePlayAreaGallery() -- get subtables local dataForType = getDataSubTableByIndex(PLAYAREA_IMAGE_DATA, typeIndex) local dataForSelection = getDataSubTableByIndex(dataForType, selectionIndex) -- get global xml to insert elements local globalXml = UI.getXmlTable() -- selectable items local itemSelection = getXmlTableElementById(globalXml, 'itemSelection') itemSelection.children = {} local i = 0 for itemName, _ in pairs(dataForType) do i = i + 1 table.insert(itemSelection.children, { tag = "Panel", attributes = { class = "itemPanel", id = "typePanel" .. i }, children = { tag = "Text", value = itemName, attributes = { class = "itemText", id = "typeListText" .. i } } }) end -- selectable images for that item local playareaList = getXmlTableElementById(globalXml, 'playareaList') playareaList.children = {} for i, v in ipairs(dataForSelection) do table.insert(playareaList.children, { tag = "VerticalLayout", attributes = { class = "imageBox", id = "image" .. i }, children = { { tag = 'Image', attributes = { class = "playareaImage", image = v.URL } }, { tag = 'Text', value = v.Name, attributes = { class = "imageName" } } } }) end playareaList.attributes.height = round(#playareaList.children / 2, 0) * 380 Global.call("updateGlobalXml", globalXml) Wait.time(highlightTabAndItem, 0.1) end function onClick_imageTab(_, _, tabId) typeIndex = tonumber(tabId:sub(9)) selectionIndex = 1 updatePlayAreaGallery() end function onClick_listItem(_, _, listId) selectionIndex = tonumber(listId:sub(10)) updatePlayAreaGallery() end function onClick_image(player, _, id) local imageIndex = tonumber(id:sub(6)) local dataForType = getDataSubTableByIndex(PLAYAREA_IMAGE_DATA, typeIndex) local dataForSelection = getDataSubTableByIndex(dataForType, selectionIndex) local newURL = dataForSelection[imageIndex].URL playAreaApi.updateSurface(newURL) Global.call("togglePlayAreaGallery", player.color) end function highlightTabAndItem() -- highlight active tab for i = 1, 5 do local color = "#888888" if i == typeIndex then color = "#ffffff" end UI.setAttribute("imageTab" .. i, "color", color) end -- highlight item UI.setAttribute("typePanel" .. selectionIndex, "color", "grey") UI.setAttribute("typeListText" .. selectionIndex, "color", "black") end -- loops through an XML table and returns the specified object ---@param ui table XmlTable (get this via getXmlTable) ---@param id string Id of the object to return function getXmlTableElementById(ui, id) for _, obj in ipairs(ui) do if obj.attributes and obj.attributes.id and obj.attributes.id == id then return obj end if obj.children then local result = getXmlTableElementById(obj.children, id) if result then return result end end end return nil end -- utility function function round(num, numDecimalPlaces) local mult = 10 ^ (numDecimalPlaces or 0) return math.floor(num * mult + 0.5) / mult end function maybeUpdatePlayAreaImage(scenarioName) -- check if option is enabled local optionPanelState = optionPanelApi.getOptions() if not optionPanelState["changePlayAreaImage"] then return end -- initialize cache if nil if not plainNameCache then plainNameCache = {} for i, dataForType in pairs(PLAYAREA_IMAGE_DATA) do for j, dataForCycle in pairs(dataForType) do for k, data in ipairs(dataForCycle) do local plainName = getPlainName(data.Name) -- override plainName for all images in the "Other Images" category (except the default image) if i == "Other Images" and data.Name ~= "Default Image" then plainName = "Generic" end if not plainNameCache[plainName] then plainNameCache[plainName] = {} end table.insert(plainNameCache[plainName], data.URL) end end end end -- look for matching playarea image or use generic ones instead local listOfEligibleImages = {} if plainNameCache[scenarioName] then listOfEligibleImages = plainNameCache[scenarioName] else listOfEligibleImages = plainNameCache["Generic"] end -- get a random entry from the eligible list local newImageIndex = math.random(#listOfEligibleImages) playAreaApi.updateSurface(listOfEligibleImages[newImageIndex]) end -- attempts to extract the plain scenario name from the playarea image name function getPlainName(str) -- remove prefix type 1 str = str:gsub("%w+%-%w%s%-%s", "") -- matches "II-B - Thousand Shapes of Horror 1" -- remove prefix type 2 str = str:gsub("%w+%-%w%s", "") -- matches "59-Z Congress of Keys 1" -- remove prefix type 3 str = str:gsub("%w+%s%-%s", "") -- matches "III - The Secret Name 4" -- remove prefix type 4 str = str:gsub("%?+%s%-%s", "") -- matches "??? - Fatal Mirage" -- remove suffix (numbering) str = str:gsub("%s%d+", "") return str end