Merge pull request #782 from argonui/playermat-xml

Added Playermat-specific Options
This commit is contained in:
dscarpac 2024-08-02 17:20:06 -05:00 committed by GitHub
commit a1eb211a19
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 620 additions and 223 deletions

View File

@ -29,6 +29,11 @@
"Type": 0,
"URL": "https://steamusercontent-a.akamaihd.net/ugc/2026086584372569912/5CB461AEAE2E59D3064D90A776EB86C46081EC78/"
},
{
"Name": "option_gear_white",
"Type": 0,
"URL": "https://steamusercontent-a.akamaihd.net/ugc/2466368617694843180/4DB761FF58E0380A11D7367DA6C25E82A5DE1AC9/"
},
{
"Name": "option_on",
"Type": 0,
@ -39,6 +44,11 @@
"Type": 0,
"URL": "https://steamusercontent-a.akamaihd.net/ugc/2462982115668996901/D6438ECBB11DECC6DB9987589FF526FBAD4D2368/"
},
{
"Name": "option_button",
"Type": 0,
"URL": "https://steamusercontent-a.akamaihd.net/ugc/2466368617694733080/433021454606C80875A2D25480910CDFC05DC115/"
},
{
"Name": "font_arkhamicons",
"Type": 1,

View File

@ -342,6 +342,28 @@
"ImageURL": "https://steamusercontent-a.akamaihd.net/ugc/2462982115659543571/5D778EA4BC682DAE97E8F59A991BCF8CB3979B04/",
"WidthScale": 0
},
"CustomUIAsset": [
{
"Name": "option_on",
"Type": 0,
"URL": "https://steamusercontent-a.akamaihd.net/ugc/2462982115668997008/2178787B67B3C96F3419EDBAB8420E39893756BC/"
},
{
"Name": "option_off",
"Type": 0,
"URL": "https://steamusercontent-a.akamaihd.net/ugc/2462982115668996901/D6438ECBB11DECC6DB9987589FF526FBAD4D2368/"
},
{
"Name": "option_button",
"Type": 0,
"URL": "https://steamusercontent-a.akamaihd.net/ugc/2466368617694733080/433021454606C80875A2D25480910CDFC05DC115/"
},
{
"Name": "option_gear_white",
"Type": 0,
"URL": "https://steamusercontent-a.akamaihd.net/ugc/2466368617694843180/4DB761FF58E0380A11D7367DA6C25E82A5DE1AC9/"
}
],
"Description": "",
"DragSelectable": true,
"GMNotes": "",

View File

