-- Bundled by luabundle {"version":"1.6.0"} local __bundle_require, __bundle_loaded, __bundle_register, __bundle_modules = (function(superRequire) local loadingPlaceholder = {[{}] = true} local register local modules = {} local require local loaded = {} register = function(name, body) if not modules[name] then modules[name] = body end end require = function(name) local loadedModule = loaded[name] if loadedModule then if loadedModule == loadingPlaceholder then return nil end else if not modules[name] then if not superRequire then local identifier = type(name) == 'string' and '\"' .. name .. '\"' or tostring(name) error('Tried to require ' .. identifier .. ', but no such module has been registered') else return superRequire(name) end end loaded[name] = loadingPlaceholder loadedModule = modules[name](require, loaded, register, modules) loaded[name] = loadedModule end return loadedModule end return require, loaded, register, modules end)(nil) __bundle_register("util/SearchLib", function(require, _LOADED, __bundle_register, __bundle_modules) do local SearchLib = {} local filterFunctions = { isCard = function(x) return x.type == "Card" end, isDeck = function(x) return x.type == "Deck" end, isCardOrDeck = function(x) return x.type == "Card" or x.type == "Deck" end, isClue = function(x) return x.memo == "clueDoom" and x.is_face_down == false end, isTileOrToken = function(x) return x.type == "Tile" end, isUniversalToken = function(x) return x.getMemo() == "universalActionAbility" end, } -- performs the actual search and returns a filtered list of object references ---@param pos tts__Vector Global position ---@param rot? tts__Vector Global rotation ---@param size table Size ---@param filter? string Name of the filter function ---@param direction? table Direction (positive is up) ---@param maxDistance? number Distance for the cast local function returnSearchResult(pos, rot, size, filter, direction, maxDistance) local filterFunc if filter then filterFunc = filterFunctions[filter] end local searchResult = Physics.cast({ origin = pos, direction = direction or { 0, 1, 0 }, orientation = rot or { 0, 0, 0 }, type = 3, size = size, max_distance = maxDistance or 0 }) -- filter the result for matching objects local objList = {} for _, v in ipairs(searchResult) do if not filter or filterFunc(v.hit_object) then table.insert(objList, v.hit_object) end end return objList end -- searches the specified area SearchLib.inArea = function(pos, rot, size, filter) return returnSearchResult(pos, rot, size, filter) end -- searches the area on an object SearchLib.onObject = function(obj, filter) local pos = obj.getPosition() local size = obj.getBounds().size:setAt("y", 1) return returnSearchResult(pos, _, size, filter) end -- searches the specified position (a single point) SearchLib.atPosition = function(pos, filter) local size = { 0.1, 2, 0.1 } return returnSearchResult(pos, _, size, filter) end -- searches below the specified position (downwards until y = 0) SearchLib.belowPosition = function(pos, filter) local size = { 0.1, 2, 0.1 } local direction = { 0, -1, 0 } local maxDistance = pos.y return returnSearchResult(pos, _, size, filter, direction, maxDistance) end return SearchLib end end) __bundle_register("__root", function(require, _LOADED, __bundle_register, __bundle_modules) require("core/NavigationOverlayHandler") end) __bundle_register("core/NavigationOverlayHandler", function(require, _LOADED, __bundle_register, __bundle_modules) local playermatApi = require("playermat/PlayermatApi") fullButtonData = { { id = "1", width = "84", height = "33", offset = "1 2" }, -- 1. Act/Agenda { id = "2", width = "78", height = "69", offset = "1 -62" }, -- 2. Map { id = "3", width = "70", height = "36", offset = "-38 -126" }, -- 3. White { id = "4", width = "70", height = "36", offset = "38 -126" }, -- 4. Orange { id = "5", width = "36", height = "70", offset = "-63 -66" }, -- 5. Green { id = "6", width = "36", height = "70", offset = "63 -66" }, -- 6. Red { id = "7", width = "38", height = "38", offset = "-65 -3" }, -- 7. Victory { id = "8", width = "40", height = "40", offset = "65 -3" }, -- 8. Guide { id = "9", width = "56", height = "16", offset = "1 -20" }, -- 9. Player count { id = "10", width = "36", height = "16", offset = "1 -102" }, -- 10. Bless/Curse { id = "11", width = "168", height = "56", offset = "1 47" }, -- 11. Scenarios { id = "12", width = "52", height = "53", offset = "-154 134" }, -- 12. Player card panel { id = "13", width = "22", height = "22", offset = "-116 132" }, -- 13. Search card panel { id = "14", width = "120", height = "75", offset = "-152 70" }, -- 14. Player card display { id = "15", width = "40", height = "54", offset = "-150 -38" }, -- 15. Deck builder { id = "16", width = "104", height = "84", offset = "-154 -114" }, -- 16. Rules area { id = "17", width = "100", height = "170", offset = "152 72" }, -- 17. Cycle area { id = "18", width = "56", height = "60", offset = "182 -124" }, -- 18. Additions { id = "19", width = "20", height = "20", offset = "0 150" }, -- 19. Shrink { id = "20", width = "20", height = "20", offset = "20 150" }, -- 20. Close { id = "21", width = "20", height = "20", offset = "-20 150" } -- 21. Settings } playButtonData = { { id = "1", width = "80", height = "33", offset = "0 55" }, { id = "2", width = "78", height = "70", offset = "0 -8" }, { id = "3", width = "68", height = "32", offset = "-36 -71" }, { id = "4", width = "68", height = "32", offset = "36 -71" }, { id = "5", width = "35", height = "66", offset = "-65 -10" }, { id = "6", width = "35", height = "66", offset = "65 -10" }, { id = "7", width = "38", height = "38", offset = "-66 52" }, { id = "8", width = "38", height = "38", offset = "66 52" }, { id = "9", width = "50", height = "12", offset = "0 33" }, { id = "10", width = "32", height = "12", offset = "0 -48" }, { id = "19", width = "20", height = "20", offset = "0 80" }, { id = "20", width = "20", height = "20", offset = "20 80" }, { id = "21", width = "20", height = "20", offset = "-20 80" } } -- To-Do: dynamically get positions by linking to objects cameraData = { { position = { -1.6, 1.55, 0 }, distance = 18 }, -- 1. Act/Agenda { position = { -28, 1.55, 0 }, distance = -1 }, -- 2. Map { position = { -31.6, 1.55, 26.4 }, distance = -1 }, -- 3. Green playermat { position = { -55, 1.55, 12.05 }, distance = -1 }, -- 4. White playermat { position = { -55, 1.55, -11.48 }, distance = -1 }, -- 5. Orange playermat { position = { -31.6, 1.55, -26.4 }, distance = -1 }, -- 6. Red playermat { position = { -3, 1.55, 30 }, distance = 16 }, -- 7. Victory / SetAside { position = { -3, 1.55, -26.76 }, distance = 16 }, -- 8. Guide { position = { -11.83, 1.55, 0 }, distance = 10 }, -- 9. Player count { position = { -48.35, 1.55, 0 }, distance = 10 }, -- 10. Bless/Curse { position = { 12.56, 1.55, 0 }, distance = 45 }, -- 11. Scenarios { position = { 57.8, 1.55, 71 }, distance = 22 }, -- 12. Player card panel { position = { 60.38, 1.55, 56 }, distance = 10 }, -- 13. Card search panel { position = { 27.48, 1.55, 71 }, distance = 35 }, -- 14. Player card area { position = { -19.48, 1.55, 71 }, distance = 22 }, -- 15. Deck builder { position = { -52.92, 1.55, 71 }, distance = 42 }, -- 16. Rules area { position = { 26, 1.55, -71 }, distance = 65 }, -- 17. Cycle area { position = { -59.08, 1.55, -83 }, distance = 27 } -- 18. Additions } local settingsOpenForColor local visibility = {} local claims = {} local pitch = {} local distance = {} --------------------------------------------------------- -- save/load functionality --------------------------------------------------------- function onSave() return JSON.encode({ visibility = visibility, claims = claims, pitch = pitch, distance = distance }) end function onLoad(savedData) if savedData and savedData ~= "" then local loadedData = JSON.decode(savedData) visibility = loadedData.visibility claims = loadedData.claims pitch = loadedData.pitch distance = loadedData.distance else -- initialize tables with defaults for _, color in ipairs(Player.getColors()) do claims[color] = {} visibility[color] = { full = false, play = false } end end createXmlButtons() updateVisibility() end --------------------------------------------------------- -- visibility related functions --------------------------------------------------------- function cycleVisibility(color) setVisibility("next", color) end function copyVisibility(params) visibility[params.targetColor] = { full = visibility[params.startColor].full, play = visibility[params.startColor].play } updateVisibility() end function setVisibility(type, color) if type == "next" then if visibility[color].full then visibility[color] = { full = false, play = true } elseif visibility[color].play then visibility[color] = { full = false, play = false } else visibility[color] = { full = true, play = false } end elseif type == "toggle" then visibility[color] = { full = not visibility[color].full, play = not visibility[color].play } else visibility[color] = { full = false, play = false } end updateVisibility() end -- update XML visibility function updateVisibility() local colorString = { full = "", play = "" } for color, v in pairs(visibility) do if v.full then if colorString.full == "" then colorString.full = color else colorString.full = colorString.full .. '|' .. color end elseif v.play then if colorString.play == "" then colorString.play = color else colorString.play = colorString.play .. '|' .. color end end end -- update the visibility on the XML UI.setAttribute("navPanelFull", "visibility", colorString.full) UI.setAttribute("navPanelPlay", "visibility", colorString.play) UI.setAttribute("navPanelFull", "active", colorString.full ~= "") UI.setAttribute("navPanelPlay", "active", colorString.play ~= "") end --------------------------------------------------------- -- XML button creation --------------------------------------------------------- function createXmlButtons() local ui = UI.getXmlTable() ui = createXmlButtonHelper(ui, { data = fullButtonData, id = "navPanelFull", overlay = "OverlayLarge" }) ui = createXmlButtonHelper(ui, { data = playButtonData, id = "navPanelPlay", overlay = "OverlaySmall" }) UI.setXmlTable(ui) end -- XML button creation function createXmlButtonHelper(ui, params) local guid = self.getGUID() local xml = findTagWithId(ui, params.id) -- add basic image xml.children = { { tag = "image", attributes = { id = "backgroundImage", image = params.overlay } } } -- add all buttons for _, d in ipairs(params.data) do table.insert(xml.children, { tag = "button", attributes = { onClick = guid .. "/buttonClicked", id = d.id, height = d.height, width = d.width, offsetXY = d.offset, color = "rgba(0,1,0,0)" } }) end return ui end function findTagWithId(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 = findTagWithId(obj.children, id) if result then return result end end end return nil end --------------------------------------------------------- -- core functionality --------------------------------------------------------- -- handles all button clicks function buttonClicked(player, _, id) local index = tonumber(id) or "" if index == 19 then setVisibility("toggle", player.color) elseif index == 20 then setVisibility("close", player.color) elseif index == 21 then toggleSettings(player) else loadCamera(player, index) end end -- generates a table with rectangular bounds for provided objects function getDynamicViewBounds(objList) local count = 0 local totalBounds = { minX = 0, maxX = -70, minZ = 60, maxZ = -60 } for _, obj in pairs(objList) do if not obj.hasTag("CameraZoom_ignore") and not obj.hasTag("CampaignLog") then count = count + 1 local bounds = obj.getBounds() local x1 = bounds['center'][1] - bounds['size'][1] / 2 local x2 = bounds['center'][1] + bounds['size'][1] / 2 local z1 = bounds['center'][3] - bounds['size'][3] / 2 local z2 = bounds['center'][3] + bounds['size'][3] / 2 totalBounds.minX = math.min(x1, totalBounds.minX) totalBounds.maxX = math.max(x2, totalBounds.maxX) totalBounds.minZ = math.min(z1, totalBounds.minZ) totalBounds.maxZ = math.max(z2, totalBounds.maxZ) end end -- default values (mainly for play area if nothing is found) if count == 0 then totalBounds.minX = -10 totalBounds.maxX = -50 totalBounds.minZ = -20 totalBounds.maxZ = 20 end totalBounds.middleX = (totalBounds.maxX + totalBounds.minX) / 2 totalBounds.middleZ = (totalBounds.maxZ + totalBounds.minZ) / 2 totalBounds.diffX = totalBounds.maxX - totalBounds.minX totalBounds.diffZ = totalBounds.maxZ - totalBounds.minZ return totalBounds end function loadCameraFromApi(params) loadCamera(params.player, params.camera) end -- loads the specified camera for a player ---@param player tts__Player Player whose camera should be moved ---@param camera number|string If number: Index of the camera view to load | If string: Color of the playermat to swap to function loadCamera(player, camera) local lookHere, index, matColor local matColorList = { "White", "Orange", "Green", "Red" } local indexList = { White = 3, Orange = 4, Green = 5, Red = 6 } if tonumber(camera) then index = tonumber(camera) matColor = matColorList[index - 2] -- mat index 1 - 4 else index = indexList[camera] matColor = camera end -- dynamic view of the play area if index == 2 then -- search the scripting zone on the play area for objects local bounds = getDynamicViewBounds(getObjectFromGUID("a2f932").getObjects()) lookHere = { position = { bounds.middleX, 1.55, bounds.middleZ }, yaw = 90, distance = 0.8 * math.max(bounds.diffX, bounds.diffZ) + 7 } -- dynamic view of the clicked play mat elseif index >= 3 and index <= 6 then -- check if anyone (except for yourself) has claimed this color local isClaimed = false for playerColor, playerTable in pairs(claims) do if playerColor ~= player.color and playerTable[matColor] then isClaimed = true break end end -- swap to that color if it isn't claimed by someone else and it's currently unoccopied if #getSeatedPlayers() == 1 or (not isClaimed and isPlayermatAvailable(matColor)) then local newPlayerColor = playermatApi.getPlayerColor(matColor) copyVisibility({ startColor = player.color, targetColor = newPlayerColor }) player.changeColor(newPlayerColor) player = Player[newPlayerColor] end -- search on the playermat for objects local bounds = getDynamicViewBounds(playermatApi.searchAroundPlayermat(matColor)) lookHere = { position = { bounds.middleX, 0, bounds.middleZ }, yaw = playermatApi.returnRotation(matColor).y + 180, distance = 0.42 * math.max(bounds.diffX, bounds.diffZ) + 7 } end -- get default data if no dynamic view (play area or play mat) was loaded if not lookHere then lookHere = cameraData[index] lookHere.yaw = 90 end -- set pitch to default if not edited lookHere.pitch = pitch[player.color] or 75 -- update distance based on selected multiplier lookHere.distance = lookHere.distance * (distance[player.color] or 100) / 100 -- delay is to account for colorswap Wait.frames(function() player.lookAt(lookHere) end, 2) end -- helper function to check if a playermat is available for a color swap function isPlayermatAvailable(matColor) local newPlayerColor = playermatApi.getPlayerColor(matColor) for _, color in ipairs(getSeatedPlayers()) do if color == newPlayerColor then return false end end return true end --------------------------------------------------------- -- settings related functionality --------------------------------------------------------- -- claims a color for a player function claimColor(player, color) local currentState = claims[player.color][color] claims[player.color][color] = not currentState end function loadDefaultSettings(player) -- reset claims for that player for _, color in ipairs(Player.getColors()) do claims[player.color][color] = (player.color == color) end -- reset pitch/distance for that player pitch[player.color] = nil distance[player.color] = nil -- update the UI accordingly updateSettingsUI(player) end -- called by clicking a toggle function toggleSettings(player) if settingsOpenForColor == player.color then settingsOpenForColor = nil UI.setAttribute("navPanelSettings", "active", false) elseif settingsOpenForColor then broadcastToColor("Someone else is currently using the settings. Please wait and try again.", player.color, "Yellow") else settingsOpenForColor = player.color updateSettingsUI(player) UI.setAttribute("navPanelSettings", "visibility", player.color) UI.setAttribute("navPanelSettings", "active", true) end end -- called by the navigation overlay options function updatePitch(player, number) pitch[player.color] = number end -- called by the navigation overlay options function updateDistance(player, number) distance[player.color] = number end -- updates the settings UI for the provided player function updateSettingsUI(player) -- update the sliders UI.setAttribute("sliderPitch", "value", pitch[player.color] or 75) UI.setAttribute("sliderDistance", "value", distance[player.color] or 100) -- update the claims local matColorList = { "White", "Orange", "Green", "Red" } for _, matColor in pairs(matColorList) do UI.setAttribute("claim" .. matColor, "isOn", claims[player.color][matColor] or false) end end end) __bundle_register("playermat/PlayermatApi", function(require, _LOADED, __bundle_register, __bundle_modules) do local PlayermatApi = {} local guidReferenceApi = require("core/GUIDReferenceApi") local searchLib = require("util/SearchLib") local localInvestigatorPosition = { x = -1.17, y = 1, z = -0.01 } -- Convenience function to look up a mat's object by color, or get all mats. ---@param matColor string Color of the playermat - White, Orange, Green, Red or All ---@return table: Single-element if only single playermat is requested local function getMatForColor(matColor) if matColor == "All" then return guidReferenceApi.getObjectsByType("Playermat") else return { matColor = guidReferenceApi.getObjectByOwnerAndType(matColor, "Playermat") } end end -- Returns the color of the closest playermat ---@param startPos table Starting position to get the closest mat from PlayermatApi.getMatColorByPosition = function(startPos) local result, smallestDistance for matColor, mat in pairs(getMatForColor("All")) do local distance = Vector.between(startPos, mat.getPosition()):magnitude() if smallestDistance == nil or distance < smallestDistance then smallestDistance = distance result = matColor end end return result end -- Returns the color of the player's hand that is seated next to the playermat ---@param matColor string Color of the playermat - White, Orange, Green or Red (does not support "All") PlayermatApi.getPlayerColor = function(matColor) for _, mat in pairs(getMatForColor(matColor)) do return mat.getVar("playerColor") end end -- Returns the color of the playermat that owns the playercolor's hand ---@param handColor string Color of the playermat PlayermatApi.getMatColor = function(handColor) for matColor, mat in pairs(getMatForColor("All")) do local playerColor = mat.getVar("playerColor") if playerColor == handColor then return matColor end end end -- Instructs a playermat to check for DES ---@param matColor string Color of the playermat - White, Orange, Green, Red or All PlayermatApi.checkForDES = function(matColor) for _, mat in pairs(getMatForColor(matColor)) do mat.call("checkForDES") end end -- Returns if there is the card "Dream-Enhancing Serum" on the requested playermat ---@param matColor string Color of the playermat - White, Orange, Green or Red (does not support "All") ---@return boolean: whether DES is present on the playermat PlayermatApi.hasDES = function(matColor) for _, mat in pairs(getMatForColor(matColor)) do return mat.getVar("hasDES") end end -- gets the slot data for the playermat ---@param matColor string Color of the playermat - White, Orange, Green or Red (does not support "All") PlayermatApi.getSlotData = function(matColor) for _, mat in pairs(getMatForColor(matColor)) do return mat.getTable("slotData") end end -- sets the slot data for the playermat ---@param matColor string Color of the playermat - White, Orange, Green or Red (does not support "All") ---@param newSlotData table New slot data for the playermat PlayermatApi.loadSlotData = function(matColor, newSlotData) for _, mat in pairs(getMatForColor(matColor)) do mat.setTable("slotData", newSlotData) mat.call("redrawSlotSymbols") return end end -- Performs a search of the deck area of the requested playermat and returns the result as table ---@param matColor string Color of the playermat - White, Orange, Green or Red (does not support "All") PlayermatApi.getDeckAreaObjects = function(matColor) for _, mat in pairs(getMatForColor(matColor)) do return mat.call("getDeckAreaObjects") end end -- Flips the top card of the deck (useful after deck manipulation for Norman Withers) ---@param matColor string Color of the playermat - White, Orange, Green or Red (does not support "All") PlayermatApi.flipTopCardFromDeck = function(matColor) for _, mat in pairs(getMatForColor(matColor)) do return mat.call("flipTopCardFromDeck") end end -- Returns the position of the discard pile of the requested playermat ---@param matColor string Color of the playermat - White, Orange, Green or Red (does not support "All") PlayermatApi.getDiscardPosition = function(matColor) for _, mat in pairs(getMatForColor(matColor)) do return mat.call("returnGlobalDiscardPosition") end end -- Returns the position of the draw pile of the requested playermat ---@param matColor string Color of the playermat - White, Orange, Green or Red (does not support "All") PlayermatApi.getDrawPosition = function(matColor) for _, mat in pairs(getMatForColor(matColor)) do return mat.call("returnGlobalDrawPosition") end end -- Transforms a local position into a global position ---@param localPos table Local position to be transformed ---@param matColor string Color of the playermat - White, Orange, Green or Red (does not support "All") PlayermatApi.transformLocalPosition = function(localPos, matColor) for _, mat in pairs(getMatForColor(matColor)) do return mat.positionToWorld(localPos) end end -- Returns the rotation of the requested playermat ---@param matColor string Color of the playermat - White, Orange, Green or Red (does not support "All") PlayermatApi.returnRotation = function(matColor) for _, mat in pairs(getMatForColor(matColor)) do return mat.getRotation() end end -- Returns a table with spawn data (position and rotation) for a helper object ---@param matColor string Color of the playermat - White, Orange, Green, Red or All ---@param helperName string Name of the helper object PlayermatApi.getHelperSpawnData = function(matColor, helperName) local resultTable = {} local localPositionTable = { ["Hand Helper"] = {0.05, 0, -1.182}, ["Search Assistant"] = {-0.3, 0, -1.182} } for color, mat in pairs(getMatForColor(matColor)) do resultTable[color] = { position = mat.positionToWorld(localPositionTable[helperName]), rotation = mat.getRotation() } end return resultTable end -- Triggers the Upkeep for the requested playermat ---@param matColor string Color of the playermat - White, Orange, Green, Red or All ---@param playerColor string Color of the calling player (for messages) PlayermatApi.doUpkeepFromHotkey = function(matColor, playerColor) for _, mat in pairs(getMatForColor(matColor)) do mat.call("doUpkeepFromHotkey", playerColor) end end -- Handles discarding for the requested playermat for the provided list of objects ---@param matColor string Color of the playermat - White, Orange, Green or Red (does not support "All") ---@param objList table List of objects to discard PlayermatApi.discardListOfObjects = function(matColor, objList) for _, mat in pairs(getMatForColor(matColor)) do mat.call("discardListOfObjects", objList) end end -- Returns the active investigator id ---@param matColor string Color of the playermat - White, Orange, Green or Red (does not support "All") PlayermatApi.returnInvestigatorId = function(matColor) for _, mat in pairs(getMatForColor(matColor)) do return mat.getVar("activeInvestigatorId") end end -- Returns the class of the active investigator ---@param matColor string Color of the playermat - White, Orange, Green or Red (does not support "All") PlayermatApi.returnInvestigatorClass = function(matColor) for _, mat in pairs(getMatForColor(matColor)) do return mat.getVar("activeInvestigatorClass") end end -- Returns the position for encounter card drawing ---@param matColor string Color of the playermat - White, Orange, Green or Red (does not support "All") ---@param stack boolean If true, returns the leftmost position instead of the first empty from the right PlayermatApi.getEncounterCardDrawPosition = function(matColor, stack) for _, mat in pairs(getMatForColor(matColor)) do return Vector(mat.call("getEncounterCardDrawPosition", stack)) end end -- Sets the requested playermat's snap points to limit snapping to matching card types or not. If -- matchTypes is true, the main card slot snap points will only snap assets, while the -- investigator area point will only snap Investigators. If matchTypes is false, snap points will -- be reset to snap all cards. ---@param matchCardTypes boolean Whether snap points should only snap for the matching card types ---@param matColor string Color of the playermat - White, Orange, Green, Red or All PlayermatApi.setLimitSnapsByType = function(matchCardTypes, matColor) for _, mat in pairs(getMatForColor(matColor)) do mat.call("setLimitSnapsByType", matchCardTypes) end end -- Sets the requested playermat's draw 1 button to visible ---@param isDrawButtonVisible boolean Whether the draw 1 button should be visible or not ---@param matColor string Color of the playermat - White, Orange, Green, Red or All PlayermatApi.showDrawButton = function(isDrawButtonVisible, matColor) for _, mat in pairs(getMatForColor(matColor)) do mat.call("showDrawButton", isDrawButtonVisible) end end -- Shows or hides the clickable clue counter for the requested playermat ---@param showCounter boolean Whether the clickable counter should be present or not ---@param matColor string Color of the playermat - White, Orange, Green, Red or All PlayermatApi.clickableClues = function(showCounter, matColor) for _, mat in pairs(getMatForColor(matColor)) do mat.call("clickableClues", showCounter) end end -- Toggles the use of class textures for the requested playermat ---@param state boolean Whether the class texture should be used or not ---@param matColor string Color of the playermat - White, Orange, Green, Red or All PlayermatApi.useClassTexture = function(state, matColor) for _, mat in pairs(getMatForColor(matColor)) do mat.call("useClassTexture", state) end end -- Removes all clues (to the trash for tokens and counters set to 0) for the requested playermat ---@param matColor string Color of the playermat - White, Orange, Green, Red or All PlayermatApi.removeClues = function(matColor) for _, mat in pairs(getMatForColor(matColor)) do mat.call("removeClues") end end -- Reports the clue count for the requested playermat ---@param useClickableCounters boolean Controls which type of counter is getting checked PlayermatApi.getClueCount = function(useClickableCounters, matColor) local count = 0 for _, mat in pairs(getMatForColor(matColor)) do count = count + mat.call("getClueCount", useClickableCounters) end return count end -- Updates the specified owned counter ---@param matColor string Color of the playermat - White, Orange, Green, Red or All ---@param type string Counter to target ---@param newValue number Value to set the counter to ---@param modifier number If newValue is not provided, the existing value will be adjusted by this modifier PlayermatApi.updateCounter = function(matColor, type, newValue, modifier) for _, mat in pairs(getMatForColor(matColor)) do mat.call("updateCounter", { type = type, newValue = newValue, modifier = modifier }) end end -- Triggers the draw function for the specified playermat ---@param matColor string Color of the playermat - White, Orange, Green, Red or All ---@param number number Amount of cards to draw PlayermatApi.drawCardsWithReshuffle = function(matColor, number) for _, mat in pairs(getMatForColor(matColor)) do mat.call("drawCardsWithReshuffle", number) end end -- Returns the resource counter amount ---@param matColor string Color of the playermat - White, Orange, Green or Red (does not support "All") ---@param type string Counter to target PlayermatApi.getCounterValue = function(matColor, type) for _, mat in pairs(getMatForColor(matColor)) do return mat.call("getCounterValue", type) end end -- Returns a list of mat colors that have an investigator placed PlayermatApi.getUsedMatColors = function() local usedColors = {} for matColor, mat in pairs(getMatForColor("All")) do local searchPos = mat.positionToWorld(localInvestigatorPosition) local searchResult = searchLib.atPosition(searchPos, "isCardOrDeck") if #searchResult > 0 then table.insert(usedColors, matColor) end end return usedColors end -- Returns investigator name ---@param matColor string Color of the playmat - White, Orange, Green or Red (does not support "All") PlayermatApi.getInvestigatorName = function(matColor) for _, mat in pairs(getMatForColor(matColor)) do local searchPos = mat.positionToWorld(localInvestigatorPosition) local searchResult = searchLib.atPosition(searchPos, "isCardOrDeck") if #searchResult == 1 then return searchResult[1].getName() end end return "" end -- Resets the specified skill tracker to "1, 1, 1, 1" ---@param matColor string Color of the playermat - White, Orange, Green, Red or All PlayermatApi.resetSkillTracker = function(matColor) for _, mat in pairs(getMatForColor(matColor)) do mat.call("resetSkillTracker") end end -- Redraws the XML for the slot symbols based on the slotData table ---@param matColor string Color of the playermat - White, Orange, Green, Red or All PlayermatApi.redrawSlotSymbols = function(matColor) for _, mat in pairs(getMatForColor(matColor)) do mat.call("redrawSlotSymbols") end end -- Finds all objects on the playermat and associated set aside zone and returns a table ---@param matColor string Color of the playermat - White, Orange, Green, Red or All ---@param filter string Name of the filte function (see util/SearchLib) PlayermatApi.searchAroundPlayermat = function(matColor, filter) local objList = {} for _, mat in pairs(getMatForColor(matColor)) do for _, obj in ipairs(mat.call("searchAroundSelf", filter)) do table.insert(objList, obj) end end return objList end -- Discard a non-hidden card from the corresponding player's hand ---@param matColor string Color of the playermat - White, Orange, Green, Red or All PlayermatApi.doDiscardOne = function(matColor) for _, mat in pairs(getMatForColor(matColor)) do mat.call("doDiscardOne") end end -- Triggers the metadata sync for all playermats PlayermatApi.syncAllCustomizableCards = function() for _, mat in pairs(getMatForColor("All")) do mat.call("syncAllCustomizableCards") end end return PlayermatApi end end) __bundle_register("core/GUIDReferenceApi", function(require, _LOADED, __bundle_register, __bundle_modules) do local GUIDReferenceApi = {} local function getGuidHandler() return getObjectFromGUID("123456") end -- Returns the matching object ---@param owner string Parent object for this search ---@param type string Type of object to search for ---@return any: Object reference to the matching object GUIDReferenceApi.getObjectByOwnerAndType = function(owner, type) return getGuidHandler().call("getObjectByOwnerAndType", { owner = owner, type = type }) end -- Returns all matching objects as a table with references ---@param type string Type of object to search for ---@return table: List of object references to matching objects GUIDReferenceApi.getObjectsByType = function(type) return getGuidHandler().call("getObjectsByType", type) end -- Returns all matching objects as a table with references ---@param owner string Parent object for this search ---@return table: List of object references to matching objects GUIDReferenceApi.getObjectsByOwner = function(owner) return getGuidHandler().call("getObjectsByOwner", owner) end -- Sends new information to the reference handler to edit the main index ---@param owner string Parent of the object ---@param type string Type of the object ---@param guid string GUID of the object GUIDReferenceApi.editIndex = function(owner, type, guid) return getGuidHandler().call("editIndex", { owner = owner, type = type, guid = guid }) end -- Returns the owner of an object or the object it's located on ---@param object tts__GameObject Object for this search ---@return string: Parent of the object or object it's located on GUIDReferenceApi.getOwnerOfObject = function(object) return getGuidHandler().call("getOwnerOfObject", object) end return GUIDReferenceApi end end) return __bundle_require("__root")