ah_sce_unpacked/unpacked/Custom_Tile Campaign ImporterExporter 334ee3.ttslua

1077 lines
39 KiB
Plaintext
Raw Normal View History

2023-08-27 21:09:46 -04:00
-- 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("accessories/CampaignImporterExporter", function(require, _LOADED, __bundle_register, __bundle_modules)
2024-01-06 21:32:29 -05:00
local blessCurseApi = require("chaosbag/BlessCurseManagerApi")
local chaosBagApi = require("chaosbag/ChaosBagApi")
local deckImporterApi = require("arkhamdb/DeckImporterApi")
local guidReferenceApi = require("core/GUIDReferenceApi")
local optionPanelApi = require("core/OptionPanelApi")
local playAreaApi = require("core/PlayAreaApi")
local playmatApi = require("playermat/PlaymatApi")
2024-01-06 21:32:07 -05:00
2024-02-04 10:51:51 -05:00
local checkWarning = true
2023-08-27 21:09:46 -04:00
local campaignTokenData = {
2024-02-04 10:51:51 -05:00
Name = "Custom_Model_Bag",
2023-08-27 21:09:46 -04:00
Transform = {
posX = -21.25,
posY = 1.68,
posZ = 55.59,
rotX = 0,
rotY = 270,
rotZ = 0,
scaleX = 2,
scaleY = 2,
scaleZ = 2
},
Description = "SCED Importer Token",
Tags = {
"ImporterToken"
},
CustomMesh = {
MeshURL = "http://cloud-3.steamusercontent.com/ugc/943949966265929204/A38BB5D72419E6298385556D931877C0A1A55C17/",
DiffuseURL = "http://cloud-3.steamusercontent.com/ugc/254843371583188147/920981125E37B5CEB6C400E3FD353A2C428DA969/",
NormalURL = "",
ColliderURL = "http://cloud-3.steamusercontent.com/ugc/943949966265929204/A38BB5D72419E6298385556D931877C0A1A55C17/",
Convex = true,
MaterialIndex = 2,
2024-02-04 10:51:51 -05:00
TypeIndex = 6,
2023-08-27 21:09:46 -04:00
CustomShader = {
2024-01-06 21:32:29 -05:00
SpecularColor = {
r = 0.7222887,
g = 0.507659256,
b = 0.339915335
},
SpecularIntensity = 0.4,
SpecularSharpness = 7.0,
FresnelStrength = 0.0
2023-08-27 21:09:46 -04:00
},
CastShadows = true
}
}
2024-01-06 21:32:29 -05:00
local COLORS = { "White", "Orange", "Green", "Red" }
2023-08-27 21:09:46 -04:00
2024-01-06 21:32:29 -05:00
function onLoad()
2023-08-27 21:09:46 -04:00
self.createButton({
click_function = "createCampaignToken",
function_owner = self,
label = "Export",
2024-02-04 10:51:51 -05:00
tooltip = "Create a campaign save token!",
position = { x = -1, y = 0.21, z = 0 },
2023-08-27 21:09:46 -04:00
font_size = 400,
width = 1400,
height = 600,
2024-01-06 21:32:29 -05:00
scale = { 0.5, 1, 0.5 },
2023-08-27 21:09:46 -04:00
})
end
2024-02-04 10:51:51 -05:00
function onObjectLeaveContainer(container, object)
if container.hasTag("ImporterToken") and checkWarning then
broadcastToAll(
"Removing objects from the Save Coin bag will break functionality. Please replace the objects in the same order they were removed.",
Color.Yellow
)
end
end
function onObjectEnterContainer(container, object)
if container.hasTag("ImporterToken") and checkWarning then
broadcastToAll(
"Adding objects to the Save Coin bag will break functionality. Please remove the objects.",
Color.Yellow
)
end
end
2024-01-06 21:32:29 -05:00
---------------------------------------------------------
-- main import functions (split up to allow for Wait conditions)
---------------------------------------------------------
2023-08-27 21:09:46 -04:00
2024-02-04 10:51:51 -05:00
function onCollisionEnter(info)
if info.collision_object.hasTag("ImporterToken") then
importFromToken(info.collision_object)
end
end
2024-01-06 21:32:29 -05:00
2024-02-04 10:51:51 -05:00
-- Identifies import token, determines campaign box and downloads it (if needed)
function importFromToken(coin)
broadcastToAll("Campaign Import Initiated")
local importData = JSON.decode(coin.getGMNotes())
2024-01-06 21:32:29 -05:00
2024-02-04 10:51:51 -05:00
local campaignBoxGUID = importData["box"]
local campaignBox = getObjectFromGUID(campaignBoxGUID)
if not campaignBox then
broadcastToAll("Campaign Box not present on table!", Color.Red)
return
end
if campaignBox.type == "Generic" then
campaignBox.call("buttonClick_download")
2023-08-27 21:09:46 -04:00
end
2024-02-04 10:51:51 -05:00
Wait.condition(
function()
if #campaignBox.getObjects() > 0 then
placeCampaignFromToken(importData, coin)
else
restoreCampaignData(importData, coin)
end
end,
function()
local obj = getObjectFromGUID(campaignBoxGUID)
if obj == nil then
return false
else
return obj.type == "Bag" and obj.getLuaScript() ~= ""
end
end,
2,
function() broadcastToAll("Error loading campaign box") end
)
2023-08-27 21:09:46 -04:00
end
-- After box has been downloaded, places content on table
2024-02-04 10:51:51 -05:00
function placeCampaignFromToken(importData, coin)
2024-01-06 21:32:29 -05:00
getObjectFromGUID(importData["box"]).call("buttonClick_place")
2023-08-27 21:09:46 -04:00
Wait.condition(
2024-02-04 10:51:51 -05:00
function() restoreCampaignData(importData, coin) end,
2024-01-06 21:32:29 -05:00
function() return findUniqueObjectWithTag("CampaignLog") ~= nil end,
2023-08-27 21:09:46 -04:00
2,
function() broadcastToAll("Error placing campaign box") end
)
end
-- After content is placed on table, conducts all the other import operations
2024-02-04 10:51:51 -05:00
function restoreCampaignData(importData, coin)
checkWarning = false
if importData["additionalIndex"] then
guidReferenceApi.getObjectByOwnerAndType("Mythos", "AdditionalPlayerCardsBag").destruct()
if coin.type == "Bag" then
coin.takeObject({index = 0, position = importData["additionalIndex"], callback_function = function(obj) obj.setLock(true) end})
else
spawnObjectJSON({json = importData["additionalIndex"]})
end
end
2024-01-06 21:32:29 -05:00
-- destroy existing campaign log and load saved campaign log
findUniqueObjectWithTag("CampaignLog").destruct()
2024-02-04 10:51:51 -05:00
if coin.type == "Bag" then
local newLog = coin.takeObject({index = 0, position = importData["log"], callback_function = function(obj) obj.setLock(true) end})
else
spawnObjectData({ data = importData["log"] })
end
coin.destruct()
checkWarning = true
2023-08-27 21:09:46 -04:00
chaosBagApi.setChaosBagState(importData["bag"])
2024-01-06 21:32:29 -05:00
-- populate trauma values
2023-08-27 21:09:46 -04:00
if importData["trauma"] then
2024-01-06 21:32:29 -05:00
setTrauma(importData["trauma"])
2023-08-27 21:09:46 -04:00
end
2024-01-06 21:32:29 -05:00
-- populate ArkhamDB deck IDs
2023-08-27 21:09:46 -04:00
if importData["decks"] then
deckImporterApi.setUiState(importData["decks"])
end
2024-01-06 21:32:29 -05:00
2023-08-27 21:09:46 -04:00
playAreaApi.setInvestigatorCount(importData["clueCount"])
2024-01-06 21:32:29 -05:00
-- set campaign guide page
local guide = findUniqueObjectWithTag("CampaignGuide")
2023-08-27 21:09:46 -04:00
if guide then
Wait.condition(
2024-01-06 21:32:29 -05:00
-- Called after the condition function returns true
function() log("Campaign Guide import successful!") end,
-- Condition function that is called continiously until returs true or timeout is reached
function() return guide.Book.setPage(importData["guide"]) end,
2023-08-27 21:09:46 -04:00
-- Amount of time in seconds until the Wait times out
2024-02-04 10:51:51 -05:00
2,
2023-08-27 21:09:46 -04:00
-- Called if the Wait times out
2024-01-06 21:32:29 -05:00
function() log("Campaign Guide import failed!") end
2023-08-27 21:09:46 -04:00
)
end
2024-01-06 21:32:29 -05:00
Wait.time(function() optionPanelApi.loadSettings(importData["options"]) end, 0.5)
-- destroy Tour Starter token
local tourStarter = guidReferenceApi.getObjectByOwnerAndType("Mythos", "TourStarter")
2024-02-04 10:51:51 -05:00
if tourStarter then
tourStarter.destruct()
end
2024-01-06 21:32:29 -05:00
-- restore PlayArea image
2024-02-04 10:51:51 -05:00
playAreaApi.updateSurface(importData["playarea"])
2024-01-06 21:32:29 -05:00
2023-08-27 21:09:46 -04:00
broadcastToAll("Campaign successfully imported!", Color.Green)
end
-- Creates a campaign token with save data encoded into GM Notes based on the current state of the table
function createCampaignToken(_, playerColor, _)
-- find active campaign
2024-01-06 21:32:29 -05:00
local campaignBox
2023-08-27 21:09:46 -04:00
for _, obj in ipairs(getObjectsWithTag("CampaignBox")) do
if obj.type == "Bag" and #obj.getObjects() == 0 then
2024-01-06 21:32:29 -05:00
if not campaignBox then
campaignBox = obj
else
2023-08-27 21:09:46 -04:00
broadcastToAll("Multiple empty campaign box detected; delete all but one.", Color.Red)
return
end
end
end
2024-01-06 21:32:29 -05:00
if not campaignBox then
2023-08-27 21:09:46 -04:00
broadcastToAll("Campaign box with all placed objects not found!", Color.Red)
return
end
2024-01-06 21:32:29 -05:00
local campaignLog = findUniqueObjectWithTag("CampaignLog")
2023-08-27 21:09:46 -04:00
if campaignLog == nil then
broadcastToAll("Campaign log not found!", Color.Red)
return
end
2024-01-06 21:32:29 -05:00
2024-02-04 10:51:51 -05:00
local additionalIndex = guidReferenceApi.getObjectByOwnerAndType("Mythos", "AdditionalPlayerCardsBag")
local traumaValues = { }
local trauma = campaignLog.getVar("returnTrauma")
if trauma ~= nil then
2023-08-27 21:09:46 -04:00
printToAll("Trauma values found in campaign log!", "Green")
2024-02-04 10:51:51 -05:00
trauma = campaignLog.call("returnTrauma")
for _, val in ipairs(trauma) do
table.insert(traumaValues, val)
2023-08-27 21:09:46 -04:00
end
else
2024-02-04 10:51:51 -05:00
printToAll("Trauma values could not be found in campaign log!", "Yellow")
2023-08-27 21:09:46 -04:00
end
2024-01-06 21:32:29 -05:00
local campaignGuide = findUniqueObjectWithTag("CampaignGuide")
2023-08-27 21:09:46 -04:00
if campaignGuide == nil then
broadcastToAll("Campaign guide not found!", Color.Red)
return
end
2024-01-06 21:32:29 -05:00
2024-02-04 10:51:51 -05:00
-- clean up chaos tokens
blessCurseApi.removeAll(playerColor)
chaosBagApi.releaseAllSealedTokens(playerColor)
2023-08-27 21:09:46 -04:00
local campaignData = {
2024-01-06 21:32:29 -05:00
box = campaignBox.getGUID(),
2024-02-04 10:51:51 -05:00
log = campaignLog.getPosition(),
2023-08-27 21:09:46 -04:00
bag = chaosBagApi.getChaosBagState(),
trauma = traumaValues,
decks = deckImporterApi.getUiState(),
clueCount = playAreaApi.getInvestigatorCount(),
2024-02-04 10:51:51 -05:00
playarea = playAreaApi.getSurface(),
2023-08-27 21:09:46 -04:00
options = optionPanelApi.getOptions(),
2024-02-04 10:51:51 -05:00
guide = campaignGuide.Book.getPage(),
additionalIndex = additionalIndex.getPosition()
2023-08-27 21:09:46 -04:00
}
campaignTokenData.GMNotes = JSON.encode(campaignData)
2024-02-04 10:51:51 -05:00
campaignTokenData.Nickname = campaignBox.getName() .. os.date(" %b %d") .. " Save"
campaignTokenData.ContainedObjects = { }
local indexData = additionalIndex.getData()
indexData.Locked = false
table.insert(campaignTokenData.ContainedObjects, indexData)
local logData = campaignLog.getData()
logData.Locked = false
table.insert(campaignTokenData.ContainedObjects, logData)
2024-01-06 21:32:29 -05:00
spawnObjectData({ data = campaignTokenData })
2023-08-27 21:09:46 -04:00
broadcastToAll("Campaign successfully exported! Save coin object to import on a fresh save", Color.Green)
end
2024-01-06 21:32:29 -05:00
---------------------------------------------------------
2023-08-27 21:09:46 -04:00
-- helper functions
2024-01-06 21:32:29 -05:00
---------------------------------------------------------
2023-08-27 21:09:46 -04:00
2024-01-06 21:32:29 -05:00
function findUniqueObjectWithTag(tag)
local objects = getObjectsWithTag(tag)
if not objects then return end
if #objects == 1 then
return objects[1]
2023-08-27 21:09:46 -04:00
else
2024-01-06 21:32:29 -05:00
broadcastToAll("More than 1 " .. tag .. " detected; delete all but one.", Color.Red)
2023-08-27 21:09:46 -04:00
return nil
end
end
2024-01-06 21:32:29 -05:00
function setTrauma(trauma)
for i = 1, 4 do
playmatApi.updateCounter(COLORS[i], "DamageCounter", trauma[i])
playmatApi.updateCounter(COLORS[i], "HorrorCounter", trauma[i + 4])
2023-08-27 21:09:46 -04:00
end
end
2024-02-04 10:51:51 -05:00
-- gets data from campaign log if possible
function loadTrauma(log)
local trauma = log.getVar("returnTrauma")
if trauma ~= nil then
printToAll("Trauma values found in campaign log!", "Green")
trauma = log.call("returnTrauma")
return trauma
else
return nil
end
end
2024-01-06 21:32:29 -05:00
end)
2024-02-17 19:48:30 -05:00
__bundle_register("chaosbag/BlessCurseManagerApi", function(require, _LOADED, __bundle_register, __bundle_modules)
2024-01-06 21:32:29 -05:00
do
2024-02-17 19:48:30 -05:00
local BlessCurseManagerApi = {}
2024-01-06 21:32:29 -05:00
local guidReferenceApi = require("core/GUIDReferenceApi")
2023-08-27 21:09:46 -04:00
2024-02-17 19:48:30 -05:00
local function getManager()
return guidReferenceApi.getObjectByOwnerAndType("Mythos", "BlessCurseManager")
2024-02-04 10:51:51 -05:00
end
2024-02-17 19:48:30 -05:00
-- removes all taken tokens and resets the counts
BlessCurseManagerApi.removeTakenTokensAndReset = function()
local BlessCurseManager = getManager()
Wait.time(function() BlessCurseManager.call("removeTakenTokens", "Bless") end, 0.05)
Wait.time(function() BlessCurseManager.call("removeTakenTokens", "Curse") end, 0.10)
Wait.time(function() BlessCurseManager.call("doReset", "White") end, 0.15)
2024-02-04 10:51:51 -05:00
end
2024-02-17 19:48:30 -05:00
-- updates the internal count (called by cards that seal bless/curse tokens)
---@param type string Type of chaos token ("Bless" or "Curse")
---@param guid string GUID of the token
BlessCurseManagerApi.sealedToken = function(type, guid)
getManager().call("sealedToken", { type = type, guid = guid })
2024-02-04 10:51:51 -05:00
end
2024-02-17 19:48:30 -05:00
-- updates the internal count (called by cards that seal bless/curse tokens)
---@param type string Type of chaos token ("Bless" or "Curse")
---@param guid string GUID of the token
BlessCurseManagerApi.releasedToken = function(type, guid)
getManager().call("releasedToken", { type = type, guid = guid })
2024-02-04 10:51:51 -05:00
end
2024-02-17 19:48:30 -05:00
-- updates the internal count (called by cards that seal bless/curse tokens)
---@param type string Type of chaos token ("Bless" or "Curse")
---@param guid string GUID of the token
BlessCurseManagerApi.returnedToken = function(type, guid)
getManager().call("returnedToken", { type = type, guid = guid })
2024-02-04 10:51:51 -05:00
end
2024-02-17 19:48:30 -05:00
-- broadcasts the current status for bless/curse tokens
---@param playerColor string Color of the player to show the broadcast to
BlessCurseManagerApi.broadcastStatus = function(playerColor)
getManager().call("broadcastStatus", playerColor)
2024-02-04 10:51:51 -05:00
end
2024-02-17 19:48:30 -05:00
-- removes all bless / curse tokens from the chaos bag and play
---@param playerColor string Color of the player to show the broadcast to
BlessCurseManagerApi.removeAll = function(playerColor)
getManager().call("doRemove", playerColor)
2024-02-04 10:51:51 -05:00
end
2024-02-17 19:48:30 -05:00
-- adds bless / curse sealing to the hovered card
---@param playerColor string Color of the player to show the broadcast to
---@param hoveredObject tts__Object Hovered object
BlessCurseManagerApi.addBlurseSealingMenu = function(playerColor, hoveredObject)
getManager().call("addMenuOptions", { playerColor = playerColor, hoveredObject = hoveredObject })
2024-02-04 10:51:51 -05:00
end
2024-02-17 19:48:30 -05:00
return BlessCurseManagerApi
2024-01-06 21:32:29 -05:00
end
end)
__bundle_register("chaosbag/ChaosBagApi", function(require, _LOADED, __bundle_register, __bundle_modules)
do
local ChaosBagApi = {}
-- respawns the chaos bag with a new state of tokens
2024-02-17 19:48:30 -05:00
---@param tokenList table List of chaos token ids
2024-01-06 21:32:29 -05:00
ChaosBagApi.setChaosBagState = function(tokenList)
return Global.call("setChaosBagState", tokenList)
end
-- returns a Table List of chaos token ids in the current chaos bag
-- requires copying the data into a new table because TTS is weird about handling table return values in Global
ChaosBagApi.getChaosBagState = function()
local chaosBagContentsCatcher = Global.call("getChaosBagState")
local chaosBagContents = {}
for _, v in ipairs(chaosBagContentsCatcher) do
table.insert(chaosBagContents, v)
end
return chaosBagContents
end
-- checks scripting zone for chaos bag (also called by a lot of objects!)
ChaosBagApi.findChaosBag = function()
return Global.call("findChaosBag")
end
-- returns a table of object references to the tokens in play (does not include sealed tokens!)
ChaosBagApi.getTokensInPlay = function()
2024-02-04 10:51:51 -05:00
return Global.call("getChaosTokensinPlay")
2024-01-06 21:32:29 -05:00
end
-- returns all sealed tokens on cards to the chaos bag
2024-02-17 19:48:30 -05:00
---@param playerColor string Color of the player to show the broadcast to
2024-01-06 21:32:29 -05:00
ChaosBagApi.releaseAllSealedTokens = function(playerColor)
return Global.call("releaseAllSealedTokens", playerColor)
end
-- returns all drawn tokens to the chaos bag
2024-02-17 19:48:30 -05:00
ChaosBagApi.returnChaosTokens = function()
return Global.call("returnChaosTokens")
2024-01-06 21:32:29 -05:00
end
-- removes the specified chaos token from the chaos bag
2024-02-17 19:48:30 -05:00
---@param id string ID of the chaos token
2024-01-06 21:32:29 -05:00
ChaosBagApi.removeChaosToken = function(id)
return Global.call("removeChaosToken", id)
end
2024-02-04 10:51:51 -05:00
-- returns a chaos token to the bag and calls all relevant functions
2024-02-17 19:48:30 -05:00
---@param token tts__Object Chaos token to return
2024-02-04 10:51:51 -05:00
ChaosBagApi.returnChaosTokenToBag = function(token)
return Global.call("returnChaosTokenToBag", token)
end
2024-01-06 21:32:29 -05:00
-- spawns the specified chaos token and puts it into the chaos bag
2024-02-17 19:48:30 -05:00
---@param id string ID of the chaos token
2024-01-06 21:32:29 -05:00
ChaosBagApi.spawnChaosToken = function(id)
return Global.call("spawnChaosToken", id)
end
-- Checks to see if the chaos bag can be manipulated. If a player is searching the bag when tokens
-- are drawn or replaced a TTS bug can cause those tokens to vanish. Any functions which change the
-- contents of the bag should check this method before doing so.
-- This method will broadcast a message to all players if the bag is being searched.
2024-02-17 19:48:30 -05:00
---@return any canTouch True if the bag is manipulated, false if it should be blocked.
2024-01-06 21:32:29 -05:00
ChaosBagApi.canTouchChaosTokens = function()
return Global.call("canTouchChaosTokens")
end
-- called by playermats (by the "Draw chaos token" button)
2024-02-17 19:48:30 -05:00
---@param mat tts__Object Playermat that triggered this
---@param drawAdditional boolean Controls whether additional tokens should be drawn
---@param tokenType? string Name of token (e.g. "Bless") to be drawn from the bag
---@param guidToBeResolved? string GUID of the sealed token to be resolved instead of drawing a token from the bag
ChaosBagApi.drawChaosToken = function(mat, drawAdditional, tokenType, guidToBeResolved)
return Global.call("drawChaosToken", {mat = mat, drawAdditional = drawAdditional, tokenType = tokenType, guidToBeResolved = guidToBeResolved})
2024-01-06 21:32:29 -05:00
end
-- returns a Table List of chaos token ids in the current chaos bag
-- requires copying the data into a new table because TTS is weird about handling table return values in Global
ChaosBagApi.getIdUrlMap = function()
return Global.getTable("ID_URL_MAP")
end
return ChaosBagApi
end
end)
__bundle_register("core/GUIDReferenceApi", function(require, _LOADED, __bundle_register, __bundle_modules)
do
local GUIDReferenceApi = {}
local function getGuidHandler()
return getObjectFromGUID("123456")
end
2024-02-17 19:48:30 -05:00
---@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
2024-01-06 21:32:29 -05:00
GUIDReferenceApi.getObjectByOwnerAndType = function(owner, type)
return getGuidHandler().call("getObjectByOwnerAndType", { owner = owner, type = type })
end
-- returns all matching objects as a table with references
2024-02-17 19:48:30 -05:00
---@param type string Type of object to search for
---@return table: List of object references to matching objects
2024-01-06 21:32:29 -05:00
GUIDReferenceApi.getObjectsByType = function(type)
return getGuidHandler().call("getObjectsByType", type)
end
-- returns all matching objects as a table with references
2024-02-17 19:48:30 -05:00
---@param owner string Parent object for this search
---@return table: List of object references to matching objects
2024-01-06 21:32:29 -05:00
GUIDReferenceApi.getObjectsByOwner = function(owner)
return getGuidHandler().call("getObjectsByOwner", owner)
end
2024-02-04 10:51:51 -05:00
-- sends new information to the reference handler to edit the main index
2024-02-17 19:48:30 -05:00
---@param owner string Parent of the object
---@param type string Type of the object
---@param guid string GUID of the object
2024-02-04 10:51:51 -05:00
GUIDReferenceApi.editIndex = function(owner, type, guid)
return getGuidHandler().call("editIndex", {
owner = owner,
type = type,
guid = guid
})
end
2024-01-06 21:32:29 -05:00
return GUIDReferenceApi
end
end)
2024-02-17 19:48:30 -05:00
__bundle_register("core/PlayAreaApi", function(require, _LOADED, __bundle_register, __bundle_modules)
do
local PlayAreaApi = {}
local guidReferenceApi = require("core/GUIDReferenceApi")
local function getPlayArea()
return guidReferenceApi.getObjectByOwnerAndType("Mythos", "PlayArea")
end
local function getInvestigatorCounter()
return guidReferenceApi.getObjectByOwnerAndType("Mythos", "InvestigatorCounter")
end
-- Returns the current value of the investigator counter from the playmat
---@return number: Number of investigators currently set on the counter
PlayAreaApi.getInvestigatorCount = function()
return getInvestigatorCounter().getVar("val")
end
-- Updates the current value of the investigator counter from the playmat
---@param count number Number of investigators to set on the counter
PlayAreaApi.setInvestigatorCount = function(count)
getInvestigatorCounter().call("updateVal", count)
end
-- Move all contents on the play area (cards, tokens, etc) one slot in the given direction. Certain
-- fixed objects will be ignored, as will anything the player has tagged with 'displacement_excluded'
---@param playerColor string Color of the player requesting the shift for messages
PlayAreaApi.shiftContentsUp = function(playerColor)
getPlayArea().call("shiftContentsUp", playerColor)
end
PlayAreaApi.shiftContentsDown = function(playerColor)
getPlayArea().call("shiftContentsDown", playerColor)
end
PlayAreaApi.shiftContentsLeft = function(playerColor)
getPlayArea().call("shiftContentsLeft", playerColor)
end
PlayAreaApi.shiftContentsRight = function(playerColor)
getPlayArea().call("shiftContentsRight", playerColor)
end
---@param state boolean This controls whether location connections should be drawn
PlayAreaApi.setConnectionDrawState = function(state)
getPlayArea().call("setConnectionDrawState", state)
end
---@param color string Connection color to be used for location connections
PlayAreaApi.setConnectionColor = function(color)
getPlayArea().call("setConnectionColor", color)
end
-- Event to be called when the current scenario has changed
---@param scenarioName string Name of the new scenario
PlayAreaApi.onScenarioChanged = function(scenarioName)
getPlayArea().call("onScenarioChanged", scenarioName)
end
-- Sets this playmat's snap points to limit snapping to locations or not.
-- 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
PlayAreaApi.setLimitSnapsByType = function(matchCardTypes)
getPlayArea().call("setLimitSnapsByType", matchCardTypes)
end
-- Receiver for the Global tryObjectEnterContainer event. Used to clear vector lines from dragged
-- cards before they're destroyed by entering the container
PlayAreaApi.tryObjectEnterContainer = function(container, object)
getPlayArea().call("tryObjectEnterContainer", { container = container, object = object })
end
-- counts the VP on locations in the play area
PlayAreaApi.countVP = function()
return getPlayArea().call("countVP")
end
-- highlights all locations in the play area without metadata
---@param state boolean True if highlighting should be enabled
PlayAreaApi.highlightMissingData = function(state)
return getPlayArea().call("highlightMissingData", state)
end
-- highlights all locations in the play area with VP
---@param state boolean True if highlighting should be enabled
PlayAreaApi.highlightCountedVP = function(state)
return getPlayArea().call("countVP", state)
end
-- Checks if an object is in the play area (returns true or false)
PlayAreaApi.isInPlayArea = function(object)
return getPlayArea().call("isInPlayArea", object)
end
PlayAreaApi.getSurface = function()
return getPlayArea().getCustomObject().image
end
PlayAreaApi.updateSurface = function(url)
return getPlayArea().call("updateSurface", url)
end
-- Called by Custom Data Helpers to push their location data into the Data Helper. This adds the
-- data to the local token manager instance.
---@param args table Single-value array holding the GUID of the Custom Data Helper making the call
PlayAreaApi.updateLocations = function(args)
getPlayArea().call("updateLocations", args)
end
PlayAreaApi.getCustomDataHelper = function()
return getPlayArea().getVar("customDataHelper")
end
return PlayAreaApi
end
end)
__bundle_register("__root", function(require, _LOADED, __bundle_register, __bundle_modules)
require("accessories/CampaignImporterExporter")
end)
__bundle_register("arkhamdb/DeckImporterApi", function(require, _LOADED, __bundle_register, __bundle_modules)
do
local DeckImporterApi = {}
local guidReferenceApi = require("core/GUIDReferenceApi")
local function getDeckImporter()
return guidReferenceApi.getObjectByOwnerAndType("Mythos", "DeckImporter")
end
---@class uiStateTable
---@field redDeck string Deck ID to load for the red player
---@field orangeDeck string Deck ID to load for the orange player
---@field whiteDeck string Deck ID to load for the white player
---@field greenDeck string Deck ID to load for the green player
---@field privateDeck boolean True to load a private deck, false to load a public deck
---@field loadNewest boolean True if the most upgraded version of the deck should be loaded
---@field investigators boolean True if investigator cards should be spawned
-- Returns a table with the full state of the UI, including options and deck IDs.
-- This can be used to persist via onSave(), or provide values for a load operation
---@return uiStateTable uiStateTable Contains data about the current UI state
DeckImporterApi.getUiState = function()
local passthroughTable = {}
for k,v in pairs(getDeckImporter().call("getUiState")) do
passthroughTable[k] = v
end
return passthroughTable
end
-- Updates the state of the UI based on the provided table. Any values not provided will be left the same.
---@return uiStateTable uiStateTable Contains data about the current UI state
DeckImporterApi.setUiState = function(uiStateTable)
return getDeckImporter().call("setUiState", uiStateTable)
end
return DeckImporterApi
end
end)
2024-02-04 10:51:51 -05:00
__bundle_register("core/OptionPanelApi", function(require, _LOADED, __bundle_register, __bundle_modules)
do
local OptionPanelApi = {}
-- loads saved options
2024-02-17 19:48:30 -05:00
---@param options table Set a new state for the option table
2024-02-04 10:51:51 -05:00
OptionPanelApi.loadSettings = function(options)
return Global.call("loadSettings", options)
end
2024-02-17 19:48:30 -05:00
---@return any: Table of option panel state
2024-02-04 10:51:51 -05:00
OptionPanelApi.getOptions = function()
return Global.getTable("optionPanel")
end
return OptionPanelApi
end
end)
2024-01-06 21:32:29 -05:00
__bundle_register("playermat/PlaymatApi", function(require, _LOADED, __bundle_register, __bundle_modules)
do
local PlaymatApi = {}
local guidReferenceApi = require("core/GUIDReferenceApi")
2024-02-04 10:51:51 -05:00
local searchLib = require("util/SearchLib")
2024-01-06 21:32:29 -05:00
-- Convenience function to look up a mat's object by color, or get all mats.
2024-02-17 19:48:30 -05:00
---@param matColor string Color of the playmat - White, Orange, Green, Red or All
---@return table: Single-element if only single playmat is requested
2024-01-06 21:32:29 -05:00
local function getMatForColor(matColor)
if matColor == "All" then
return guidReferenceApi.getObjectsByType("Playermat")
2023-08-27 21:09:46 -04:00
else
2024-01-06 21:32:29 -05:00
return { matColor = guidReferenceApi.getObjectByOwnerAndType(matColor, "Playermat") }
end
end
-- Returns the color of the closest playmat
2024-02-17 19:48:30 -05:00
---@param startPos table Starting position to get the closest mat from
2024-01-06 21:32:29 -05:00
PlaymatApi.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 playmat
2024-02-17 19:48:30 -05:00
---@param matColor string Color of the playmat - White, Orange, Green or Red (does not support "All")
2024-01-06 21:32:29 -05:00
PlaymatApi.getPlayerColor = function(matColor)
for _, mat in pairs(getMatForColor(matColor)) do
return mat.getVar("playerColor")
end
end
-- Returns the color of the playmat that owns the playercolor's hand
2024-02-17 19:48:30 -05:00
---@param handColor string Color of the playmat
2024-01-06 21:32:29 -05:00
PlaymatApi.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
-- Returns if there is the card "Dream-Enhancing Serum" on the requested playmat
2024-02-17 19:48:30 -05:00
---@param matColor string Color of the playmat - White, Orange, Green or Red (does not support "All")
2024-01-06 21:32:29 -05:00
PlaymatApi.isDES = function(matColor)
for _, mat in pairs(getMatForColor(matColor)) do
return mat.getVar("isDES")
end
end
-- Performs a search of the deck area of the requested playmat and returns the result as table
2024-02-17 19:48:30 -05:00
---@param matColor string Color of the playmat - White, Orange, Green or Red (does not support "All")
2024-01-06 21:32:29 -05:00
PlaymatApi.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)
2024-02-17 19:48:30 -05:00
---@param matColor string Color of the playmat - White, Orange, Green or Red (does not support "All")
2024-01-06 21:32:29 -05:00
PlaymatApi.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 playmat
2024-02-17 19:48:30 -05:00
---@param matColor string Color of the playmat - White, Orange, Green or Red (does not support "All")
2024-01-06 21:32:29 -05:00
PlaymatApi.getDiscardPosition = function(matColor)
for _, mat in pairs(getMatForColor(matColor)) do
return mat.call("returnGlobalDiscardPosition")
end
end
-- Transforms a local position into a global position
2024-02-17 19:48:30 -05:00
---@param localPos table Local position to be transformed
---@param matColor string Color of the playmat - White, Orange, Green or Red (does not support "All")
2024-01-06 21:32:29 -05:00
PlaymatApi.transformLocalPosition = function(localPos, matColor)
for _, mat in pairs(getMatForColor(matColor)) do
return mat.positionToWorld(localPos)
end
end
-- Returns the rotation of the requested playmat
2024-02-17 19:48:30 -05:00
---@param matColor string Color of the playmat - White, Orange, Green or Red (does not support "All")
2024-01-06 21:32:29 -05:00
PlaymatApi.returnRotation = function(matColor)
for _, mat in pairs(getMatForColor(matColor)) do
return mat.getRotation()
end
end
2024-02-04 10:51:51 -05:00
-- Returns a table with spawn data (position and rotation) for a helper object
2024-02-17 19:48:30 -05:00
---@param matColor string Color of the playmat - White, Orange, Green, Red or All
---@param helperName string Name of the helper object
2024-02-04 10:51:51 -05:00
PlaymatApi.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
2024-01-06 21:32:29 -05:00
-- Triggers the Upkeep for the requested playmat
2024-02-17 19:48:30 -05:00
---@param matColor string Color of the playmat - White, Orange, Green, Red or All
---@param playerColor string Color of the calling player (for messages)
2024-01-06 21:32:29 -05:00
PlaymatApi.doUpkeepFromHotkey = function(matColor, playerColor)
for _, mat in pairs(getMatForColor(matColor)) do
mat.call("doUpkeepFromHotkey", playerColor)
end
end
-- Handles discarding for the requested playmat for the provided list of objects
2024-02-17 19:48:30 -05:00
---@param matColor string Color of the playmat - White, Orange, Green or Red (does not support "All")
---@param objList table List of objects to discard
2024-01-06 21:32:29 -05:00
PlaymatApi.discardListOfObjects = function(matColor, objList)
for _, mat in pairs(getMatForColor(matColor)) do
mat.call("discardListOfObjects", objList)
end
end
-- Returns the active investigator id
2024-02-17 19:48:30 -05:00
---@param matColor string Color of the playmat - White, Orange, Green or Red (does not support "All")
2024-01-06 21:32:29 -05:00
PlaymatApi.returnInvestigatorId = function(matColor)
for _, mat in pairs(getMatForColor(matColor)) do
return mat.getVar("activeInvestigatorId")
end
end
-- Sets the requested playmat'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.
2024-02-17 19:48:30 -05:00
---@param matchCardTypes boolean Whether snap points should only snap for the matching card types
---@param matColor string Color of the playmat - White, Orange, Green, Red or All
2024-01-06 21:32:29 -05:00
PlaymatApi.setLimitSnapsByType = function(matchCardTypes, matColor)
for _, mat in pairs(getMatForColor(matColor)) do
mat.call("setLimitSnapsByType", matchCardTypes)
end
end
-- Sets the requested playmat's draw 1 button to visible
2024-02-17 19:48:30 -05:00
---@param isDrawButtonVisible boolean Whether the draw 1 button should be visible or not
---@param matColor string Color of the playmat - White, Orange, Green, Red or All
2024-01-06 21:32:29 -05:00
PlaymatApi.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 playmat
2024-02-17 19:48:30 -05:00
---@param showCounter boolean Whether the clickable counter should be present or not
---@param matColor string Color of the playmat - White, Orange, Green, Red or All
2024-01-06 21:32:29 -05:00
PlaymatApi.clickableClues = function(showCounter, matColor)
for _, mat in pairs(getMatForColor(matColor)) do
mat.call("clickableClues", showCounter)
end
end
-- Removes all clues (to the trash for tokens and counters set to 0) for the requested playmat
2024-02-17 19:48:30 -05:00
---@param matColor string Color of the playmat - White, Orange, Green, Red or All
2024-01-06 21:32:29 -05:00
PlaymatApi.removeClues = function(matColor)
for _, mat in pairs(getMatForColor(matColor)) do
mat.call("removeClues")
end
end
-- Reports the clue count for the requested playmat
2024-02-17 19:48:30 -05:00
---@param useClickableCounters boolean Controls which type of counter is getting checked
2024-01-06 21:32:29 -05:00
PlaymatApi.getClueCount = function(useClickableCounters, matColor)
local count = 0
for _, mat in pairs(getMatForColor(matColor)) do
count = count + mat.call("getClueCount", useClickableCounters)
2023-08-27 21:09:46 -04:00
end
2024-01-06 21:32:29 -05:00
return count
2023-08-27 21:09:46 -04:00
end
2024-01-06 21:32:29 -05:00
-- updates the specified owned counter
2024-02-17 19:48:30 -05:00
---@param matColor string Color of the playmat - 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
2024-01-06 21:32:29 -05:00
PlaymatApi.updateCounter = function(matColor, type, newValue, modifier)
for _, mat in pairs(getMatForColor(matColor)) do
mat.call("updateCounter", { type = type, newValue = newValue, modifier = modifier })
end
end
2024-02-04 10:51:51 -05:00
-- triggers the draw function for the specified playmat
2024-02-17 19:48:30 -05:00
---@param matColor string Color of the playmat - White, Orange, Green, Red or All
---@param number number Amount of cards to draw
2024-02-04 10:51:51 -05:00
PlaymatApi.drawCardsWithReshuffle = function(matColor, number)
for _, mat in pairs(getMatForColor(matColor)) do
mat.call("drawCardsWithReshuffle", number)
end
end
2024-01-06 21:32:29 -05:00
-- returns the resource counter amount
2024-02-17 19:48:30 -05:00
---@param matColor string Color of the playmat - White, Orange, Green or Red (does not support "All")
---@param type string Counter to target
2024-01-06 21:32:29 -05:00
PlaymatApi.getCounterValue = function(matColor, type)
for _, mat in pairs(getMatForColor(matColor)) do
return mat.call("getCounterValue", type)
end
end
2024-02-04 10:51:51 -05:00
-- returns a list of mat colors that have an investigator placed
PlaymatApi.getUsedMatColors = function()
local localInvestigatorPosition = { x = -1.17, y = 1, z = -0.01 }
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
2024-01-06 21:32:29 -05:00
-- resets the specified skill tracker to "1, 1, 1, 1"
2024-02-17 19:48:30 -05:00
---@param matColor string Color of the playmat - White, Orange, Green, Red or All
2024-01-06 21:32:29 -05:00
PlaymatApi.resetSkillTracker = function(matColor)
for _, mat in pairs(getMatForColor(matColor)) do
mat.call("resetSkillTracker")
end
end
-- finds all objects on the playmat and associated set aside zone and returns a table
2024-02-17 19:48:30 -05:00
---@param matColor string Color of the playmat - White, Orange, Green, Red or All
---@param filter string Name of the filte function (see util/SearchLib)
2024-01-06 21:32:29 -05:00
PlaymatApi.searchAroundPlaymat = 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
2024-02-17 19:48:30 -05:00
---@param matColor string Color of the playmat - White, Orange, Green, Red or All
2024-01-06 21:32:29 -05:00
PlaymatApi.doDiscardOne = function(matColor)
for _, mat in pairs(getMatForColor(matColor)) do
mat.call("doDiscardOne")
end
end
-- Triggers the metadata sync for all playmats
PlaymatApi.syncAllCustomizableCards = function()
for _, mat in pairs(getMatForColor("All")) do
mat.call("syncAllCustomizableCards")
end
end
return PlaymatApi
2023-08-27 21:09:46 -04:00
end
end)
2024-02-17 19:48:30 -05:00
__bundle_register("util/SearchLib", function(require, _LOADED, __bundle_register, __bundle_modules)
2024-02-04 10:51:51 -05:00
do
2024-02-17 19:48:30 -05:00
local SearchLib = {}
local filterFunctions = {
isActionToken = function(x) return x.getDescription() == "Action Token" end,
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
}
2024-02-04 10:51:51 -05:00
2024-02-17 19:48:30 -05:00
-- 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]
2024-02-04 10:51:51 -05:00
end
2024-02-17 19:48:30 -05:00
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
})
2024-02-04 10:51:51 -05:00
2024-02-17 19:48:30 -05:00
-- filtering the result
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
2024-02-04 10:51:51 -05:00
end
2024-02-17 19:48:30 -05:00
-- searches the specified area
SearchLib.inArea = function(pos, rot, size, filter)
return returnSearchResult(pos, rot, size, filter)
2024-02-04 10:51:51 -05:00
end
2024-02-17 19:48:30 -05:00
-- searches the area on an object
SearchLib.onObject = function(obj, filter)
pos = obj.getPosition()
size = obj.getBounds().size:setAt("y", 1)
return returnSearchResult(pos, _, size, filter)
2024-02-04 10:51:51 -05:00
end
2024-02-17 19:48:30 -05:00
-- searches the specified position (a single point)
SearchLib.atPosition = function(pos, filter)
size = { 0.1, 2, 0.1 }
return returnSearchResult(pos, _, size, filter)
2024-02-04 10:51:51 -05:00
end
2024-02-17 19:48:30 -05:00
-- searches below the specified position (downwards until y = 0)
SearchLib.belowPosition = function(pos, filter)
direction = { 0, -1, 0 }
maxDistance = pos.y
return returnSearchResult(pos, _, size, filter, direction, maxDistance)
2024-02-04 10:51:51 -05:00
end
2024-02-17 19:48:30 -05:00
return SearchLib
2024-02-04 10:51:51 -05:00
end
end)
2023-08-27 21:09:46 -04:00
return __bundle_require("__root")