@ -1,8 +1,14 @@
{
"activeInvestigatorClass": "Neutral",
"activeInvestigatorId": "00000",
"activeInvestigatorData": {
"class": "Neutral",
"id": "00000"
},
"isClassTextureEnabled": true,
"isDrawButtonVisible": false,
"optionPanelData": {
"slotEditing": false
},
"optionPanelVisibility": "",
"playerColor": "White",
"slotData": [
"any",

View File

@ -342,6 +342,28 @@
"ImageURL": "https://steamusercontent-a.akamaihd.net/ugc/2462982115659543571/5D778EA4BC682DAE97E8F59A991BCF8CB3979B04/",
"WidthScale": 0
},
"CustomUIAsset": [
{
"Name": "option_on",
"Type": 0,
"URL": "https://steamusercontent-a.akamaihd.net/ugc/2462982115668997008/2178787B67B3C96F3419EDBAB8420E39893756BC/"
},
{
"Name": "option_off",
"Type": 0,
"URL": "https://steamusercontent-a.akamaihd.net/ugc/2462982115668996901/D6438ECBB11DECC6DB9987589FF526FBAD4D2368/"
},
{
"Name": "option_button",
"Type": 0,
"URL": "https://steamusercontent-a.akamaihd.net/ugc/2466368617694733080/433021454606C80875A2D25480910CDFC05DC115/"
},
{
"Name": "option_gear_white",
"Type": 0,
"URL": "https://steamusercontent-a.akamaihd.net/ugc/2466368617694843180/4DB761FF58E0380A11D7367DA6C25E82A5DE1AC9/"
}
],
"Description": "",
"DragSelectable": true,
"GMNotes": "",

View File

@ -1,8 +1,14 @@
{
"activeInvestigatorClass": "Neutral",
"activeInvestigatorId": "00000",
"activeInvestigatorData": {
"class": "Neutral",
"id": "00000"
},
"isClassTextureEnabled": true,
"isDrawButtonVisible": false,
"optionPanelData": {
"slotEditing": false
},
"optionPanelVisibility": "",
"playerColor": "Orange",
"slotData": [
"any",

View File

@ -342,6 +342,28 @@
"ImageURL": "https://steamusercontent-a.akamaihd.net/ugc/2462982115659543571/5D778EA4BC682DAE97E8F59A991BCF8CB3979B04/",
"WidthScale": 0
},
"CustomUIAsset": [
{
"Name": "option_on",
"Type": 0,
"URL": "https://steamusercontent-a.akamaihd.net/ugc/2462982115668997008/2178787B67B3C96F3419EDBAB8420E39893756BC/"
},
{
"Name": "option_off",
"Type": 0,
"URL": "https://steamusercontent-a.akamaihd.net/ugc/2462982115668996901/D6438ECBB11DECC6DB9987589FF526FBAD4D2368/"
},
{
"Name": "option_button",
"Type": 0,
"URL": "https://steamusercontent-a.akamaihd.net/ugc/2466368617694733080/433021454606C80875A2D25480910CDFC05DC115/"
},
{
"Name": "option_gear_white",
"Type": 0,
"URL": "https://steamusercontent-a.akamaihd.net/ugc/2466368617694843180/4DB761FF58E0380A11D7367DA6C25E82A5DE1AC9/"
}
],
"Description": "",
"DragSelectable": true,
"GMNotes": "",

View File

@ -1,8 +1,14 @@
{
"activeInvestigatorClass": "Neutral",
"activeInvestigatorId": "00000",
"activeInvestigatorData": {
"class": "Neutral",
"id": "00000"
},
"isClassTextureEnabled": true,
"isDrawButtonVisible": false,
"optionPanelData": {
"slotEditing": false
},
"optionPanelVisibility": "",
"playerColor": "Green",
"slotData": [
"any",

View File

@ -342,6 +342,28 @@
"ImageURL": "https://steamusercontent-a.akamaihd.net/ugc/2462982115659543571/5D778EA4BC682DAE97E8F59A991BCF8CB3979B04/",
"WidthScale": 0
},
"CustomUIAsset": [
{
"Name": "option_on",
"Type": 0,
"URL": "https://steamusercontent-a.akamaihd.net/ugc/2462982115668997008/2178787B67B3C96F3419EDBAB8420E39893756BC/"
},
{
"Name": "option_off",
"Type": 0,
"URL": "https://steamusercontent-a.akamaihd.net/ugc/2462982115668996901/D6438ECBB11DECC6DB9987589FF526FBAD4D2368/"
},
{
"Name": "option_button",
"Type": 0,
"URL": "https://steamusercontent-a.akamaihd.net/ugc/2466368617694733080/433021454606C80875A2D25480910CDFC05DC115/"
},
{
"Name": "option_gear_white",
"Type": 0,
"URL": "https://steamusercontent-a.akamaihd.net/ugc/2466368617694843180/4DB761FF58E0380A11D7367DA6C25E82A5DE1AC9/"
}
],
"Description": "",
"DragSelectable": true,
"GMNotes": "",

View File

@ -1,8 +1,14 @@
{
"activeInvestigatorClass": "Neutral",
"activeInvestigatorId": "00000",
"activeInvestigatorData": {
"class": "Neutral",
"id": "00000"
},
"isClassTextureEnabled": true,
"isDrawButtonVisible": false,
"optionPanelData": {
"slotEditing": false
},
"optionPanelVisibility": "",
"playerColor": "Red",
"slotData": [
"any",

View File

@ -356,12 +356,6 @@ function tidyPlayerMatCoroutine()
maybeTrashObject(obj, trash)
end
-- reset "activeInvestigatorId" and "...class"
local mat = guidReferenceApi.getObjectByOwnerAndType(color, "Playermat")
mat.setVar("activeInvestigatorId", "00000")
mat.setVar("activeInvestigatorClass", "Neutral")
mat.call("updateTexture")
coWaitFrames(5)
-- maybe respawn tekelili cards
@ -370,6 +364,10 @@ function tidyPlayerMatCoroutine()
end
end
end
-- reset "activeInvestigatorId" and "...class"
playermatApi.setActiveInvestigatorData("All", {class = "Neutral", id = "00000"})
playermatApi.updateTexture("All")
end
-- mythos area cleanup

View File

@ -11,7 +11,7 @@ function onLoad()
buttonParamaters.hover_color = "White"
buttonParamaters.label = 0
buttonParamaters.click_function = "none"
buttonParamaters.position = Vector(0, 0.11, -0.4)
buttonParamaters.position = Vector(0, 0.11, -0.2)
buttonParamaters.height = 0
buttonParamaters.width = 0
buttonParamaters.font_size = 500
@ -20,20 +20,10 @@ function onLoad()
-- index 1: button to toggle "des"
buttonParamaters.label = "DES: ✗"
buttonParamaters.position.z = 0.25
buttonParamaters.position.z = 0.45
buttonParamaters.font_size = 120
self.createButton(buttonParamaters)
-- index 2: button to discard a card
buttonParamaters.label = "Discard Random Card"
buttonParamaters.click_function = "discardRandom"
buttonParamaters.position.z = 0.7
buttonParamaters.height = 175
buttonParamaters.width = 900
buttonParamaters.font_size = 90
buttonParamaters.font_color = "Black"
self.createButton(buttonParamaters)
-- make sure this part executes after the playermats are loaded
Wait.time(function()
updateColors()
@ -117,8 +107,3 @@ function updateValue()
-- update button label and color
self.editButton({ index = 0, font_color = hasDES and "Green" or "White", label = size })
end
-- discards a random non-hidden card from hand
function discardRandom()
playermatApi.doDiscardOne(matColor)
end

View File

@ -267,11 +267,6 @@ function onObjectNumberTyped(hoveredObject, playerColor, number)
end
end
-- TTS event, used to redraw the playermat slot symbols after a small delay to account for the custom font loading
function onPlayerConnect()
Wait.time(function() playermatApi.redrawSlotSymbols("All") end, 0.2)
end
-- disable delete action (only applies to promoted players) and discard objects instead
function onPlayerAction(player, action, targets)
if action == Player.Action.Delete and not player.admin then
@ -1169,14 +1164,24 @@ function onClick_toggleUi(player, windowId)
changeWindowVisibilityForColor(player.color, windowId)
end
function changeWindowVisibilityForColorWrapper(params)
changeWindowVisibilityForColor(params.color, params.windowId, params.overrideState, params.owner)
end
-- toggles the visibility of the specific window for the specified color
---@param color string Player color to toggle the visibility for
---@param windowId string ID of the XML element
---@param overrideState? boolean Forcefully sets the new visibility
---@param owner? tts__Object Object that owns the XML (or nil if Global)
---@return boolean visible Returns the new state of the visibility
function changeWindowVisibilityForColor(color, windowId, overrideState)
function changeWindowVisibilityForColor(color, windowId, overrideState, owner)
local targetUi = UI
if owner then
targetUi = owner.UI
end
-- current state
local colorString = UI.getAttribute(windowId, "visibility") or ""
local colorString = targetUi.getAttribute(windowId, "visibility") or ""
-- parse the visibility string
local visible = false
@ -1215,8 +1220,8 @@ function changeWindowVisibilityForColor(color, windowId, overrideState)
newColorString = newColorString:sub(1, -2)
-- update the visibility of the XML
UI.setAttribute(windowId, "visibility", newColorString)
UI.setAttribute(windowId, "active", newColorString ~= "")
targetUi.setAttribute(windowId, "visibility", newColorString)
targetUi.setAttribute(windowId, "active", newColorString ~= "")
return visible
end
@ -1561,6 +1566,12 @@ end
-- removes a playermat and all related objects from play
---@param matColor string Color of the playermat to remove
function removePlayermat(matColor)
-- if there's a seated player, move them to grey
local handColor = playermatApi.getPlayerColor(matColor)
if Player[handColor].seated then
Player[handColor].changeColor("Grey")
end
local matObjects = guidReferenceApi.getObjectsByOwner(matColor)
if not matObjects.Playermat then return end

View File

@ -8,6 +8,31 @@ local tokenChecker = require("core/token/TokenChecker")
local tokenManager = require("core/token/TokenManager")
local tokenSpawnTrackerApi = require("core/token/TokenSpawnTrackerApi")
-- option panel data
local availableOptions = {
["PERSONAL SETTINGS"] = {
{
id = "slotEditing",
title = "Enable Slot Edit Mode",
type = "toggle"
},
{
id = "textureSelect",
title = "Select Playermat Texture",
type = "button"
},
{
id = "handColorSelect",
title = "Select Hand Color",
type = "button"
}
}
}
-- stores the value for each id
local optionPanelData = {}
optionPanelData.slotEditing = false
-- we use this to turn off collision handling until onLoad() is complete
local collisionEnabled = false
local currentlyEditingSlots = false
@ -52,7 +77,7 @@ local ENCOUNTER_DISCARD_POSITION = { x = -3.85, y = 1.5, z = 10.38 }
local buttonParameters = {
label = "Upkeep",
click_function = "doUpkeep",
tooltip = "Right-click to change color",
tooltip = "Right-click to skip resource gain and card draw",
function_owner = self,
position = { x = 1.82, y = 0.1, z = -0.45 },
scale = { 0.12, 0.12, 0.12 },
@ -94,24 +119,24 @@ local defaultSlotData = {
"any", "any", "any", "Accessory", "Arcane", "Arcane", "Body"
}
-- global variables for access
activeInvestigatorClass = "Neutral"
activeInvestigatorId = "00000"
hasDES = false
local activeInvestigatorData = {}
local hasDES = false
local isClassTextureEnabled = true
local isDrawButtonVisible = false
local optionPanelVisibility = ""
-- table of type-object reference pairs of all owned objects
local ownedObjects = {}
local matColor = self.getMemo()
function onSave()
return JSON.encode({
activeInvestigatorClass = activeInvestigatorClass,
activeInvestigatorId = activeInvestigatorId,
function updateSave()
optionPanelVisibility = self.UI.getAttribute("optionPanelMain", "visibility") or ""
self.script_state = JSON.encode({
activeInvestigatorData = activeInvestigatorData,
isClassTextureEnabled = isClassTextureEnabled,
isDrawButtonVisible = isDrawButtonVisible,
optionPanelData = optionPanelData,
optionPanelVisibility = optionPanelVisibility,
playerColor = playerColor,
slotData = slotData
})
@ -120,12 +145,16 @@ end
function onLoad(savedData)
if savedData and savedData ~= "" then
local loadedData = JSON.decode(savedData)
activeInvestigatorClass = loadedData.activeInvestigatorClass
activeInvestigatorId = loadedData.activeInvestigatorId
activeInvestigatorData = loadedData.activeInvestigatorData
isClassTextureEnabled = loadedData.isClassTextureEnabled
isDrawButtonVisible = loadedData.isDrawButtonVisible
optionPanelData = loadedData.optionPanelData
optionPanelVisibility = loadedData.optionPanelVisibility
playerColor = loadedData.playerColor
slotData = loadedData.slotData
-- make sure that edit mode starts disabled
optionPanelData.slotEditing = false
end
updateMessageColor(playerColor)
@ -161,15 +190,15 @@ function onLoad(savedData)
-- Upkeep button: can use the default parameters for this
self.createButton(buttonParameters)
-- Slot editing button: modified default data
buttonParameters.label = "Edit Slots"
buttonParameters.click_function = "toggleSlotEditing"
buttonParameters.tooltip = "Right-click to reset slot symbols"
-- Discard 1 button: modified default data
buttonParameters.label = "Discard 1"
buttonParameters.click_function = "doDiscardOne"
buttonParameters.tooltip = "Discard one random card from hand (hidden cards are excluded)."
buttonParameters.position.z = 0.92
self.createButton(buttonParameters)
showDrawButton(isDrawButtonVisible)
redrawSlotSymbols()
showDrawButton()
createXML()
math.randomseed(os.time())
Wait.time(function() collisionEnabled = true end, 0.1)
end
@ -226,18 +255,6 @@ function round(num, numDecimalPlaces)
return math.floor(num * mult + 0.5) / mult
end
-- edits the label of a button
---@param oldLabel string Old label of the button
---@param newLabel string New label of the button
function editButtonLabel(oldLabel, newLabel)
local buttons = self.getButtons()
for i = 1, #buttons do
if buttons[i].label == oldLabel then
self.editButton({ index = buttons[i].index, label = newLabel })
end
end
end
-- updates the internal "messageColor" which is used for print/broadcast statements if no player is seated
---@param clickedByColor string Colorstring of player who clicked a button
function updateMessageColor(clickedByColor)
@ -245,7 +262,7 @@ function updateMessageColor(clickedByColor)
end
---------------------------------------------------------
-- Discard buttons
-- Discard buttons (threat area)
---------------------------------------------------------
-- handles discarding for a list of objects
@ -303,11 +320,6 @@ function doUpkeepFromHotkey(clickedByColor)
end
function doUpkeep(_, clickedByColor, isRightClick)
if isRightClick then
changeColor(clickedByColor)
return
end
updateMessageColor(clickedByColor)
-- unexhaust cards in play zone, flip action tokens and find Forced Learning / Dream-Enhancing Serum
@ -363,7 +375,7 @@ function doUpkeep(_, clickedByColor, isRightClick)
-- flip investigator mini-card and summoned servitor mini-card
-- (all characters allowed to account for custom IDs - e.g. 'Z0000' for TTS Zoop generated IDs)
local miniId = string.match(activeInvestigatorId, ".....") .. "-m"
local miniId = string.match(activeInvestigatorData.id, ".....") .. "-m"
for _, obj in ipairs(getObjects()) do
if obj.type == "Card" and obj.is_face_down then
local notes = JSON.decode(obj.getGMNotes())
@ -373,8 +385,13 @@ function doUpkeep(_, clickedByColor, isRightClick)
end
end
if isRightClick then
printToColor("Skipping resource gain and card draw", messageColor)
return
end
-- gain a resource (or two if playing non-parallel Jenny Barnes)
if activeInvestigatorId == "02003" or activeInvestigatorId == "02003-pb" then
if activeInvestigatorData.id == "02003" or activeInvestigatorData.id == "02003-pb" then
updateCounter({ type = "ResourceCounter", modifier = 2 })
printToColor("Gaining 2 resources (Jenny)", messageColor)
else
@ -382,7 +399,7 @@ function doUpkeep(_, clickedByColor, isRightClick)
end
-- draw a card (with handling for Patrice and Forced Learning)
if activeInvestigatorId == "06005" then
if activeInvestigatorData.id == "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)
@ -419,7 +436,7 @@ function doUpkeep(_, clickedByColor, isRightClick)
elseif forcedLearning then
printToColor("Drawing 2 cards, discard 1 (Forced Learning)", messageColor)
drawCardsWithReshuffle(2)
elseif activeInvestigatorId == "89001" then
elseif activeInvestigatorData.id == "89001" then
printToColor("Drawing 2 cards (Subject 5U-21)", messageColor)
drawCardsWithReshuffle(2)
else
@ -596,9 +613,12 @@ function doDiscardOne()
-- get a random eligible card (from the "choices" table)
local num = math.random(1, #choices)
deckLib.placeOrMergeIntoDeck(hand[choices[num]], returnGlobalDiscardPosition(), self.getRotation())
broadcastToAll(getColoredName(playerColor) .. " randomly discarded card "
.. choices[num] .. "/" .. #hand .. ".", "White")
local card = hand[choices[num]]
local cardName = card.getName()
local cardId = choices[num] .. "/" .. #hand
deckLib.placeOrMergeIntoDeck(card, returnGlobalDiscardPosition(), self.getRotation())
broadcastToAll(getColoredName(playerColor) .. " randomly discarded " .. cardName " (" .. cardId .. ").", "White")
end
end
@ -633,15 +653,16 @@ function checkForDES()
end
---------------------------------------------------------
-- slot symbol displaying
-- XML creation and modifying
---------------------------------------------------------
-- this will redraw the XML for the slot symbols based on the slotData table
function redrawSlotSymbols()
-- initializes the XML
function createXML()
local xml = {}
local snapId = 0
-- create a panel for each slot symbol
-- use the snap point positions in the main play area for positions
local snapId = 0
for _, snap in ipairs(self.getSnapPoints()) do
if inArea(snap.position, MAIN_PLAY_AREA) then
snapId = snapId + 1
@ -656,6 +677,8 @@ function redrawSlotSymbols()
tag = "Panel",
attributes = {
id = "slotPanel" .. snapId,
raycastTarget = "false", -- this disables the click function temporarily
onClick = "slotClickFunction",
scale = "0.1 0.1 1",
width = "175",
height = "175",
@ -679,9 +702,312 @@ function redrawSlotSymbols()
end
end
-- create the personal option panel
local defaultsXML = {
tag = "Defaults",
children = {
{
tag = "Text",
attributes = { color = "#FFFFFF", alignment = "MiddleLeft" }
},
{
tag = "Dropdown",
attributes = { rectAlignment = "MiddleCenter" }
},
{
tag = "Cell",
attributes = { dontUseTableCellBackground = "true", outlineSize = "0 1", outline = "grey" }
}
}
}
table.insert(xml, defaultsXML)
-- work out the position
local bounds = self.getBoundsNormalized()
local setAsideDirection = bounds.center.z > 0 and 1 or -1
-- create a button to toggle the option panel visibility
local gearPos
if setAsideDirection == -1 then
-- next to upkeep button
gearPos = "-202 -45 -11"
else
-- below encounter card drawing
gearPos = "203 -21 -11"
end
local toggleOptionPanelXML = {
tag = "Button",
attributes = {
onClick = "onClick_hideOrShowOptions",
width = "7",
height = "7",
position = gearPos,
rotation = "0 0 180",
image = "option_gear_white"
}
}
table.insert(xml, toggleOptionPanelXML)
-- work out the size
local rowHeight = {
header = 200,
groupHeader = 150,
option = 150
}
local totalHeight = rowHeight.header
local scale = 0.11
-- main window
local optionPanelXML = {
tag = "TableLayout",
attributes = {
id = "optionPanelMain",
scale = scale .. " " .. scale,
width = "1000",
rotation = "0 0 180",
active = optionPanelVisibility ~= "",
visibility = optionPanelVisibility,
color = "#000000",
outlineSize = "5 5",
outline = "grey",
showAnimation = "SlideIn_Right",
hideAnimation = "SlideOut_Right",
animationDuration = "0.2"
},
children = {
-- header
{
tag = "Row",
attributes = { preferredHeight = rowHeight.header },
children = {
{
tag = "Cell",
children = {
{
tag = "Panel",
attributes = { padding = "30 0 0 0" },
children = {
{
tag = "Text",
attributes = { font = "font_teutonic-arkham", fontSize = "110", text = "Options" }
}
}
}
}
}
}
}
}
}
-- add options groups
for groupName, groupData in pairs(availableOptions) do
totalHeight = totalHeight + rowHeight.groupHeader
-- group header
local groupXML = {
tag = "Row",
attributes = { preferredHeight = rowHeight.groupHeader },
children = {
{
tag = "Cell",
attributes = { padding = "20 10 0 0", columnSpan = "3", color = "#222222" },
children = {
{
tag = "Panel",
attributes = { padding = "40 0 0 0" },
children = {
{
tag = "Text",
attributes = { fontSize = "75", font = "font_teutonic-arkham", text = groupName }
}
}
}
}
}
}
}
table.insert(optionPanelXML.children, groupXML)
-- options
for _, optionData in ipairs(groupData) do
totalHeight = totalHeight + rowHeight.option
local optionXML = {
tag = "Row",
attributes = { preferredHeight = rowHeight.option },
children = {
-- option title
{
tag = "Cell",
attributes = { padding = "20 10 5 5", color = "#333333", columnSpan = "2" },
children = {
{
tag = "Panel",
attributes = { padding = "50 0 0 0" },
children = {
{
tag = "Text",
attributes = { fontSize = "65", font = "font_teutonic-arkham", text = optionData.title }
}
}
}
}
},
}
}
local typeXML
if optionData.type == "toggle" then
typeXML = {
tag = "Cell",
attributes = { padding = "10 10 5 5", color = "#333333" },
children = {
{
tag = "Button",
attributes = {
id = optionData.id,
image = optionPanelData[optionData.id] and "option_on" or "option_off",
onClick = "onClick_toggleOption",
rectAlignment = "MiddleRight",
offsetXY = "-30 0",
colors = "#FFFFFF|#dfdfdf",
height = "108",
width = "195",
ignoreLayout = "True"
}
}
}
}
elseif optionData.type == "button" then
typeXML = {
tag = "Cell",
attributes = { padding = "10 10 5 5", color = "#333333" },
children = {
{
tag = "Button",
attributes = {
id = optionData.id,
image = "option_button",
onClick = "onClick_" .. optionData.id,
rectAlignment = "MiddleRight",
offsetXY = "-30 0",
colors = "#FFFFFF|#dfdfdf",
height = "108",
width = "195",
ignoreLayout = "True"
}
}
}
}
end
table.insert(optionXML.children, typeXML)
table.insert(optionPanelXML.children, optionXML)
end
end
table.insert(xml, optionPanelXML)
-- set correct height
optionPanelXML.attributes.height = totalHeight
-- set correct position to align with playermat
optionPanelXML.attributes.position = (setAsideDirection * 270) .. " " .. (-95 + scale * totalHeight / 2) .. " -65"
self.UI.setXmlTable(xml)
end
function onClick_hideOrShowOptions(player)
Global.call("changeWindowVisibilityForColorWrapper", {
color = player.color,
windowId = "optionPanelMain",
owner = self
})
end
function onClick_textureSelect(player)
local textureList = {}
for texture, _ in pairs(nameToTexture) do
table.insert(textureList, texture)
end
player.showOptionsDialog("Select a texture:", textureList, _, updateTexture)
end
function onClick_handColorSelect(player)
local colorList = Player.getColors()
-- remove existing colors from the list of choices
for _, existingColor in ipairs(Player.getAvailableColors()) do
for i, newColor in ipairs(colorList) do
if existingColor == newColor or newColor == "Black" or newColor == "Grey" then
table.remove(colorList, i)
end
end
end
-- show the option dialog for color selection to the player that triggered this
player.showOptionsDialog("Select a new color:", colorList, _, function(newColor)
-- update the color of the hand zone
local handZone = ownedObjects.HandZone
handZone.setValue(newColor)
-- update visibility for old and new color
Global.call("changeWindowVisibilityForColorWrapper", {
color = playerColor,
windowId = "optionPanelMain",
owner = self
})
Global.call("changeWindowVisibilityForColorWrapper", {
color = newColor,
windowId = "optionPanelMain",
owner = self
})
navigationOverlayApi.copyVisibility(playerColor, newColor)
-- if there was a seated player, reseat to the new color
if Player[playerColor].seated then
Player[playerColor].changeColor(newColor)
else
printToColor("Updated handcolor for this playermat to " .. newColor .. ".", player.color)
end
-- update the internal variable
playerColor = newColor
updateSave()
end)
end
-- changes the UI state and the internal variable for the togglebuttons
function onClick_toggleOption(player, _, id)
local state = optionPanelData[id]
local newState = not state
applyOptionPanelChange(id, newState, player.color)
self.UI.setAttribute(id, "image", newState and "option_on" or "option_off")
end
function applyOptionPanelChange(id, state, clickedByColor)
optionPanelData[id] = state
updateSave()
if id == "slotEditing" then
toggleSlotEditing(_, clickedByColor)
end
end
-- updates the XML for the slot symbols based on the slotData table
function updateSlotSymbols()
for slotId, slotName in ipairs(slotData) do
-- update the symbol
self.UI.setAttributes("slot" .. slotId, {
rotation = getSlotRotation(slotName),
text = slotNameToChar[slotName]
})
-- update availability of the click function
self.UI.setAttribute("slotPanel" .. slotId, "raycastTarget", currentlyEditingSlots)
end
-- TODO: update the "edit slots button"?
end
-- toggle the "slot editing mode"
function toggleSlotEditing(_, clickedByColor, isRightClick)
if isRightClick then
@ -693,19 +1019,17 @@ function toggleSlotEditing(_, clickedByColor, isRightClick)
-- toggle internal variable
currentlyEditingSlots = not currentlyEditingSlots
updateSlotSymbols()
if currentlyEditingSlots then
editButtonLabel("Edit Slots", "Stop editing")
broadcastToColor("Click on a slot symbol (or an empty slot) to edit it.", messageColor, "Orange")
addClickFunctionToSlots()
else
editButtonLabel("Stop editing", "Edit Slots")
redrawSlotSymbols()
updateSave()
end
end
-- click function for slot symbols during the "slot editing mode"
function slotClickfunction(player, _, id)
function slotClickFunction(player, _, id)
local slotIndex = id:gsub("slotPanel", "")
slotIndex = tonumber(slotIndex)
@ -719,12 +1043,7 @@ function slotClickfunction(player, _, id)
player.showOptionsDialog("Choose Slot Symbol", slotNames, slotData[slotIndex],
function(chosenSlotName)
slotData[slotIndex] = chosenSlotName
-- update slot symbol
self.UI.setAttribute("slot" .. slotIndex, "text", slotNameToChar[chosenSlotName])
-- update slot rotation
self.UI.setAttribute("slot" .. slotIndex, "rotation", getSlotRotation(chosenSlotName))
updateSlotSymbols()
end
)
end
@ -744,54 +1063,8 @@ function resetSlotSymbols()
for _, slotName in ipairs(defaultSlotData) do
table.insert(slotData, slotName)
end
redrawSlotSymbols()
-- need to re-add the click functions if currently in edit mode
if currentlyEditingSlots then
addClickFunctionToSlots()
end
end
-- enables the click functions for editing
function addClickFunctionToSlots()
for i = 1, #slotData do
self.UI.setAttribute("slotPanel" .. i, "onClick", "slotClickfunction")
end
end
---------------------------------------------------------
-- color related functions
---------------------------------------------------------
-- changes the player color
function changeColor(clickedByColor)
local colorList = Player.getColors()
-- remove existing colors from the list of choices
for _, existingColor in ipairs(Player.getAvailableColors()) do
for i, newColor in ipairs(colorList) do
if existingColor == newColor or newColor == "Black" or newColor == "Grey" then
table.remove(colorList, i)
end
end
end
-- show the option dialog for color selection to the player that triggered this
Player[clickedByColor].showOptionsDialog("Select a new color:", colorList, _, function(color)
-- update the color of the hand zone
local handZone = ownedObjects.HandZone
handZone.setValue(color)
-- if the seated player clicked this, reseat him to the new color
if clickedByColor == playerColor then
navigationOverlayApi.copyVisibility(playerColor, color)
Player[playerColor].changeColor(color)
end
-- update the internal variable
playerColor = color
end)
updateSave()
updateSlotSymbols()
end
---------------------------------------------------------
@ -837,7 +1110,7 @@ function spawnTokensFor(object)
local extraUses = {}
-- add one additional charge for Akachi Onyele
if activeInvestigatorId == "03004" then
if activeInvestigatorData.id == "03004" then
extraUses["Charge"] = 1
end
@ -943,9 +1216,9 @@ function maybeUpdateActiveInvestigator(card)
local extraToken
if notes ~= nil and notes.type == "Investigator" and notes.id ~= nil then
if notes.id == activeInvestigatorId then return end
activeInvestigatorClass = notes.class
activeInvestigatorId = notes.id
if notes.id == activeInvestigatorData.id then return end
activeInvestigatorData.class = notes.class
activeInvestigatorData.id = notes.id
extraToken = notes.extraToken
ownedObjects.InvestigatorSkillTracker.call("updateStats", {
notes.willpowerIcons,
@ -954,9 +1227,9 @@ function maybeUpdateActiveInvestigator(card)
notes.agilityIcons
})
updateTexture()
elseif activeInvestigatorId ~= "00000" then
activeInvestigatorClass = "Neutral"
activeInvestigatorId = "00000"
elseif activeInvestigatorData.id ~= "00000" then
activeInvestigatorData.class = "Neutral"
activeInvestigatorData.id = "00000"
ownedObjects.InvestigatorSkillTracker.call("updateStats", { 1, 1, 1, 1 })
updateTexture()
else
@ -984,7 +1257,8 @@ function maybeUpdateActiveInvestigator(card)
tokenManager.spawnToken(pos, "universalActionAbility", self.getRotation(),
function(spawned)
spawned.call("updateClassAndSymbol", { class = activeInvestigatorClass, symbol = activeInvestigatorClass })
spawned.call("updateClassAndSymbol",
{ class = activeInvestigatorData.class, symbol = activeInvestigatorData.class })
end)
end
@ -1019,7 +1293,7 @@ function maybeUpdateActiveInvestigator(card)
tokenManager.spawnToken(globalSpawnPos, "universalActionAbility", self.getRotation(),
function(spawned)
spawned.call("updateClassAndSymbol", { class = activeInvestigatorClass, symbol = str })
spawned.call("updateClassAndSymbol", { class = activeInvestigatorData.class, symbol = str })
end)
end
end
@ -1029,11 +1303,13 @@ end
-- updates the texture of the playermat
---@param overrideName? string Force a specific texture
function updateTexture(overrideName)
updateSave()
local name = "Neutral"
-- use class specific texture if enabled
if isClassTextureEnabled then
name = activeInvestigatorClass
name = activeInvestigatorData.class
end
-- get new texture URL
@ -1056,8 +1332,8 @@ function updateTexture(overrideName)
end
end
self.script_state = onSave()
customInfo.image = newUrl
---@diagnostic disable-next-line: param-type-mismatch
self.setCustomObject(customInfo)
local reloadedMat = self.reload()
@ -1150,9 +1426,12 @@ function getEncounterCardDrawPosition(stack)
end
-- creates / removes the draw 1 button
---@param visible boolean Whether the draw 1 button should be visible
---@param visible? boolean Whether the draw 1 button should be visible
function showDrawButton(visible)
if visible then
isDrawButtonVisible = visible
updateSave()
end
if isDrawButtonVisible then
-- Draw 1 button: modified default data
@ -1291,3 +1570,9 @@ function getColoredName(playerColor)
-- add bb-code
return "[" .. Color.fromString(playerColor):toHex() .. "]" .. displayName .. "[-]"
end
function getActiveInvestigatorData() return activeInvestigatorData end
function setActiveInvestigatorData(newData) activeInvestigatorData = newData end
function getDES() return hasDES end

View File

@ -61,7 +61,7 @@ do
---@return boolean: whether DES is present on the playermat
PlayermatApi.hasDES = function(matColor)
for _, mat in pairs(getMatForColor(matColor)) do
return mat.getVar("hasDES")
return mat.call("getDES")
end
end
@ -79,7 +79,7 @@ do
PlayermatApi.loadSlotData = function(matColor, newSlotData)
for _, mat in pairs(getMatForColor(matColor)) do
mat.setTable("slotData", newSlotData)
mat.call("redrawSlotSymbols")
mat.call("updateSlotSymbols")
return
end
end
@ -171,19 +171,20 @@ do
end
end
-- Returns the active investigator id
-- Gets data about the active investigator
---@param matColor string Color of the playermat - White, Orange, Green or Red (does not support "All")
PlayermatApi.returnInvestigatorId = function(matColor)
PlayermatApi.getActiveInvestigatorData = function(matColor)
for _, mat in pairs(getMatForColor(matColor)) do
return mat.getVar("activeInvestigatorId")
return mat.call("getActiveInvestigatorData")
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)
-- Gets data about the active investigator
---@param matColor string Color of the playermat - White, Orange, Green, Red or All
---@param newData table New active investigator data (class and id)
PlayermatApi.setActiveInvestigatorData = function(matColor, newData)
for _, mat in pairs(getMatForColor(matColor)) do
return mat.getVar("activeInvestigatorClass")
mat.call("setActiveInvestigatorData",newData)
end
end
@ -235,6 +236,15 @@ do
end
end
-- updates the texture of the playermat
---@param matColor string Color of the playermat - White, Orange, Green, Red or All
---@param overrideName? string Force a specific texture
PlayermatApi.updateTexture = function(matColor, overrideName)
for _, mat in pairs(getMatForColor(matColor)) do
mat.call("updateTexture", overrideName)
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)
@ -316,11 +326,11 @@ do
end
end
-- Redraws the XML for the slot symbols based on the slotData table
-- Updates 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)
PlayermatApi.updateSlotSymbols = function(matColor)
for _, mat in pairs(getMatForColor(matColor)) do
mat.call("redrawSlotSymbols")
mat.call("updateSlotSymbols")
end
end

View File

@ -63,6 +63,7 @@
padding="0 17 3 3"/>
<Button class="optionToggle"
image="option_off"
onClick="onClick_toggleOption"
rectAlignment="MiddleRight"
offsetXY="-30 0"
colors="#FFFFFF|#dfdfdf"
@ -156,8 +157,7 @@
</Cell>
<Cell class="option-button">
<Button class="optionToggle"
id="showTitleSplash"
onClick="onClick_toggleOption"/>
id="showTitleSplash"/>
</Cell>
</Row>
@ -171,8 +171,7 @@
</Cell>
<Cell class="option-button">
<Button class="optionToggle"
id="enableCardHelpers"
onClick="onClick_toggleOption"/>
id="enableCardHelpers"/>
</Cell>
</Row>
@ -196,8 +195,7 @@
</Cell>
<Cell class="option-button">
<Button class="optionToggle"
id="playAreaSnapTags"
onClick="onClick_toggleOption"/>
id="playAreaSnapTags"/>
</Cell>
</Row>
@ -211,8 +209,7 @@
</Cell>
<Cell class="option-button">
<Button class="optionToggle"
id="playAreaConnections"
onClick="onClick_toggleOption"/>
id="playAreaConnections"/>
</Cell>
</Row>
@ -243,8 +240,7 @@
</Cell>
<Cell class="option-button">
<Button class="optionToggle"
id="changePlayAreaImage"
onClick="onClick_toggleOption"/>
id="changePlayAreaImage"/>
</Cell>
</Row>
@ -253,7 +249,7 @@
<Cell class="group-header">
<Panel class="group-header"
image="header_cover">
<Text class="group-header">PLAYERMAT SETTINGS</Text>
<Text class="group-header">GLOBAL PLAYERMAT SETTINGS</Text>
</Panel>
</Cell>
</Row>
@ -268,8 +264,7 @@
</Cell>
<Cell class="option-button">
<Button class="optionToggle"
id="useSnapTags"
onClick="onClick_toggleOption"/>
id="useSnapTags"/>
</Cell>
</Row>
@ -283,8 +278,7 @@
</Cell>
<Cell class="option-button">
<Button class="optionToggle"
id="showDrawButton"
onClick="onClick_toggleOption"/>
id="showDrawButton"/>
</Cell>
</Row>
@ -298,8 +292,7 @@
</Cell>
<Cell class="option-button">
<Button class="optionToggle"
id="useClassTexture"
onClick="onClick_toggleOption"/>
id="useClassTexture"/>
</Cell>
</Row>
@ -313,8 +306,7 @@
</Cell>
<Cell class="option-button">
<Button class="optionToggle"
id="useClueClickers"
onClick="onClick_toggleOption"/>
id="useClueClickers"/>
</Cell>
</Row>
@ -380,8 +372,7 @@
</Cell>
<Cell class="option-button">
<Button class="optionToggle"
id="showAttachmentHelper"
onClick="onClick_toggleOption"/>
id="showAttachmentHelper"/>
</Cell>
</Row>
@ -395,8 +386,7 @@
</Cell>
<Cell class="option-button">
<Button class="optionToggle"
id="showCleanUpHelper"
onClick="onClick_toggleOption"/>
id="showCleanUpHelper"/>
</Cell>
</Row>
@ -410,8 +400,7 @@
</Cell>
<Cell class="option-button">
<Button class="optionToggle"
id="showCYOA"
onClick="onClick_toggleOption"/>
id="showCYOA"/>
</Cell>
</Row>
@ -425,8 +414,7 @@
</Cell>
<Cell class="option-button">
<Button class="optionToggle"
id="showDisplacementTool"
onClick="onClick_toggleOption"/>
id="showDisplacementTool"/>
</Cell>
</Row>
@ -440,8 +428,7 @@
</Cell>
<Cell class="option-button">
<Button class="optionToggle"
id="showHandHelper"
onClick="onClick_toggleOption"/>
id="showHandHelper"/>
</Cell>
</Row>
@ -455,8 +442,7 @@
</Cell>
<Cell class="option-button">
<Button class="optionToggle"
id="showSearchAssistant"
onClick="onClick_toggleOption"/>
id="showSearchAssistant"/>
</Cell>
</Row>
</TableLayout>