updated Nkosi and added slot XML

This commit is contained in:
Chr1Z93 2024-04-26 01:36:58 +02:00
parent c9b8ae3a51
commit 32bf52d3b4
7 changed files with 549 additions and 472 deletions

View File

@ -1,34 +1,9 @@
[
{
"Name": "refresh",
"Type": 0,
"URL": "http://cloud-3.steamusercontent.com/ugc/1695031152736214852/EC3BBEF1A1788381A8F4C5ACB7FB27770CAF03C5/"
},
{
"Name": "close",
"Type": 0,
"URL": "http://cloud-3.steamusercontent.com/ugc/1695031152736214756/2EEB07E453A7ECF4BE5A1030A253185B37A7CDAB/"
},
{
"Name": "cthulhu",
"Type": 0,
"URL": "http://cloud-3.steamusercontent.com/ugc/1782854877010107768/BC6A97F193385D01C1A9149B68923F55A284CB2D/"
},
{
"Name": "dark-cult",
"Type": 0,
"URL": "http://cloud-3.steamusercontent.com/ugc/1782854877010108105/08594607341D6537C28A08A34CE82159025AB8DB/"
},
{
"Name": "yog-sothoth",
"Type": 0,
"URL": "http://cloud-3.steamusercontent.com/ugc/1782854877010107124/D8042D1A1B08CFB7E76488B09216B4611D85A2B9/"
},
{
"Name": "elder-sign",
"Type": 0,
"URL": "http://cloud-3.steamusercontent.com/ugc/1782854877010107442/43BC029410751208A90AE7FDEBCB587A0E9403D7/"
},
{
"Name": "devourer",
"Type": 0,
@ -55,40 +30,15 @@
"URL": "http://cloud-3.steamusercontent.com/ugc/2026086584372569912/5CB461AEAE2E59D3064D90A776EB86C46081EC78/"
},
{
"Name": "font_arkhamslim",
"Name": "font_arkhamicons",
"Type": 1,
"URL": "http://cloud-3.steamusercontent.com/ugc/2510267299454546112/8CDF773519FEC8C488569072280AC848BCC293D5/"
},
{
"Name": "font_birmingham",
"Type": 1,
"URL": "http://cloud-3.steamusercontent.com/ugc/2027213118466443497/3CF9BB9AF968D245961494CC9A151774EB9BA638/"
},
{
"Name": "font_columbus",
"Type": 1,
"URL": "http://cloud-3.steamusercontent.com/ugc/2027213118466515872/F473E4ACC75ACB6CE07457C45290B4912E0B3286/"
},
{
"Name": "font_oldremington",
"Type": 1,
"URL": "http://cloud-3.steamusercontent.com/ugc/2027213118466515932/AFCE53F1E1D9580D166F53AD9EB0D77A331D4A26/"
"URL": "http://cloud-3.steamusercontent.com/ugc/2462982115649258367/C20CC4C299A6FE5F1ECAB968E15BE590337CC019/"
},
{
"Name": "font_teutonic-arkham",
"Type": 1,
"URL": "http://cloud-3.steamusercontent.com/ugc/2027213118467703445/89328E273B4C5180BF491516CE998DE3C604E162/"
},
{
"Name": "font_uglyqua",
"Type": 1,
"URL": "http://cloud-3.steamusercontent.com/ugc/2027213118466516005/113C19D37CFFA9E554394FD5B11B32967F846A62/"
},
{
"Name": "font_chinese_fzlibian",
"Type": 1,
"URL": "http://cloud-3.steamusercontent.com/ugc/2028355502896482829/8DAB311590B97586309E66D795AC2C43D4913188/"
},
{
"Name": "header_cover",
"Type": 0,
@ -124,11 +74,6 @@
"Type": 0,
"URL": "https://i.imgur.com/6MReiEO.png"
},
{
"Name": "Inv-Roland",
"Type": 0,
"URL": "https://i.imgur.com/lx6unDY.png"
},
{
"Name": "NextArrow",
"Type": 0,
@ -139,6 +84,11 @@
"Type": 0,
"URL": "https://i.imgur.com/8qmTXwt.png"
},
{
"Name": "Inv-Roland",
"Type": 0,
"URL": "https://i.imgur.com/lx6unDY.png"
},
{
"Name": "Inv-Mandy",
"Type": 0,
@ -285,7 +235,7 @@
"URL": "http://cloud-3.steamusercontent.com/ugc/2510267932886739653/CB7AA2D73777EF5938A6E6CD664B2ABA52B6E20A/"
},
{
"Name": "token-custom",
"Name": "token-custom-token",
"Type": 0,
"URL": "http://cloud-3.steamusercontent.com/ugc/2380784374792650571/E4C2B2B69282A4EE15FE290FF6B08BEFC8FCA65C/"
}

View File

@ -57,29 +57,9 @@
},
{
"Position": {
"x": -0.631,
"y": 0.1,
"z": 0.551
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": -0.616,
"y": 0.102,
"z": 0.024
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": -0.177,
"x": 1.758,
"y": 0.101,
"z": 0.032
"z": 0.04
},
"Tags": [
"Asset"
@ -87,28 +67,18 @@
},
{
"Position": {
"x": -0.174,
"x": 1.371,
"y": 0.1,
"z": 0.038
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": 0.98,
"y": 0.099,
"z": 0.551
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": 0.212,
"y": 0.1,
"z": 0.559
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": 0.217,
"y": 0.1,
"z": 0.035
},
"Tags": [
@ -127,28 +97,8 @@
},
{
"Position": {
"x": 0.605,
"x": 0.217,
"y": 0.1,
"z": 0.555
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": 0.977,
"y": 0.099,
"z": 0.556
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": 0.98,
"y": 0.099,
"z": 0.035
},
"Tags": [
@ -157,9 +107,9 @@
},
{
"Position": {
"x": 1.371,
"y": 0.1,
"z": 0.038
"x": -0.177,
"y": 0.101,
"z": 0.032
},
"Tags": [
"Asset"
@ -167,9 +117,9 @@
},
{
"Position": {
"x": 1.371,
"y": 0.099,
"z": 0.558
"x": -0.616,
"y": 0.102,
"z": 0.024
},
"Tags": [
"Asset"
@ -187,9 +137,59 @@
},
{
"Position": {
"x": 1.758,
"y": 0.101,
"z": 0.04
"x": 1.371,
"y": 0.099,
"z": 0.558
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": 0.977,
"y": 0.099,
"z": 0.556
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": 0.605,
"y": 0.1,
"z": 0.555
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": 0.212,
"y": 0.1,
"z": 0.559
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": -0.174,
"y": 0.099,
"z": 0.551
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": -0.631,
"y": 0.1,
"z": 0.551
},
"Tags": [
"Asset"

View File

@ -57,29 +57,9 @@
},
{
"Position": {
"x": -0.631,
"y": 0.1,
"z": 0.551
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": -0.616,
"y": 0.102,
"z": 0.024
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": -0.177,
"x": 1.758,
"y": 0.101,
"z": 0.032
"z": 0.04
},
"Tags": [
"Asset"
@ -87,28 +67,18 @@
},
{
"Position": {
"x": -0.174,
"x": 1.371,
"y": 0.1,
"z": 0.038
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": 0.98,
"y": 0.099,
"z": 0.551
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": 0.212,
"y": 0.1,
"z": 0.559
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": 0.217,
"y": 0.1,
"z": 0.035
},
"Tags": [
@ -127,28 +97,8 @@
},
{
"Position": {
"x": 0.605,
"x": 0.217,
"y": 0.1,
"z": 0.555
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": 0.977,
"y": 0.099,
"z": 0.556
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": 0.98,
"y": 0.099,
"z": 0.035
},
"Tags": [
@ -157,9 +107,9 @@
},
{
"Position": {
"x": 1.371,
"y": 0.1,
"z": 0.038
"x": -0.177,
"y": 0.101,
"z": 0.032
},
"Tags": [
"Asset"
@ -167,9 +117,9 @@
},
{
"Position": {
"x": 1.371,
"y": 0.099,
"z": 0.558
"x": -0.616,
"y": 0.102,
"z": 0.024
},
"Tags": [
"Asset"
@ -187,9 +137,59 @@
},
{
"Position": {
"x": 1.758,
"y": 0.101,
"z": 0.04
"x": 1.371,
"y": 0.099,
"z": 0.558
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": 0.977,
"y": 0.099,
"z": 0.556
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": 0.605,
"y": 0.1,
"z": 0.555
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": 0.212,
"y": 0.1,
"z": 0.559
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": -0.174,
"y": 0.099,
"z": 0.551
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": -0.631,
"y": 0.1,
"z": 0.551
},
"Tags": [
"Asset"

View File

@ -57,29 +57,9 @@
},
{
"Position": {
"x": -0.631,
"y": 0.1,
"z": 0.551
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": -0.616,
"y": 0.102,
"z": 0.024
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": -0.177,
"x": 1.758,
"y": 0.101,
"z": 0.032
"z": 0.04
},
"Tags": [
"Asset"
@ -87,28 +67,18 @@
},
{
"Position": {
"x": -0.174,
"x": 1.371,
"y": 0.1,
"z": 0.038
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": 0.98,
"y": 0.099,
"z": 0.551
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": 0.212,
"y": 0.1,
"z": 0.559
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": 0.217,
"y": 0.1,
"z": 0.035
},
"Tags": [
@ -127,28 +97,8 @@
},
{
"Position": {
"x": 0.605,
"x": 0.217,
"y": 0.1,
"z": 0.555
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": 0.977,
"y": 0.099,
"z": 0.556
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": 0.98,
"y": 0.099,
"z": 0.035
},
"Tags": [
@ -157,9 +107,9 @@
},
{
"Position": {
"x": 1.371,
"y": 0.1,
"z": 0.038
"x": -0.177,
"y": 0.101,
"z": 0.032
},
"Tags": [
"Asset"
@ -167,9 +117,9 @@
},
{
"Position": {
"x": 1.371,
"y": 0.099,
"z": 0.558
"x": -0.616,
"y": 0.102,
"z": 0.024
},
"Tags": [
"Asset"
@ -187,9 +137,59 @@
},
{
"Position": {
"x": 1.758,
"y": 0.101,
"z": 0.04
"x": 1.371,
"y": 0.099,
"z": 0.558
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": 0.977,
"y": 0.099,
"z": 0.556
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": 0.605,
"y": 0.1,
"z": 0.555
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": 0.212,
"y": 0.1,
"z": 0.559
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": -0.174,
"y": 0.099,
"z": 0.551
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": -0.631,
"y": 0.1,
"z": 0.551
},
"Tags": [
"Asset"

View File

@ -57,29 +57,9 @@
},
{
"Position": {
"x": -0.631,
"y": 0.1,
"z": 0.551
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": -0.616,
"y": 0.102,
"z": 0.024
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": -0.177,
"x": 1.758,
"y": 0.101,
"z": 0.032
"z": 0.04
},
"Tags": [
"Asset"
@ -87,28 +67,18 @@
},
{
"Position": {
"x": -0.174,
"x": 1.371,
"y": 0.1,
"z": 0.038
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": 0.98,
"y": 0.099,
"z": 0.551
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": 0.212,
"y": 0.1,
"z": 0.559
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": 0.217,
"y": 0.1,
"z": 0.035
},
"Tags": [
@ -127,28 +97,8 @@
},
{
"Position": {
"x": 0.605,
"x": 0.217,
"y": 0.1,
"z": 0.555
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": 0.977,
"y": 0.099,
"z": 0.556
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": 0.98,
"y": 0.099,
"z": 0.035
},
"Tags": [
@ -157,9 +107,9 @@
},
{
"Position": {
"x": 1.371,
"y": 0.1,
"z": 0.038
"x": -0.177,
"y": 0.101,
"z": 0.032
},
"Tags": [
"Asset"
@ -167,9 +117,9 @@
},
{
"Position": {
"x": 1.371,
"y": 0.099,
"z": 0.558
"x": -0.616,
"y": 0.102,
"z": 0.024
},
"Tags": [
"Asset"
@ -187,9 +137,59 @@
},
{
"Position": {
"x": 1.758,
"y": 0.101,
"z": 0.04
"x": 1.371,
"y": 0.099,
"z": 0.558
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": 0.977,
"y": 0.099,
"z": 0.556
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": 0.605,
"y": 0.1,
"z": 0.555
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": 0.212,
"y": 0.1,
"z": 0.559
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": -0.174,
"y": 0.099,
"z": 0.551
},
"Tags": [
"Asset"
]
},
{
"Position": {
"x": -0.631,
"y": 0.1,
"z": 0.551
},
"Tags": [
"Asset"

View File

@ -2,28 +2,17 @@ local chaosBagApi = require("chaosbag/ChaosBagApi")
local guidReferenceApi = require("core/GUIDReferenceApi")
local playmatApi = require("playermat/PlaymatApi")
local tokenNames = {
"Skull",
"Cultist",
"Tablet",
"Elder Thing",
"Auto-fail",
"Bless",
"Curse",
"Frost",
"Custom Token"
}
local dataForToken = {
["Skull"] = { color = "#4A0400E6", icon = "token-skull" },
["Cultist"] = { color = "#173B0BE6", icon = "token-cultist" },
["Tablet"] = { color = "#1D2238E6", icon = "token-tablet" },
["Elder Thing"] = { color = "#4D2331E6", icon = "token-elder-thing" },
["Auto-fail"] = { color = "#9B0004E6", icon = "token-auto-fail" },
["Bless"] = { color = "#9D702CE6", icon = "token-bless" },
["Curse"] = { color = "#633A84E6", icon = "token-curse" },
["Frost"] = { color = "#404450E6", icon = "token-frost" },
[""] = { color = "#77674DE6", icon = "token-custom" }
-- XML background color for each token
local tokenColor = {
["Skull"] = "#4A0400E6",
["Cultist"] = "#173B0BE6",
["Tablet"] = "#1D2238E6",
["Elder Thing"] = "#4D2331E6",
["Auto-fail"] = "#9B0004E6",
["Bless"] = "#9D702CE6",
["Curse"] = "#633A84E6",
["Frost"] = "#404450E6",
[""] = "#77674DE6"
}
local sigil
@ -36,13 +25,18 @@ function onLoad(savedData)
self.addContextMenuItem("Enable Helper", chooseSigil)
sigil = JSON.decode(savedData)
if sigil and sigil ~= nil then
makeXMLButton(sigil)
makeXMLButton()
self.clearContextMenu()
self.addContextMenuItem("Clear Helper", deleteButtons)
end
end
function makeXMLButton(chosenToken)
function makeXMLButton()
-- get name of the icon for the sigil ("token" + lowercase name without space characters)
local sigilName = Global.call("getReadableTokenName", sigil)
local iconName = "token-" .. string.lower(sigilName)
iconName = iconName:gsub("%s", "-")
self.UI.setXmlTable({
{
tag = "Button",
@ -55,15 +49,15 @@ function makeXMLButton(chosenToken)
padding = "50 50 50 50",
font = "font_teutonic-arkham",
fontSize = 300,
iconWidth = 400,
iconWidth = "400",
iconAlignment = "Right",
onClick = "resolveSigil",
id = sigil,
icon = dataForToken[sigil].icon,
color = dataForToken[sigil].color,
textColor = "White",
icon = iconName,
color = tokenColor[sigil],
textColor = "White"
},
value = "Resolve",
value = "Resolve"
}
}
)
@ -73,10 +67,18 @@ end
function chooseSigil(playerColor)
self.clearContextMenu()
self.addContextMenuItem("Clear Helper", deleteButtons)
Player[playerColor].showOptionsDialog("Choose Sigil", tokenNames, 1,
-- get list of readable names
local readableNames = {}
for token, _ in pairs(tokenColor) do
table.insert(readableNames, Global.call("getReadableTokenName", token))
end
-- prompt player to choose sigil
Player[playerColor].showOptionsDialog("Choose Sigil", readableNames, 1,
function(chosenToken)
sigil = Global.call("getChaosTokenName", chosenToken)
makeXMLButton(sigil)
makeXMLButton()
end
)
end
@ -92,14 +94,16 @@ end
function resolveSigil()
local tokensInPlay = chaosBagApi.getTokensInPlay()
local chaosbag = chaosBagApi.findChaosBag()
local match = false
for i, obj in ipairs(chaosbag.getObjects()) do
for _, obj in ipairs(chaosbag.getObjects()) do
-- if there are any sigils in the bag
if obj.nickname == sigil then
match = true
break
end
end
if not match then
broadcastToAll(Global.call("getReadableTokenName", sigil) .. " not found in chaos bag", "Red")
return
@ -107,8 +111,11 @@ function resolveSigil()
local matchingSymbolsInPlay = {}
for j, token in ipairs(tokensInPlay) do
if (token.getName() == "Cultist" or token.getName() == "Elder Thing" or token.getName() == "Tablet") and token.getName() ~= sigil then
for _, token in ipairs(tokensInPlay) do
if (token.getName() == "Cultist"
or token.getName() == "Tablet"
or token.getName() == "Elder Thing")
and token.getName() ~= sigil then
matchingSymbolsInPlay[#matchingSymbolsInPlay + 1] = token
end
end
@ -117,7 +124,7 @@ function resolveSigil()
broadcastToAll("No eligible symbol token found in play area", "Red")
return
elseif #matchingSymbolsInPlay > 1 then
for j, token in ipairs(matchingSymbolsInPlay) do
for _, token in ipairs(matchingSymbolsInPlay) do
-- draw XML to return token to bag
token.UI.setXmlTable({
{
@ -131,7 +138,7 @@ function resolveSigil()
rotation = "0 0 180",
position = "0 0 -15",
color = "rgba(0,0,0,0.7)",
onClick = self.getGUID() .. "/drawSigil(" .. token.getGUID() .. ")",
onClick = self.getGUID() .. "/drawSigil(" .. token.getGUID() .. ")"
},
children = {
{
@ -140,18 +147,18 @@ function resolveSigil()
fontSize = "100",
font = "font_teutonic-arkham",
color = "#ffffff",
text = "Nkosi",
},
text = "Nkosi"
}
},
{
tag = "Text",
attributes = {
fontSize = "125",
font = "font_arkhamslim",
font = "font_arkhamicons",
color = "#ffffff",
text = "U",
},
},
text = "u"
}
}
}
}
})
@ -162,15 +169,17 @@ function resolveSigil()
end
function drawSigil(player, tokenGUID)
returnedToken = getObjectFromGUID(tokenGUID)
local returnedToken = getObjectFromGUID(tokenGUID)
local matColor = playmatApi.getMatColorByPosition(returnedToken.getPosition())
local mat = guidReferenceApi.getObjectByOwnerAndType(matColor, "Playermat")
chaosBagApi.drawChaosToken(mat, true, sigil, _, returnedToken)
local tokensInPlay = chaosBagApi.getTokensInPlay()
for j, returnedToken in ipairs(tokensInPlay) do
if returnedToken.getName() == "Cultist" or returnedToken.getName() == "Elder Thing" or returnedToken.getName() == "Tablet" then
returnedToken.UI.setXml("")
-- remove XML from tokens in play
for _, token in ipairs(chaosBagApi.getTokensInPlay()) do
if token.getName() == "Cultist"
or token.getName() == "Tablet"
or token.getName() == "Elder Thing" then
token.UI.setXml("")
end
end
end

View File

@ -1,22 +1,22 @@
local chaosBagApi = require("chaosbag/ChaosBagApi")
local deckLib = require("util/DeckLib")
local guidReferenceApi = require("core/GUIDReferenceApi")
local mythosAreaApi = require("core/MythosAreaApi")
local navigationOverlayApi = require("core/NavigationOverlayApi")
local searchLib = require("util/SearchLib")
local tokenChecker = require("core/token/TokenChecker")
local tokenManager = require("core/token/TokenManager")
local chaosBagApi = require("chaosbag/ChaosBagApi")
local deckLib = require("util/DeckLib")
local guidReferenceApi = require("core/GUIDReferenceApi")
local mythosAreaApi = require("core/MythosAreaApi")
local navigationOverlayApi = require("core/NavigationOverlayApi")
local searchLib = require("util/SearchLib")
local tokenChecker = require("core/token/TokenChecker")
local tokenManager = require("core/token/TokenManager")
-- we use this to turn off collision handling until onLoad() is complete
local collisionEnabled = false
local collisionEnabled = false
-- x-Values for discard buttons
local DISCARD_BUTTON_OFFSETS = {-1.365, -0.91, -0.455, 0, 0.455, 0.91}
local DISCARD_BUTTON_OFFSETS = { -1.365, -0.91, -0.455, 0, 0.455, 0.91 }
local SEARCH_AROUND_SELF_X_BUFFER = 8
-- defined areas for object searching
local MAIN_PLAY_AREA = {
local MAIN_PLAY_AREA = {
upperLeft = {
x = 1.98,
z = 0.736
@ -26,7 +26,7 @@ local MAIN_PLAY_AREA = {
z = -0.39
}
}
local INVESTIGATOR_AREA = {
local INVESTIGATOR_AREA = {
upperLeft = {
x = -1.084,
z = 0.06517
@ -36,7 +36,7 @@ local INVESTIGATOR_AREA = {
z = -0.0805
}
}
local THREAT_AREA = {
local THREAT_AREA = {
upperLeft = {
x = 1.53,
z = -0.34
@ -46,7 +46,7 @@ local THREAT_AREA = {
z = -0.92
}
}
local DECK_DISCARD_AREA = {
local DECK_DISCARD_AREA = {
upperLeft = {
x = -1.62,
z = 0.855
@ -68,24 +68,24 @@ local DECK_DISCARD_AREA = {
}
-- local position of draw and discard pile
local DRAW_DECK_POSITION = { x = -1.82, y = 0.1, z = 0 }
local DISCARD_PILE_POSITION = { x = -1.82, y = 0.1, z = 0.61 }
local DRAW_DECK_POSITION = { x = -1.82, y = 0.1, z = 0 }
local DISCARD_PILE_POSITION = { x = -1.82, y = 0.1, z = 0.61 }
-- global position of encounter discard pile
local ENCOUNTER_DISCARD_POSITION = { x = -3.85, y = 1.5, z = 10.38}
local ENCOUNTER_DISCARD_POSITION = { x = -3.85, y = 1.5, z = 10.38 }
-- global variable so it can be reset by the Clean Up Helper
activeInvestigatorId = "00000"
activeInvestigatorId = "00000"
-- table of type-object reference pairs of all owned objects
local ownedObjects = {}
local matColor = self.getMemo()
local ownedObjects = {}
local matColor = self.getMemo()
-- variable to track the status of the "Show Draw Button" option
local isDrawButtonVisible = false
local isDrawButtonVisible = false
-- global variable to report "Dream-Enhancing Serum" status
isDES = false
isDES = false
function onSave()
return JSON.encode({
@ -116,8 +116,8 @@ function onLoad(savedData)
self.createButton({
click_function = "drawEncounterCard",
function_owner = self,
position = {-1.84, 0, -0.65},
rotation = {0, 80, 0},
position = { -1.84, 0, -0.65 },
rotation = { 0, 80, 0 },
width = 265,
height = 190
})
@ -125,8 +125,8 @@ function onLoad(savedData)
self.createButton({
click_function = "drawChaosTokenButton",
function_owner = self,
position = {1.85, 0, -0.74},
rotation = {0, -45, 0},
position = { 1.85, 0, -0.74 },
rotation = { 0, -45, 0 },
width = 135,
height = 135
})
@ -135,8 +135,19 @@ function onLoad(savedData)
label = "Upkeep",
click_function = "doUpkeep",
function_owner = self,
position = {1.84, 0.1, -0.44},
scale = {0.12, 0.12, 0.12},
position = { 1.84, 0.1, -0.44 },
scale = { 0.12, 0.12, 0.12 },
width = 800,
height = 280,
font_size = 180
})
self.createButton({
label = "Edit Slots",
click_function = "editSlots",
function_owner = self,
position = { 1.84, 0.1, 0.84 },
scale = { 0.12, 0.12, 0.12 },
width = 800,
height = 280,
font_size = 180
@ -145,6 +156,7 @@ function onLoad(savedData)
showDrawButton(isDrawButtonVisible)
math.randomseed(os.time())
Wait.time(function() collisionEnabled = true end, 0.1)
updateSlots()
end
---------------------------------------------------------
@ -178,7 +190,7 @@ function searchDeckAndDiscardArea(filter)
local scale = self.getScale()
local size = {
x = DECK_DISCARD_AREA.size.x * scale.x,
y = DECK_DISCARD_AREA.size.y,
y = DECK_DISCARD_AREA.size.y,
z = DECK_DISCARD_AREA.size.z * scale.z
}
return searchArea(pos, size, filter)
@ -192,7 +204,7 @@ end
---@param num number Initial value
---@param numDecimalPlaces number Amount of decimal places
function round(num, numDecimalPlaces)
local mult = 10^(numDecimalPlaces or 0)
local mult = 10 ^ (numDecimalPlaces or 0)
return math.floor(num * mult + 0.5) / mult
end
@ -208,12 +220,12 @@ function discardListOfObjects(objList)
if obj.hasTag("PlayerCard") then
deckLib.placeOrMergeIntoDeck(obj, returnGlobalDiscardPosition(), self.getRotation())
else
deckLib.placeOrMergeIntoDeck(obj, ENCOUNTER_DISCARD_POSITION, {x = 0, y = -90, z = 0})
deckLib.placeOrMergeIntoDeck(obj, ENCOUNTER_DISCARD_POSITION, { x = 0, y = -90, z = 0 })
end
-- put chaos tokens back into bag (e.g. Unrelenting)
-- put chaos tokens back into bag (e.g. Unrelenting)
elseif tokenChecker.isChaosToken(obj) then
chaosBagApi.returnChaosTokenToBag(obj)
-- don't touch locked objects (like the table etc.) or specific objects (like key tokens)
-- don't touch locked objects (like the table etc.) or specific objects (like key tokens)
elseif not obj.getLock() and not obj.hasTag("DontDiscard") then
ownedObjects.Trash.putObject(obj)
end
@ -222,11 +234,11 @@ end
-- build a discard button to discard from searchPosition (number must be unique)
function makeDiscardButton(xValue, number)
local position = { xValue, 0.1, -0.94}
local searchPosition = {-position[1], position[2], position[3] + 0.32}
local position = { xValue, 0.1, -0.94 }
local searchPosition = { -position[1], position[2], position[3] + 0.32 }
local handlerName = 'handler' .. number
self.setVar(handlerName, function()
local cardSizeSearch = {2, 1, 3.2}
local cardSizeSearch = { 2, 1, 3.2 }
local globalSearchPosition = self.positionToWorld(searchPosition)
local searchResult = searchArea(globalSearchPosition, cardSizeSearch)
return discardListOfObjects(searchResult)
@ -236,7 +248,7 @@ function makeDiscardButton(xValue, number)
click_function = handlerName,
function_owner = self,
position = position,
scale = {0.12, 0.12, 0.12},
scale = { 0.12, 0.12, 0.12 },
width = 900,
height = 350,
font_size = 220
@ -286,7 +298,7 @@ function doUpkeep(_, clickedByColor, isRightClick)
-- set correct rotation for face-down cards
rot.z = obj.is_face_down and 180 or 0
obj.setRotation({rot.x, rot.y + yRotDiff, rot.z})
obj.setRotation({ rot.x, rot.y + yRotDiff, rot.z })
end
if cardMetadata.id == "08031" then
forcedLearning = true
@ -294,7 +306,7 @@ function doUpkeep(_, clickedByColor, isRightClick)
if cardMetadata.uses ~= nil then
tokenManager.maybeReplenishCard(obj, cardMetadata.uses, self)
end
-- check decks for forced learning
-- check decks for forced learning
elseif obj.type == "Deck" and forcedLearning == false then
for _, deepObj in ipairs(obj.getObjects()) do
local cardMetadata = JSON.decode(deepObj.gm_notes) or {}
@ -319,16 +331,18 @@ function doUpkeep(_, clickedByColor, isRightClick)
-- gain a resource (or two if playing Jenny Barnes)
if string.match(activeInvestigatorId, "%d%d%d%d%d") == "02003" then
updateCounter({type = "ResourceCounter", modifier = 2})
updateCounter({ type = "ResourceCounter", modifier = 2 })
printToColor("Gaining 2 resources (Jenny)", messageColor)
else
updateCounter({type = "ResourceCounter", modifier = 1})
updateCounter({ type = "ResourceCounter", modifier = 1 })
end
-- draw a card (with handling for Patrice and Forced Learning)
if activeInvestigatorId == "06005" then
if forcedLearning then
printToColor("Wow, did you really take 'Versatile' to play Patrice with 'Forced Learning'? Choose which draw replacement effect takes priority and draw cards accordingly.", messageColor)
printToColor(
"Wow, did you really take 'Versatile' to play Patrice with 'Forced Learning'? Choose which draw replacement effect takes priority and draw cards accordingly.",
messageColor)
else
local handSize = #Player[playerColor].getHandObjects()
if handSize < 5 then
@ -421,7 +435,7 @@ function getDeckAreaObjects()
for _, object in ipairs(searchDeckAndDiscardArea("isCardOrDeck")) do
if self.positionToLocal(object.getPosition()).z > 0.5 then
deckAreaObjects.discard = object
-- Norman Withers handling
-- Norman Withers handling
elseif object.type == "Card" and not object.is_face_down then
deckAreaObjects.topCard = object
else
@ -497,6 +511,111 @@ function doDiscardOne()
end
end
---------------------------------------------------------
-- playmat slot modifying
---------------------------------------------------------
-- translation table for slot names to characters for special font
local slotFontCharacter = {
["any"] = "",
["Accessory"] = "C",
["Ally"] = "E",
["Arcane"] = "G",
["Body"] = "K",
["Hand (right)"] = "M",
["Hand (left)"] = "M",
["Hand x2"] = "N",
["Tarot"] = "A"
}
-- top left to bottom right
local slotData = {
"any",
"any",
"any",
"Tarot",
"Hand (left)",
"Hand (right)",
"Ally",
-- 2nd row
"any",
"any",
"any",
"Accessory",
"Arcane",
"Arcane",
"Body"
}
function updateSlots()
local xml = {}
local snapId = 0
for _, snap in ipairs(self.getSnapPoints()) do
if inArea(snap.position, MAIN_PLAY_AREA) then
snapId = snapId + 1
local slotName = slotData[snapId]
local slotRotation = "0 0 180"
if slotName == "Hand (left)" then
slotRotation = "0 180 180"
end
-- increased coordinates to account for scale (0.1)
local x = snap.position.x * 100
local y = snap.position.z * 100
local slotXML = {
tag = "Panel",
attributes = {
scale = "0.1 0.1 1",
width="150",
height="150",
rotation = slotRotation,
position = x .. " " .. y .. " -11"
},
children = {
{
tag = "Text",
attributes = {
id = "slot" .. snapId,
fontSize = "145",
font = "font_arkhamicons",
color = "#414141CB",
text = slotFontCharacter[slotName]
}
}
}
}
table.insert(xml, slotXML)
end
end
self.UI.setXmlTable(xml)
end
function editSlots()
for i = 1, #slotData do
self.UI.setAttribute("slot" .. i, "onClick", "slotClickfunction")
end
end
function slotClickfunction(player, _, id)
local index = id:gsub("slot", "")
local slotNames = {}
for slotName, _ in pairs(slotFontCharacter) do
table.insert(slotNames, slotName)
end
-- prompt player to choose symbol
player.showOptionsDialog("Choose Slot Symbol", slotNames, slotData[index],
function(chosenSlot, chosenIndex)
self.UI.setAttribute(id, "text", slotFontCharacter[chosenSlot])
slotData[chosenIndex] = chosenSlot
end
)
end
---------------------------------------------------------
-- color related functions
---------------------------------------------------------
@ -558,12 +677,12 @@ function syncAllCustomizableCards()
end
function syncCustomizableMetadata(card)
local cardMetadata = JSON.decode(card.getGMNotes()) or { }
local cardMetadata = JSON.decode(card.getGMNotes()) or {}
if cardMetadata == nil or cardMetadata.customizations == nil then
return
end
for _, upgradeSheet in ipairs(searchAroundSelf("isCard")) do
local upgradeSheetMetadata = JSON.decode(upgradeSheet.getGMNotes()) or { }
local upgradeSheetMetadata = JSON.decode(upgradeSheet.getGMNotes()) or {}
if upgradeSheetMetadata.id == (cardMetadata.id .. "-c") then
for i, customization in ipairs(cardMetadata.customizations) do
if customization.replaces ~= nil and customization.replaces.uses ~= nil then
@ -584,7 +703,7 @@ function syncCustomizableMetadata(card)
end
function spawnTokensFor(object)
local extraUses = { }
local extraUses = {}
if activeInvestigatorId == "03004" then
extraUses["Charge"] = 1
end
@ -638,15 +757,15 @@ function shouldSpawnTokens(card)
-- Spawn tokens for assets and events on the main area
if inArea(localCardPos, MAIN_PLAY_AREA)
and (metadata.type == "Asset"
or metadata.type == "Event") then
or metadata.type == "Event") then
return true
end
-- Spawn tokens for all encounter types in the threat area
if inArea(localCardPos, THREAT_AREA)
and (metadata.type == "Treachery"
or metadata.type == "Enemy"
or metadata.weakness) then
or metadata.type == "Enemy"
or metadata.weakness) then
return true
end
@ -710,13 +829,13 @@ function maybeUpdateActiveInvestigator(card)
elseif activeInvestigatorId ~= "00000" then
class = "Neutral"
activeInvestigatorId = "00000"
ownedObjects.InvestigatorSkillTracker.call("updateStats", {1, 1, 1, 1})
ownedObjects.InvestigatorSkillTracker.call("updateStats", { 1, 1, 1, 1 })
else
return
end
-- change state of action tokens
local search = searchArea(self.positionToWorld({-1.1, 0.05, -0.27}), {4, 1, 1})
local search = searchArea(self.positionToWorld({ -1.1, 0.05, -0.27 }), { 4, 1, 1 })
local smallToken = nil
local STATE_TABLE = {
["Guardian"] = 1,
@ -783,12 +902,12 @@ end
-- set investigator skill tracker to "1, 1, 1, 1"
function resetSkillTracker()
local obj = ownedObjects.InvestigatorSkillTracker
if obj ~= nil then
obj.call("updateStats", { 1, 1, 1, 1 })
else
printToAll("Skill tracker for " .. matColor .. " playmat could not be found.", "Yellow")
end
local obj = ownedObjects.InvestigatorSkillTracker
if obj ~= nil then
obj.call("updateStats", { 1, 1, 1, 1 })
else
printToAll("Skill tracker for " .. matColor .. " playmat could not be found.", "Yellow")
end
end
---------------------------------------------------------
@ -819,17 +938,17 @@ function showDrawButton(visible)
-- create the "Draw 1" button
if isDrawButtonVisible then
self.createButton({
label = "Draw 1",
click_function = "doDrawOne",
function_owner = self,
position = { 1.84, 0.1, -0.36 },
scale = { 0.12, 0.12, 0.12 },
width = 800,
height = 280,
font_size = 180
label = "Draw 1",
click_function = "doDrawOne",
function_owner = self,
position = { 1.84, 0.1, -0.36 },
scale = { 0.12, 0.12, 0.12 },
width = 800,
height = 280,
font_size = 180
})
-- remove the "Draw 1" button
-- remove the "Draw 1" button
else
local buttons = self.getButtons()
for i = 1, #buttons do
@ -845,7 +964,7 @@ end
function clickableClues(showCounter)
local clickerPos = ownedObjects.ClickableClueCounter.getPosition()
local clueCount = 0
-- move clue counters
local modY = showCounter and 0.525 or -0.525
ownedObjects.ClickableClueCounter.setPosition(clickerPos + Vector(0, modY, 0))
@ -864,7 +983,7 @@ function clickableClues(showCounter)
clueCount = ownedObjects.ClickableClueCounter.getVar("val")
-- spawn clues
local pos = self.positionToWorld({x = -1.12, y = 0.05, z = 0.7})
local pos = self.positionToWorld({ x = -1.12, y = 0.05, z = 0.7 })
for i = 1, clueCount do
pos.y = pos.y + 0.045 * i
tokenManager.spawnToken(pos, "clue", self.getRotation())
@ -895,8 +1014,7 @@ end
function setLimitSnapsByType(matchTypes)
local snaps = self.getSnapPoints()
for i, snap in ipairs(snaps) do
local snapPos = snap.position
if inArea(snapPos, MAIN_PLAY_AREA) then
if inArea(snap.position, MAIN_PLAY_AREA) then
local snapTags = snaps[i].tags
if matchTypes then
if snapTags == nil then
@ -908,7 +1026,7 @@ function setLimitSnapsByType(matchTypes)
snaps[i].tags = nil
end
end
if inArea(snapPos, INVESTIGATOR_AREA) then
if inArea(snap.position, INVESTIGATOR_AREA) then
local snapTags = snaps[i].tags
if matchTypes then
if snapTags == nil then
@ -931,9 +1049,9 @@ end
---@return boolean: True if the point is in the area defined by bounds
function inArea(point, bounds)
return (point.x < bounds.upperLeft.x
and point.x > bounds.lowerRight.x
and point.z < bounds.upperLeft.z
and point.z > bounds.lowerRight.z)
and point.x > bounds.lowerRight.x
and point.z < bounds.upperLeft.z
and point.z > bounds.lowerRight.z)
end
-- called by custom data helpers to add player card data