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, "Type": 0,
"URL": "https://steamusercontent-a.akamaihd.net/ugc/2026086584372569912/5CB461AEAE2E59D3064D90A776EB86C46081EC78/" "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", "Name": "option_on",
"Type": 0, "Type": 0,
@ -39,6 +44,11 @@
"Type": 0, "Type": 0,
"URL": "https://steamusercontent-a.akamaihd.net/ugc/2462982115668996901/D6438ECBB11DECC6DB9987589FF526FBAD4D2368/" "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", "Name": "font_arkhamicons",
"Type": 1, "Type": 1,

View File

@ -342,6 +342,28 @@
"ImageURL": "https://steamusercontent-a.akamaihd.net/ugc/2462982115659543571/5D778EA4BC682DAE97E8F59A991BCF8CB3979B04/", "ImageURL": "https://steamusercontent-a.akamaihd.net/ugc/2462982115659543571/5D778EA4BC682DAE97E8F59A991BCF8CB3979B04/",
"WidthScale": 0 "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": "", "Description": "",
"DragSelectable": true, "DragSelectable": true,
"GMNotes": "", "GMNotes": "",

View File

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

View File

@ -342,6 +342,28 @@
"ImageURL": "https://steamusercontent-a.akamaihd.net/ugc/2462982115659543571/5D778EA4BC682DAE97E8F59A991BCF8CB3979B04/", "ImageURL": "https://steamusercontent-a.akamaihd.net/ugc/2462982115659543571/5D778EA4BC682DAE97E8F59A991BCF8CB3979B04/",
"WidthScale": 0 "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": "", "Description": "",
"DragSelectable": true, "DragSelectable": true,
"GMNotes": "", "GMNotes": "",

View File

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

View File

@ -342,6 +342,28 @@
"ImageURL": "https://steamusercontent-a.akamaihd.net/ugc/2462982115659543571/5D778EA4BC682DAE97E8F59A991BCF8CB3979B04/", "ImageURL": "https://steamusercontent-a.akamaihd.net/ugc/2462982115659543571/5D778EA4BC682DAE97E8F59A991BCF8CB3979B04/",
"WidthScale": 0 "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": "", "Description": "",
"DragSelectable": true, "DragSelectable": true,
"GMNotes": "", "GMNotes": "",

View File

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

View File

@ -342,6 +342,28 @@
"ImageURL": "https://steamusercontent-a.akamaihd.net/ugc/2462982115659543571/5D778EA4BC682DAE97E8F59A991BCF8CB3979B04/", "ImageURL": "https://steamusercontent-a.akamaihd.net/ugc/2462982115659543571/5D778EA4BC682DAE97E8F59A991BCF8CB3979B04/",
"WidthScale": 0 "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": "", "Description": "",
"DragSelectable": true, "DragSelectable": true,
"GMNotes": "", "GMNotes": "",

View File

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

View File

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

View File

@ -11,7 +11,7 @@ function onLoad()
buttonParamaters.hover_color = "White" buttonParamaters.hover_color = "White"
buttonParamaters.label = 0 buttonParamaters.label = 0
buttonParamaters.click_function = "none" buttonParamaters.click_function = "none"
buttonParamaters.position = Vector(0, 0.11, -0.4) buttonParamaters.position = Vector(0, 0.11, -0.2)
buttonParamaters.height = 0 buttonParamaters.height = 0
buttonParamaters.width = 0 buttonParamaters.width = 0
buttonParamaters.font_size = 500 buttonParamaters.font_size = 500
@ -20,20 +20,10 @@ function onLoad()
-- index 1: button to toggle "des" -- index 1: button to toggle "des"
buttonParamaters.label = "DES: ✗" buttonParamaters.label = "DES: ✗"
buttonParamaters.position.z = 0.25 buttonParamaters.position.z = 0.45
buttonParamaters.font_size = 120 buttonParamaters.font_size = 120
self.createButton(buttonParamaters) 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 -- make sure this part executes after the playermats are loaded
Wait.time(function() Wait.time(function()
updateColors() updateColors()
@ -117,8 +107,3 @@ function updateValue()
-- update button label and color -- update button label and color
self.editButton({ index = 0, font_color = hasDES and "Green" or "White", label = size }) self.editButton({ index = 0, font_color = hasDES and "Green" or "White", label = size })
end 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
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 -- disable delete action (only applies to promoted players) and discard objects instead
function onPlayerAction(player, action, targets) function onPlayerAction(player, action, targets)
if action == Player.Action.Delete and not player.admin then if action == Player.Action.Delete and not player.admin then
@ -1169,14 +1164,24 @@ function onClick_toggleUi(player, windowId)
changeWindowVisibilityForColor(player.color, windowId) changeWindowVisibilityForColor(player.color, windowId)
end 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 -- toggles the visibility of the specific window for the specified color
---@param color string Player color to toggle the visibility for ---@param color string Player color to toggle the visibility for
---@param windowId string ID of the XML element ---@param windowId string ID of the XML element
---@param overrideState? boolean Forcefully sets the new visibility ---@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 ---@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 -- current state
local colorString = UI.getAttribute(windowId, "visibility") or "" local colorString = targetUi.getAttribute(windowId, "visibility") or ""
-- parse the visibility string -- parse the visibility string
local visible = false local visible = false
@ -1215,8 +1220,8 @@ function changeWindowVisibilityForColor(color, windowId, overrideState)
newColorString = newColorString:sub(1, -2) newColorString = newColorString:sub(1, -2)
-- update the visibility of the XML -- update the visibility of the XML
UI.setAttribute(windowId, "visibility", newColorString) targetUi.setAttribute(windowId, "visibility", newColorString)
UI.setAttribute(windowId, "active", newColorString ~= "") targetUi.setAttribute(windowId, "active", newColorString ~= "")
return visible return visible
end end
@ -1561,6 +1566,12 @@ end
-- removes a playermat and all related objects from play -- removes a playermat and all related objects from play
---@param matColor string Color of the playermat to remove ---@param matColor string Color of the playermat to remove
function removePlayermat(matColor) 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) local matObjects = guidReferenceApi.getObjectsByOwner(matColor)
if not matObjects.Playermat then return end 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 tokenManager = require("core/token/TokenManager")
local tokenSpawnTrackerApi = require("core/token/TokenSpawnTrackerApi") 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 -- we use this to turn off collision handling until onLoad() is complete
local collisionEnabled = false local collisionEnabled = false
local currentlyEditingSlots = false local currentlyEditingSlots = false
@ -52,7 +77,7 @@ local ENCOUNTER_DISCARD_POSITION = { x = -3.85, y = 1.5, z = 10.38 }
local buttonParameters = { local buttonParameters = {
label = "Upkeep", label = "Upkeep",
click_function = "doUpkeep", click_function = "doUpkeep",
tooltip = "Right-click to change color", tooltip = "Right-click to skip resource gain and card draw",
function_owner = self, function_owner = self,
position = { x = 1.82, y = 0.1, z = -0.45 }, position = { x = 1.82, y = 0.1, z = -0.45 },
scale = { 0.12, 0.12, 0.12 }, scale = { 0.12, 0.12, 0.12 },
@ -94,24 +119,24 @@ local defaultSlotData = {
"any", "any", "any", "Accessory", "Arcane", "Arcane", "Body" "any", "any", "any", "Accessory", "Arcane", "Arcane", "Body"
} }
-- global variables for access local activeInvestigatorData = {}
activeInvestigatorClass = "Neutral" local hasDES = false
activeInvestigatorId = "00000"
hasDES = false
local isClassTextureEnabled = true local isClassTextureEnabled = true
local isDrawButtonVisible = false local isDrawButtonVisible = false
local optionPanelVisibility = ""
-- table of type-object reference pairs of all owned objects -- table of type-object reference pairs of all owned objects
local ownedObjects = {} local ownedObjects = {}
local matColor = self.getMemo() local matColor = self.getMemo()
function onSave() function updateSave()
return JSON.encode({ optionPanelVisibility = self.UI.getAttribute("optionPanelMain", "visibility") or ""
activeInvestigatorClass = activeInvestigatorClass, self.script_state = JSON.encode({
activeInvestigatorId = activeInvestigatorId, activeInvestigatorData = activeInvestigatorData,
isClassTextureEnabled = isClassTextureEnabled, isClassTextureEnabled = isClassTextureEnabled,
isDrawButtonVisible = isDrawButtonVisible, isDrawButtonVisible = isDrawButtonVisible,
optionPanelData = optionPanelData,
optionPanelVisibility = optionPanelVisibility,
playerColor = playerColor, playerColor = playerColor,
slotData = slotData slotData = slotData
}) })
@ -120,12 +145,16 @@ end
function onLoad(savedData) function onLoad(savedData)
if savedData and savedData ~= "" then if savedData and savedData ~= "" then
local loadedData = JSON.decode(savedData) local loadedData = JSON.decode(savedData)
activeInvestigatorClass = loadedData.activeInvestigatorClass activeInvestigatorData = loadedData.activeInvestigatorData
activeInvestigatorId = loadedData.activeInvestigatorId
isClassTextureEnabled = loadedData.isClassTextureEnabled isClassTextureEnabled = loadedData.isClassTextureEnabled
isDrawButtonVisible = loadedData.isDrawButtonVisible isDrawButtonVisible = loadedData.isDrawButtonVisible
optionPanelData = loadedData.optionPanelData
optionPanelVisibility = loadedData.optionPanelVisibility
playerColor = loadedData.playerColor playerColor = loadedData.playerColor
slotData = loadedData.slotData slotData = loadedData.slotData
-- make sure that edit mode starts disabled
optionPanelData.slotEditing = false
end end
updateMessageColor(playerColor) updateMessageColor(playerColor)
@ -161,15 +190,15 @@ function onLoad(savedData)
-- Upkeep button: can use the default parameters for this -- Upkeep button: can use the default parameters for this
self.createButton(buttonParameters) self.createButton(buttonParameters)
-- Slot editing button: modified default data -- Discard 1 button: modified default data
buttonParameters.label = "Edit Slots" buttonParameters.label = "Discard 1"
buttonParameters.click_function = "toggleSlotEditing" buttonParameters.click_function = "doDiscardOne"
buttonParameters.tooltip = "Right-click to reset slot symbols" buttonParameters.tooltip = "Discard one random card from hand (hidden cards are excluded)."
buttonParameters.position.z = 0.92 buttonParameters.position.z = 0.92
self.createButton(buttonParameters) self.createButton(buttonParameters)
showDrawButton(isDrawButtonVisible) showDrawButton()
redrawSlotSymbols() createXML()
math.randomseed(os.time()) math.randomseed(os.time())
Wait.time(function() collisionEnabled = true end, 0.1) Wait.time(function() collisionEnabled = true end, 0.1)
end end
@ -226,18 +255,6 @@ function round(num, numDecimalPlaces)
return math.floor(num * mult + 0.5) / mult return math.floor(num * mult + 0.5) / mult
end 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 -- 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 ---@param clickedByColor string Colorstring of player who clicked a button
function updateMessageColor(clickedByColor) function updateMessageColor(clickedByColor)
@ -245,7 +262,7 @@ function updateMessageColor(clickedByColor)
end end
--------------------------------------------------------- ---------------------------------------------------------
-- Discard buttons -- Discard buttons (threat area)
--------------------------------------------------------- ---------------------------------------------------------
-- handles discarding for a list of objects -- handles discarding for a list of objects
@ -303,11 +320,6 @@ function doUpkeepFromHotkey(clickedByColor)
end end
function doUpkeep(_, clickedByColor, isRightClick) function doUpkeep(_, clickedByColor, isRightClick)
if isRightClick then
changeColor(clickedByColor)
return
end
updateMessageColor(clickedByColor) updateMessageColor(clickedByColor)
-- unexhaust cards in play zone, flip action tokens and find Forced Learning / Dream-Enhancing Serum -- 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 -- 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) -- (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 for _, obj in ipairs(getObjects()) do
if obj.type == "Card" and obj.is_face_down then if obj.type == "Card" and obj.is_face_down then
local notes = JSON.decode(obj.getGMNotes()) local notes = JSON.decode(obj.getGMNotes())
@ -373,8 +385,13 @@ function doUpkeep(_, clickedByColor, isRightClick)
end end
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) -- 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 }) updateCounter({ type = "ResourceCounter", modifier = 2 })
printToColor("Gaining 2 resources (Jenny)", messageColor) printToColor("Gaining 2 resources (Jenny)", messageColor)
else else
@ -382,7 +399,7 @@ function doUpkeep(_, clickedByColor, isRightClick)
end end
-- draw a card (with handling for Patrice and Forced Learning) -- draw a card (with handling for Patrice and Forced Learning)
if activeInvestigatorId == "06005" then if activeInvestigatorData.id == "06005" then
if forcedLearning then if forcedLearning then
printToColor("Wow, did you really take 'Versatile' to play Patrice with 'Forced Learning'?" 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) .. " Choose which draw replacement effect takes priority and draw cards accordingly.", messageColor)
@ -419,7 +436,7 @@ function doUpkeep(_, clickedByColor, isRightClick)
elseif forcedLearning then elseif forcedLearning then
printToColor("Drawing 2 cards, discard 1 (Forced Learning)", messageColor) printToColor("Drawing 2 cards, discard 1 (Forced Learning)", messageColor)
drawCardsWithReshuffle(2) drawCardsWithReshuffle(2)
elseif activeInvestigatorId == "89001" then elseif activeInvestigatorData.id == "89001" then
printToColor("Drawing 2 cards (Subject 5U-21)", messageColor) printToColor("Drawing 2 cards (Subject 5U-21)", messageColor)
drawCardsWithReshuffle(2) drawCardsWithReshuffle(2)
else else
@ -596,9 +613,12 @@ function doDiscardOne()
-- get a random eligible card (from the "choices" table) -- get a random eligible card (from the "choices" table)
local num = math.random(1, #choices) local num = math.random(1, #choices)
deckLib.placeOrMergeIntoDeck(hand[choices[num]], returnGlobalDiscardPosition(), self.getRotation()) local card = hand[choices[num]]
broadcastToAll(getColoredName(playerColor) .. " randomly discarded card " local cardName = card.getName()
.. choices[num] .. "/" .. #hand .. ".", "White") local cardId = choices[num] .. "/" .. #hand
deckLib.placeOrMergeIntoDeck(card, returnGlobalDiscardPosition(), self.getRotation())
broadcastToAll(getColoredName(playerColor) .. " randomly discarded " .. cardName " (" .. cardId .. ").", "White")
end end
end end
@ -633,15 +653,16 @@ function checkForDES()
end end
--------------------------------------------------------- ---------------------------------------------------------
-- slot symbol displaying -- XML creation and modifying
--------------------------------------------------------- ---------------------------------------------------------
-- this will redraw the XML for the slot symbols based on the slotData table -- initializes the XML
function redrawSlotSymbols() function createXML()
local xml = {} local xml = {}
local snapId = 0
-- create a panel for each slot symbol
-- use the snap point positions in the main play area for positions -- use the snap point positions in the main play area for positions
local snapId = 0
for _, snap in ipairs(self.getSnapPoints()) do for _, snap in ipairs(self.getSnapPoints()) do
if inArea(snap.position, MAIN_PLAY_AREA) then if inArea(snap.position, MAIN_PLAY_AREA) then
snapId = snapId + 1 snapId = snapId + 1
@ -656,6 +677,8 @@ function redrawSlotSymbols()
tag = "Panel", tag = "Panel",
attributes = { attributes = {
id = "slotPanel" .. snapId, id = "slotPanel" .. snapId,
raycastTarget = "false", -- this disables the click function temporarily
onClick = "slotClickFunction",
scale = "0.1 0.1 1", scale = "0.1 0.1 1",
width = "175", width = "175",
height = "175", height = "175",
@ -679,9 +702,312 @@ function redrawSlotSymbols()
end end
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) self.UI.setXmlTable(xml)
end 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" -- toggle the "slot editing mode"
function toggleSlotEditing(_, clickedByColor, isRightClick) function toggleSlotEditing(_, clickedByColor, isRightClick)
if isRightClick then if isRightClick then
@ -693,19 +1019,17 @@ function toggleSlotEditing(_, clickedByColor, isRightClick)
-- toggle internal variable -- toggle internal variable
currentlyEditingSlots = not currentlyEditingSlots currentlyEditingSlots = not currentlyEditingSlots
updateSlotSymbols()
if currentlyEditingSlots then if currentlyEditingSlots then
editButtonLabel("Edit Slots", "Stop editing")
broadcastToColor("Click on a slot symbol (or an empty slot) to edit it.", messageColor, "Orange") broadcastToColor("Click on a slot symbol (or an empty slot) to edit it.", messageColor, "Orange")
addClickFunctionToSlots()
else else
editButtonLabel("Stop editing", "Edit Slots") updateSave()
redrawSlotSymbols()
end end
end end
-- click function for slot symbols during the "slot editing mode" -- click function for slot symbols during the "slot editing mode"
function slotClickfunction(player, _, id) function slotClickFunction(player, _, id)
local slotIndex = id:gsub("slotPanel", "") local slotIndex = id:gsub("slotPanel", "")
slotIndex = tonumber(slotIndex) slotIndex = tonumber(slotIndex)
@ -719,12 +1043,7 @@ function slotClickfunction(player, _, id)
player.showOptionsDialog("Choose Slot Symbol", slotNames, slotData[slotIndex], player.showOptionsDialog("Choose Slot Symbol", slotNames, slotData[slotIndex],
function(chosenSlotName) function(chosenSlotName)
slotData[slotIndex] = chosenSlotName slotData[slotIndex] = chosenSlotName
updateSlotSymbols()
-- update slot symbol
self.UI.setAttribute("slot" .. slotIndex, "text", slotNameToChar[chosenSlotName])
-- update slot rotation
self.UI.setAttribute("slot" .. slotIndex, "rotation", getSlotRotation(chosenSlotName))
end end
) )
end end
@ -744,54 +1063,8 @@ function resetSlotSymbols()
for _, slotName in ipairs(defaultSlotData) do for _, slotName in ipairs(defaultSlotData) do
table.insert(slotData, slotName) table.insert(slotData, slotName)
end end
updateSave()
redrawSlotSymbols() updateSlotSymbols()
-- 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)
end end
--------------------------------------------------------- ---------------------------------------------------------
@ -837,7 +1110,7 @@ function spawnTokensFor(object)
local extraUses = {} local extraUses = {}
-- add one additional charge for Akachi Onyele -- add one additional charge for Akachi Onyele
if activeInvestigatorId == "03004" then if activeInvestigatorData.id == "03004" then
extraUses["Charge"] = 1 extraUses["Charge"] = 1
end end
@ -943,9 +1216,9 @@ function maybeUpdateActiveInvestigator(card)
local extraToken local extraToken
if notes ~= nil and notes.type == "Investigator" and notes.id ~= nil then if notes ~= nil and notes.type == "Investigator" and notes.id ~= nil then
if notes.id == activeInvestigatorId then return end if notes.id == activeInvestigatorData.id then return end
activeInvestigatorClass = notes.class activeInvestigatorData.class = notes.class
activeInvestigatorId = notes.id activeInvestigatorData.id = notes.id
extraToken = notes.extraToken extraToken = notes.extraToken
ownedObjects.InvestigatorSkillTracker.call("updateStats", { ownedObjects.InvestigatorSkillTracker.call("updateStats", {
notes.willpowerIcons, notes.willpowerIcons,
@ -954,9 +1227,9 @@ function maybeUpdateActiveInvestigator(card)
notes.agilityIcons notes.agilityIcons
}) })
updateTexture() updateTexture()
elseif activeInvestigatorId ~= "00000" then elseif activeInvestigatorData.id ~= "00000" then
activeInvestigatorClass = "Neutral" activeInvestigatorData.class = "Neutral"
activeInvestigatorId = "00000" activeInvestigatorData.id = "00000"
ownedObjects.InvestigatorSkillTracker.call("updateStats", { 1, 1, 1, 1 }) ownedObjects.InvestigatorSkillTracker.call("updateStats", { 1, 1, 1, 1 })
updateTexture() updateTexture()
else else
@ -984,7 +1257,8 @@ function maybeUpdateActiveInvestigator(card)
tokenManager.spawnToken(pos, "universalActionAbility", self.getRotation(), tokenManager.spawnToken(pos, "universalActionAbility", self.getRotation(),
function(spawned) function(spawned)
spawned.call("updateClassAndSymbol", { class = activeInvestigatorClass, symbol = activeInvestigatorClass }) spawned.call("updateClassAndSymbol",
{ class = activeInvestigatorData.class, symbol = activeInvestigatorData.class })
end) end)
end end
@ -1019,7 +1293,7 @@ function maybeUpdateActiveInvestigator(card)
tokenManager.spawnToken(globalSpawnPos, "universalActionAbility", self.getRotation(), tokenManager.spawnToken(globalSpawnPos, "universalActionAbility", self.getRotation(),
function(spawned) function(spawned)
spawned.call("updateClassAndSymbol", { class = activeInvestigatorClass, symbol = str }) spawned.call("updateClassAndSymbol", { class = activeInvestigatorData.class, symbol = str })
end) end)
end end
end end
@ -1029,11 +1303,13 @@ end
-- updates the texture of the playermat -- updates the texture of the playermat
---@param overrideName? string Force a specific texture ---@param overrideName? string Force a specific texture
function updateTexture(overrideName) function updateTexture(overrideName)
updateSave()
local name = "Neutral" local name = "Neutral"
-- use class specific texture if enabled -- use class specific texture if enabled
if isClassTextureEnabled then if isClassTextureEnabled then
name = activeInvestigatorClass name = activeInvestigatorData.class
end end
-- get new texture URL -- get new texture URL
@ -1056,8 +1332,8 @@ function updateTexture(overrideName)
end end
end end
self.script_state = onSave()
customInfo.image = newUrl customInfo.image = newUrl
---@diagnostic disable-next-line: param-type-mismatch
self.setCustomObject(customInfo) self.setCustomObject(customInfo)
local reloadedMat = self.reload() local reloadedMat = self.reload()
@ -1150,9 +1426,12 @@ function getEncounterCardDrawPosition(stack)
end end
-- creates / removes the draw 1 button -- 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) function showDrawButton(visible)
if visible then
isDrawButtonVisible = visible isDrawButtonVisible = visible
updateSave()
end
if isDrawButtonVisible then if isDrawButtonVisible then
-- Draw 1 button: modified default data -- Draw 1 button: modified default data
@ -1291,3 +1570,9 @@ function getColoredName(playerColor)
-- add bb-code -- add bb-code
return "[" .. Color.fromString(playerColor):toHex() .. "]" .. displayName .. "[-]" return "[" .. Color.fromString(playerColor):toHex() .. "]" .. displayName .. "[-]"
end 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 ---@return boolean: whether DES is present on the playermat
PlayermatApi.hasDES = function(matColor) PlayermatApi.hasDES = function(matColor)
for _, mat in pairs(getMatForColor(matColor)) do for _, mat in pairs(getMatForColor(matColor)) do
return mat.getVar("hasDES") return mat.call("getDES")
end end
end end
@ -79,7 +79,7 @@ do
PlayermatApi.loadSlotData = function(matColor, newSlotData) PlayermatApi.loadSlotData = function(matColor, newSlotData)
for _, mat in pairs(getMatForColor(matColor)) do for _, mat in pairs(getMatForColor(matColor)) do
mat.setTable("slotData", newSlotData) mat.setTable("slotData", newSlotData)
mat.call("redrawSlotSymbols") mat.call("updateSlotSymbols")
return return
end end
end end
@ -171,19 +171,20 @@ do
end end
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") ---@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 for _, mat in pairs(getMatForColor(matColor)) do
return mat.getVar("activeInvestigatorId") return mat.call("getActiveInvestigatorData")
end end
end end
-- Returns the class of the active investigator -- Gets data about the active investigator
---@param matColor string Color of the playermat - White, Orange, Green or Red (does not support "All") ---@param matColor string Color of the playermat - White, Orange, Green, Red or All
PlayermatApi.returnInvestigatorClass = function(matColor) ---@param newData table New active investigator data (class and id)
PlayermatApi.setActiveInvestigatorData = function(matColor, newData)
for _, mat in pairs(getMatForColor(matColor)) do for _, mat in pairs(getMatForColor(matColor)) do
return mat.getVar("activeInvestigatorClass") mat.call("setActiveInvestigatorData",newData)
end end
end end
@ -235,6 +236,15 @@ do
end end
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 -- 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 ---@param matColor string Color of the playermat - White, Orange, Green, Red or All
PlayermatApi.removeClues = function(matColor) PlayermatApi.removeClues = function(matColor)
@ -316,11 +326,11 @@ do
end end
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 ---@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 for _, mat in pairs(getMatForColor(matColor)) do
mat.call("redrawSlotSymbols") mat.call("updateSlotSymbols")
end end
end end

View File

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