Merge branch 'main' into scroll-of-secrets

This commit is contained in:
Chr1Z93 2024-06-27 02:21:09 +02:00
commit 2d202bd513
51 changed files with 985 additions and 1194 deletions

View File

@ -3,6 +3,7 @@
"ComponentTags_path": "ComponentTags.json",
"CustomUIAssets_path": "CustomUIAssets.json",
"DecalPallet_path": "DecalPallet.json",
"Decals": [],
"GameComplexity": "",
"GameMode": "Arkham Horror LCG - Super Complete Edition",
"GameType": "",
@ -140,7 +141,7 @@
"ArkhamDBDeckImporter.a28140",
"Configuration.03804b",
"DrawingTool.280086",
"PlaymatImageSwapper.b7b45b",
"PlayAreaImageSwapper.b7b45b",
"AllPlayerCards.15bb07",
"InvestigatorSkillTracker.af7ed7",
"InvestigatorSkillTracker.e598c2",

View File

@ -22,7 +22,7 @@
"ImageURL": "https://i.imgur.com/SBE8GR5.png",
"WidthScale": 0
},
"Description": "Only tracks tokens that actually hit the playmat.\n\nAll credit goes to TadGH!",
"Description": "",
"DragSelectable": true,
"GMNotes": "",
"GUID": "766620",

View File

@ -1,188 +1,172 @@
tableHeightOffset =-9
tableHeightOffset = -9
function onSave()
saved_data = JSON.encode({tid=tableImageData, cd=checkData})
--saved_data = ""
return saved_data
return JSON.encode({ tid = tableImageData, cd = checkData })
end
function onload(saved_data)
--Loads the tracking for if the game has started yet
if saved_data ~= "" then
local loaded_data = JSON.decode(saved_data)
tableImageData = loaded_data.tid
checkData = loaded_data.cd
else
tableImageData = {}
checkData = {move=false, scale=false}
end
if saved_data ~= "" then
local loaded_data = JSON.decode(saved_data)
tableImageData = loaded_data.tid
checkData = loaded_data.cd
else
tableImageData = {}
checkData = { move = false, scale = false }
end
--Disables interactable status of objects with GUID in list
for _, guid in ipairs(ref_noninteractable) do
local obj = getObjectFromGUID(guid)
if obj then obj.interactable = false end
end
--Disables interactable status of objects with GUID in list
for _, guid in ipairs(ref_noninteractable) do
local obj = getObjectFromGUID(guid)
if obj then obj.interactable = false end
end
--Establish references to table parts
obj_leg1 = getObjectFromGUID("afc863")
obj_leg2 = getObjectFromGUID("c8edca")
obj_leg3 = getObjectFromGUID("393bf7")
obj_leg4 = getObjectFromGUID("12c65e")
obj_surface = getObjectFromGUID("4ee1f2")
obj_side_top = getObjectFromGUID("35b95f")
obj_side_bot = getObjectFromGUID("f938a2")
obj_side_lef = getObjectFromGUID("9f95fd")
obj_side_rig = getObjectFromGUID("5af8f2")
--Establish references to table parts
obj_leg1 = getObjectFromGUID("afc863")
obj_leg2 = getObjectFromGUID("c8edca")
obj_leg3 = getObjectFromGUID("393bf7")
obj_leg4 = getObjectFromGUID("12c65e")
obj_surface = getObjectFromGUID("4ee1f2")
obj_side_top = getObjectFromGUID("35b95f")
obj_side_bot = getObjectFromGUID("f938a2")
obj_side_lef = getObjectFromGUID("9f95fd")
obj_side_rig = getObjectFromGUID("5af8f2")
controlActive = true
createOpenCloseButton()
controlActive = true
createOpenCloseButton()
end
--Activation/deactivation of control panel
--Activated by clicking on
function click_toggleControl(_, color)
if permissionCheck(color) then
if not controlActive then
--Activate control panel
controlActive = true
self.clearButtons()
createOpenCloseButton()
createSurfaceInput()
createSurfaceButtons()
createScaleInput()
createScaleButtons()
else
--Deactivate control panel
controlActive = false
self.clearButtons()
self.clearInputs()
createOpenCloseButton()
end
if permissionCheck(color) then
if not controlActive then
--Activate control panel
controlActive = true
self.clearButtons()
createOpenCloseButton()
createSurfaceInput()
createSurfaceButtons()
createScaleInput()
createScaleButtons()
else
--Deactivate control panel
controlActive = false
self.clearButtons()
self.clearInputs()
createOpenCloseButton()
end
end
end
--Table surface control
--Changes table surface
function click_applySurface(_, color)
if permissionCheck(color) then
updateSurface()
broadcastToAll("New Table Image Applied", {0.2,0.9,0.2})
end
if permissionCheck(color) then
updateSurface()
broadcastToAll("New Table Image Applied", { 0.2, 0.9, 0.2 })
end
end
--Saves table surface
function click_saveSurface(_, color)
if permissionCheck(color) then
local nickname = self.getInputs()[1].value
local url = self.getInputs()[2].value
if nickname == "" then
--No nickname
broadcastToAll("Please supply a nickname for this save.", {0.9,0.2,0.2})
else
--Nickname exists
if permissionCheck(color) then
local nickname = self.getInputs()[1].value
local url = self.getInputs()[2].value
if nickname == "" then
--No nickname
broadcastToAll("Please supply a nickname for this save.", { 0.9, 0.2, 0.2 })
else
--Nickname exists
if findInImageDataIndex(url, nickname) == nil then
--Save doesn't exist already
table.insert(tableImageData, {url=url, name=nickname})
broadcastToAll("Image URL saved to memory.", {0.2,0.9,0.2})
--Refresh buttons
self.clearButtons()
createOpenCloseButton()
createSurfaceButtons()
createScaleButtons()
else
--Save exists already
broadcastToAll("Memory already contains a save with this Name or URL. Delete it first.", {0.9,0.2,0.2})
end
end
end
end
--Loads table surface
function click_loadMemory(_, color, index)
if permissionCheck(color) then
self.editInput({index=0, value=tableImageData[index].name})
self.editInput({index=1, value=tableImageData[index].url})
updateSurface()
broadcastToAll("Table Image Loaded", {0.2,0.9,0.2})
end
end
--Deletes table surface
function click_deleteMemory(_, color, index)
if permissionCheck(color) then
table.remove(tableImageData, index)
if findInImageDataIndex(url, nickname) == nil then
--Save doesn't exist already
table.insert(tableImageData, { url = url, name = nickname })
broadcastToAll("Image URL saved to memory.", { 0.2, 0.9, 0.2 })
--Refresh buttons
self.clearButtons()
createOpenCloseButton()
createSurfaceButtons()
createScaleButtons()
broadcastToAll("Element Removed from Memory", {0.2,0.9,0.2})
else
--Save exists already
broadcastToAll("Memory already contains a save with this Name or URL. Delete it first.", { 0.9, 0.2, 0.2 })
end
end
end
end
--Loads table surface
function click_loadMemory(_, color, index)
if permissionCheck(color) then
self.editInput({ index = 0, value = tableImageData[index].name })
self.editInput({ index = 1, value = tableImageData[index].url })
updateSurface()
broadcastToAll("Table Image Loaded", { 0.2, 0.9, 0.2 })
end
end
--Deletes table surface
function click_deleteMemory(_, color, index)
if permissionCheck(color) then
table.remove(tableImageData, index)
self.clearButtons()
createOpenCloseButton()
createSurfaceButtons()
createScaleButtons()
broadcastToAll("Element Removed from Memory", { 0.2, 0.9, 0.2 })
end
end
--Updates surface from the values in the input field
function updateSurface()
local customInfo = obj_surface.getCustomObject()
customInfo.diffuse = self.getInputs()[2].value
obj_surface.setCustomObject(customInfo)
obj_surface = obj_surface.reload()
local customInfo = obj_surface.getCustomObject()
customInfo.diffuse = self.getInputs()[2].value
obj_surface.setCustomObject(customInfo)
obj_surface = obj_surface.reload()
end
--Table Scale control
--Applies Scale to table pieces
function click_applyScale(_, color)
if permissionCheck(color) then
local newWidth = tonumber(self.getInputs()[3].value)
local newDepth = tonumber(self.getInputs()[4].value)
if type(newWidth) ~= "number" then
broadcastToAll("Invalid Width", {0.9,0.2,0.2})
return
elseif type(newDepth) ~= "number" then
broadcastToAll("Invalid Depth", {0.9,0.2,0.2})
return
elseif newWidth<0.1 or newDepth<0.1 then
broadcastToAll("Scale cannot go below 0.1", {0.9,0.2,0.2})
return
elseif newWidth>12 or newDepth>12 then
broadcastToAll("Scale should not go over 12 (world size limitation)", {0.9,0.2,0.2})
return
else
changeTableScale(math.abs(newWidth), math.abs(newDepth))
broadcastToAll("Scale applied.", {0.2,0.9,0.2})
end
if permissionCheck(color) then
local newWidth = tonumber(self.getInputs()[3].value)
local newDepth = tonumber(self.getInputs()[4].value)
if type(newWidth) ~= "number" then
broadcastToAll("Invalid Width", { 0.9, 0.2, 0.2 })
return
elseif type(newDepth) ~= "number" then
broadcastToAll("Invalid Depth", { 0.9, 0.2, 0.2 })
return
elseif newWidth < 0.1 or newDepth < 0.1 then
broadcastToAll("Scale cannot go below 0.1", { 0.9, 0.2, 0.2 })
return
elseif newWidth > 12 or newDepth > 12 then
broadcastToAll("Scale should not go over 12 (world size limitation)", { 0.9, 0.2, 0.2 })
return
else
changeTableScale(math.abs(newWidth), math.abs(newDepth))
broadcastToAll("Scale applied.", { 0.2, 0.9, 0.2 })
end
end
end
--Checks/unchecks move box for hands
function click_checkMove(_, color)
if permissionCheck(color) then
local find_func = function(o) return o.click_function=="click_checkMove" end
if checkData.move == true then
checkData.move = false
local buttonEntry = findButton(self, find_func)
self.editButton({index=buttonEntry.index, label=""})
else
checkData.move = true
local buttonEntry = findButton(self, find_func)
self.editButton({index=buttonEntry.index, label=string.char(10008)})
end
if permissionCheck(color) then
local find_func = function(o) return o.click_function == "click_checkMove" end
if checkData.move == true then
checkData.move = false
local buttonEntry = findButton(self, find_func)
self.editButton({ index = buttonEntry.index, label = "" })
else
checkData.move = true
local buttonEntry = findButton(self, find_func)
self.editButton({ index = buttonEntry.index, label = string.char(10008) })
end
end
end
--Checks/unchecks scale box for hands
@ -206,273 +190,343 @@ end
--Alters scale of elements and moves them
function changeTableScale(width, depth)
--Scaling factors used to translate scale to position offset
local width2pos = (width-1) * 18
local depth2pos = (depth-1) * 18
--Scaling factors used to translate scale to position offset
local width2pos = (width - 1) * 18
local depth2pos = (depth - 1) * 18
--Hand zone movement
if checkData.move == true then
for _, pc in ipairs(ref_playerColor) do
if Player[pc].getHandCount() > 0 then
moveHandZone(Player[pc], width2pos, depth2pos)
end
end
--Hand zone movement
if checkData.move == true then
for _, pc in ipairs(ref_playerColor) do
if Player[pc].getHandCount() > 0 then
moveHandZone(Player[pc], width2pos, depth2pos)
end
end
--Hand zone scaling
--The button to enable this was disabled for technical reasons
if checkData.scale == true then
for _, pc in ipairs(ref_playerColor) do
if Player[pc].getHandCount() > 0 then
scaleHandZone(Player[pc], width, depth)
end
end
end
--Hand zone scaling
--The button to enable this was disabled for technical reasons
if checkData.scale == true then
for _, pc in ipairs(ref_playerColor) do
if Player[pc].getHandCount() > 0 then
scaleHandZone(Player[pc], width, depth)
end
end
end
--Resizing table elements
obj_side_top.setScale({width, 1, 1})
obj_side_bot.setScale({width, 1, 1})
obj_side_lef.setScale({depth, 1, 1})
obj_side_rig.setScale({depth, 1, 1})
obj_surface.setScale({width, 1, depth})
--Resizing table elements
obj_side_top.setScale({ width, 1, 1 })
obj_side_bot.setScale({ width, 1, 1 })
obj_side_lef.setScale({ depth, 1, 1 })
obj_side_rig.setScale({ depth, 1, 1 })
obj_surface.setScale({ width, 1, depth })
--Moving table elements to accomodate new scale
obj_side_lef.setPosition({-width2pos,tableHeightOffset,0})
obj_side_rig.setPosition({ width2pos,tableHeightOffset,0})
obj_side_top.setPosition({0,tableHeightOffset, depth2pos})
obj_side_bot.setPosition({0,tableHeightOffset,-depth2pos})
obj_leg1.setPosition({-width2pos,tableHeightOffset,-depth2pos})
obj_leg2.setPosition({-width2pos,tableHeightOffset, depth2pos})
obj_leg3.setPosition({ width2pos,tableHeightOffset, depth2pos})
obj_leg4.setPosition({ width2pos,tableHeightOffset,-depth2pos})
self.setPosition(obj_leg4.positionToWorld({-22.12, 8.74,-19.16}))
--Only enabled when changing tableHeightOffset
--obj_surface.setPosition({0,tableHeightOffset,0})
--Moving table elements to accomodate new scale
obj_side_lef.setPosition({ -width2pos, tableHeightOffset, 0 })
obj_side_rig.setPosition({ width2pos, tableHeightOffset, 0 })
obj_side_top.setPosition({ 0, tableHeightOffset, depth2pos })
obj_side_bot.setPosition({ 0, tableHeightOffset, -depth2pos })
obj_leg1.setPosition({ -width2pos, tableHeightOffset, -depth2pos })
obj_leg2.setPosition({ -width2pos, tableHeightOffset, depth2pos })
obj_leg3.setPosition({ width2pos, tableHeightOffset, depth2pos })
obj_leg4.setPosition({ width2pos, tableHeightOffset, -depth2pos })
self.setPosition(obj_leg4.positionToWorld({ -22.12, 8.74, -19.16 }))
--Only enabled when changing tableHeightOffset
--obj_surface.setPosition({0,tableHeightOffset,0})
end
--Move hand zone, p=player reference, facts are scaling factors
function moveHandZone(p, width2pos, depth2pos)
local widthX = obj_side_rig.getPosition().x
local depthZ = obj_side_top.getPosition().z
for i=1, p.getHandCount() do
local handT = p.getHandTransform()
local pos = handT.position
local y = handT.rotation.y
local widthX = obj_side_rig.getPosition().x
local depthZ = obj_side_top.getPosition().z
for i = 1, p.getHandCount() do
local handT = p.getHandTransform()
local pos = handT.position
local y = handT.rotation.y
if y<45 or y>320 or y>135 and y<225 then
if pos.z > 0 then
pos.z = pos.z + depth2pos - depthZ
else
pos.z = pos.z - depth2pos + depthZ
end
else
if pos.x > 0 then
pos.x = pos.x + width2pos - widthX
else
pos.x = pos.x - width2pos + widthX
end
end
--Only enabled when changing tableHeightOffset
--pos.y = tableHeightOffset + 14
handT.position = pos
p.setHandTransform(handT, i)
if y < 45 or y > 320 or y > 135 and y < 225 then
if pos.z > 0 then
pos.z = pos.z + depth2pos - depthZ
else
pos.z = pos.z - depth2pos + depthZ
end
else
if pos.x > 0 then
pos.x = pos.x + width2pos - widthX
else
pos.x = pos.x - width2pos + widthX
end
end
end
--Only enabled when changing tableHeightOffset
--pos.y = tableHeightOffset + 14
handT.position = pos
p.setHandTransform(handT, i)
end
end
---Scales hand zones, p=player reference, facts are scaling factors
function scaleHandZone(p, width, depth)
local widthFact = width / obj_side_top.getScale().x
local depthFact = depth / obj_side_lef.getScale().x
for i=1, p.getHandCount() do
local handT = p.getHandTransform()
local scale = handT.scale
local y = handT.rotation.y
if y<45 or y>320 or y>135 and y<225 then
scale.x = scale.x * widthFact
else
scale.x = scale.x * depthFact
end
handT.scale = scale
p.setHandTransform(handT, i)
local widthFact = width / obj_side_top.getScale().x
local depthFact = depth / obj_side_lef.getScale().x
for i = 1, p.getHandCount() do
local handT = p.getHandTransform()
local scale = handT.scale
local y = handT.rotation.y
if y < 45 or y > 320 or y > 135 and y < 225 then
scale.x = scale.x * widthFact
else
scale.x = scale.x * depthFact
end
handT.scale = scale
p.setHandTransform(handT, i)
end
end
--Information gathering
--Checks if a color is promoted or host
function permissionCheck(color)
if Player[color].host==true or Player[color].promoted==true then
return true
else
return false
end
if Player[color].host == true or Player[color].promoted == true then
return true
else
return false
end
end
--Locates a string saved within memory file
function findInImageDataIndex(...)
for _, str in ipairs({...}) do
for i, v in ipairs(tableImageData) do
if v.url == str or v.name == str then
return i
end
end
for _, str in ipairs({ ... }) do
for i, v in ipairs(tableImageData) do
if v.url == str or v.name == str then
return i
end
end
return nil
end
return nil
end
--Round number (num) to the Nth decimal (dec)
function round(num, dec)
local mult = 10^(dec or 0)
local mult = 10 ^ (dec or 0)
return math.floor(num * mult + 0.5) / mult
end
--Locates a button with a helper function
function findButton(obj, func)
if func==nil then error("No func supplied to findButton") end
for _, v in ipairs(obj.getButtons()) do
if func(v) then
return v
end
if func == nil then error("No func supplied to findButton") end
for _, v in ipairs(obj.getButtons()) do
if func(v) then
return v
end
return nil
end
return nil
end
--Creation of buttons/inputs
function createOpenCloseButton()
local tooltip = "Open Table Control Panel"
if controlActive then
tooltip = "Close Table Control Panel"
end
self.createButton({
click_function="click_toggleControl", function_owner=self,
position={0,0,0}, rotation={-45,0,0}, height=400, width=400,
color={1,1,1,0}, tooltip=tooltip
})
local tooltip = "Open Table Control Panel"
if controlActive then
tooltip = "Close Table Control Panel"
end
self.createButton({
click_function = "click_toggleControl",
function_owner = self,
position = { 0, 0, 0 },
rotation = { -45, 0, 0 },
height = 400,
width = 400,
color = { 1, 1, 1, 0 },
tooltip = tooltip
})
end
function createSurfaceInput()
local currentURL = obj_surface.getCustomObject().diffuse
local nickname = ""
if findInImageDataIndex(currentURL) ~= nil then
nickname = tableImageData[findInImageDataIndex(currentURL)].name
end
self.createInput({
label="Nickname", input_function="none", function_owner=self,
alignment=3, position={0,0,2}, height=224, width=4000,
font_size=200, tooltip="Enter nickname for table image (only used for save)",
value=nickname
})
self.createInput({
label="URL", input_function="none", function_owner=self,
alignment=3, position={0,0,3}, height=224, width=4000,
font_size=200, tooltip="Enter URL for tabletop image",
value=currentURL
})
local currentURL = obj_surface.getCustomObject().diffuse
local nickname = ""
if findInImageDataIndex(currentURL) ~= nil then
nickname = tableImageData[findInImageDataIndex(currentURL)].name
end
self.createInput({
label = "Nickname",
input_function = "none",
function_owner = self,
alignment = 3,
position = { 0, 0, 2 },
height = 224,
width = 4000,
font_size = 200,
tooltip = "Enter nickname for table image (only used for save)",
value = nickname
})
self.createInput({
label = "URL",
input_function = "none",
function_owner = self,
alignment = 3,
position = { 0, 0, 3 },
height = 224,
width = 4000,
font_size = 200,
tooltip = "Enter URL for tabletop image",
value = currentURL
})
end
function createSurfaceButtons()
--Label
--Label
self.createButton({
label = "Tabletop Surface Image",
click_function = "none",
position = { 0, 0, 1 },
height = 0,
width = 0,
font_size = 300,
font_color = { 1, 1, 1 }
})
--Functional
self.createButton({
label = "Apply Image\nTo Table",
click_function = "click_applySurface",
function_owner = self,
tooltip = "Apply URL as table image",
position = { 2, 0, 4 },
height = 440,
width = 1400,
font_size = 200,
})
self.createButton({
label = "Save Image\nTo Memory",
click_function = "click_saveSurface",
function_owner = self,
tooltip = "Record URL into memory (requires nickname)",
position = { -2, 0, 4 },
height = 440,
width = 1400,
font_size = 200,
})
--Label
self.createButton({
label = "Load From Memory",
click_function = "none",
position = { 0, 0, 5.5 },
height = 0,
width = 0,
font_size = 300,
font_color = { 1, 1, 1 }
})
--Saves, created dynamically from memory file
for i, memoryEntry in ipairs(tableImageData) do
--Load
local funcName = i .. "loadMemory"
local func = function(x, y) click_loadMemory(x, y, i) end
self.setVar(funcName, func)
self.createButton({
label="Tabletop Surface Image", click_function="none",
position={0,0,1}, height=0, width=0, font_size=300, font_color={1,1,1}
label = memoryEntry.name,
click_function = funcName,
function_owner = self,
tooltip = memoryEntry.url,
font_size = 200,
position = { -0.6, 0, 6.5 + 0.5 * (i - 1) },
height = 240,
width = 3300,
})
--Functional
--Delete
local funcName = i .. "deleteMemory"
local func = function(x, y) click_deleteMemory(x, y, i) end
self.setVar(funcName, func)
self.createButton({
label="Apply Image\nTo Table", click_function="click_applySurface",
function_owner=self, tooltip="Apply URL as table image",
position={2,0,4}, height=440, width=1400, font_size=200,
label = "DELETE",
click_function = funcName,
function_owner = self,
tooltip = "",
position = { 3.6, 0, 6.5 + 0.5 * (i - 1) },
height = 240,
width = 600,
font_size = 160,
font_color = { 1, 0, 0 },
color = { 0.8, 0.8, 0.8 }
})
self.createButton({
label="Save Image\nTo Memory", click_function="click_saveSurface",
function_owner=self, tooltip="Record URL into memory (requires nickname)",
position={-2,0,4}, height=440, width=1400, font_size=200,
})
--Label
self.createButton({
label="Load From Memory", click_function="none",
position={0,0,5.5}, height=0, width=0, font_size=300, font_color={1,1,1}
})
--Saves, created dynamically from memory file
for i, memoryEntry in ipairs(tableImageData) do
--Load
local funcName = i.."loadMemory"
local func = function(x,y) click_loadMemory(x,y,i) end
self.setVar(funcName, func)
self.createButton({
label=memoryEntry.name, click_function=funcName,
function_owner=self, tooltip=memoryEntry.url, font_size=200,
position={-0.6,0,6.5+0.5*(i-1)}, height=240, width=3300,
})
--Delete
local funcName = i.."deleteMemory"
local func = function(x,y) click_deleteMemory(x,y,i) end
self.setVar(funcName, func)
self.createButton({
label="DELETE", click_function=funcName,
function_owner=self, tooltip="",
position={3.6,0,6.5+0.5*(i-1)}, height=240, width=600,
font_size=160, font_color={1,0,0}, color={0.8,0.8,0.8}
})
end
end
end
function createScaleInput()
self.createInput({
label=string.char(8644), input_function="none", function_owner=self,
alignment=3, position={-8.5,0,2}, height=224, width=400,
font_size=200, tooltip="Table Width",
value=round(obj_side_top.getScale().x, 1)
})
self.createInput({
label=string.char(8645), input_function="none", function_owner=self,
alignment=3, position={-7.5,0,2}, height=224, width=400,
font_size=200, tooltip="Table Depth",
value=round(obj_side_lef.getScale().x, 1)
})
self.createInput({
label = string.char(8644),
input_function = "none",
function_owner = self,
alignment = 3,
position = { -8.5, 0, 2 },
height = 224,
width = 400,
font_size = 200,
tooltip = "Table Width",
value = round(obj_side_top.getScale().x, 1)
})
self.createInput({
label = string.char(8645),
input_function = "none",
function_owner = self,
alignment = 3,
position = { -7.5, 0, 2 },
height = 224,
width = 400,
font_size = 200,
tooltip = "Table Depth",
value = round(obj_side_lef.getScale().x, 1)
})
end
function createScaleButtons()
--Labels
self.createButton({
label="Table Scale", click_function="none",
position={-8,0,1}, height=0, width=0, font_size=300, font_color={1,1,1}
})
self.createButton({
label=string.char(8644).." "..string.char(8645),
click_function="none",
position={-8,0,2}, height=0, width=0, font_size=300, font_color={1,1,1}
})
self.createButton({
label="Move Hands:", click_function="none",
position={-8.3,0,3}, height=0, width=0, font_size=200, font_color={1,1,1}
})
--Disabled due to me removing the feature for technical reasons
--[[
--Labels
self.createButton({
label = "Table Scale",
click_function = "none",
position = { -8, 0, 1 },
height = 0,
width = 0,
font_size = 300,
font_color = { 1, 1, 1 }
})
self.createButton({
label = string.char(8644) .. " " .. string.char(8645),
click_function = "none",
position = { -8, 0, 2 },
height = 0,
width = 0,
font_size = 300,
font_color = { 1, 1, 1 }
})
self.createButton({
label = "Move Hands:",
click_function = "none",
position = { -8.3, 0, 3 },
height = 0,
width = 0,
font_size = 200,
font_color = { 1, 1, 1 }
})
--Disabled due to me removing the feature for technical reasons
--[[
self.createButton({
label="Scale Hands:", click_function="none",
position={-8.3,0,4}, height=0, width=0, font_size=200, font_color={1,1,1}
})
]]
--Checkboxes
local label = ""
if checkData.move == true then label = string.char(10008) end
self.createButton({
label=label, click_function="click_checkMove",
function_owner=self, tooltip="Check to move hands when table is rescaled",
position={-6.8,0,3}, height=224, width=224, font_size=200,
})
--[[
--Checkboxes
local label = ""
if checkData.move == true then label = string.char(10008) end
self.createButton({
label = label,
click_function = "click_checkMove",
function_owner = self,
tooltip = "Check to move hands when table is rescaled",
position = { -6.8, 0, 3 },
height = 224,
width = 224,
font_size = 200,
})
--[[
local label = ""
if checkData.scale == true then label = string.char(10008) end
self.createButton({
@ -481,31 +535,29 @@ function createScaleButtons()
position={-6.8,0,4}, height=224, width=224, font_size=200,
})
]]
--Apply button
self.createButton({
label="Apply Scale", click_function="click_applyScale",
function_owner=self, tooltip="Apply width/depth to table",
position={-8,0,4}, height=440, width=1400, font_size=200,
})
--Apply button
self.createButton({
label = "Apply Scale",
click_function = "click_applyScale",
function_owner = self,
tooltip = "Apply width/depth to table",
position = { -8, 0, 4 },
height = 440,
width = 1400,
font_size = 200,
})
end
--Data tables
ref_noninteractable = {
"afc863","c8edca","393bf7","12c65e","f938a2","9f95fd","35b95f",
"5af8f2","4ee1f2","bd69bd"
"afc863", "c8edca", "393bf7", "12c65e", "f938a2", "9f95fd", "35b95f",
"5af8f2", "4ee1f2", "bd69bd"
}
ref_playerColor = {
"White", "Brown", "Red", "Orange", "Yellow",
"Green", "Teal", "Blue", "Purple", "Pink", "Black"
"White", "Brown", "Red", "Orange", "Yellow",
"Green", "Teal", "Blue", "Purple", "Pink", "Black"
}
--Dummy function, absorbs unwanted triggers

View File

@ -1 +1 @@
{"acknowledgedUpgradeVersions":[],"chaosTokensGUID":[],"optionPanel":{"cardLanguage":"en","changePlayAreaImage":false,"enableCardHelpers":false,"playAreaConnectionColor":{"a":1,"b":0.4,"g":0.4,"r":0.4},"playAreaConnections":true,"playAreaSnapTags":true,"showAttachmentHelper":false,"showCleanUpHelper":false,"showCYOA":false,"showDisplacementTool":false,"showDrawButton":false,"showHandHelper":false,"showSearchAssistant":false,"showTitleSplash":true,"useClueClickers":false,"useResourceCounters":"disabled","useSnapTags":true}}
{"acknowledgedUpgradeVersions":[],"chaosTokensGUID":[],"optionPanel":{"cardLanguage":"en","changePlayAreaImage":false,"enableCardHelpers":false,"playAreaConnectionColor":{"a":1,"b":0.4,"g":0.4,"r":0.4},"playAreaConnections":true,"playAreaSnapTags":true,"showAttachmentHelper":false,"showCleanUpHelper":false,"showCYOA":false,"showDisplacementTool":false,"showDrawButton":false,"showHandHelper":false,"showSearchAssistant":false,"showTitleSplash":true,"useClassTexture":true,"useClueClickers":false,"useResourceCounters":"disabled","useSnapTags":true}}

View File

@ -22,7 +22,7 @@
"ImageURL": "http://cloud-3.steamusercontent.com/ugc/1915746489209870095/5F6A6F2946DBEB81667C15B112F9E35943E61A97/",
"WidthScale": 0
},
"Description": "Moves all objects on the playmat in the chosen direction.",
"Description": "Moves all objects on the playermat in the chosen direction.",
"DragSelectable": true,
"GMNotes": "",
"GUID": "0f1374",

View File

@ -22,7 +22,7 @@
"ImageURL": "http://cloud-3.steamusercontent.com/ugc/1838053776205435595/ECFB88938ADBD1EF7AEF713111A11330FD9FAA5A/",
"WidthScale": 0
},
"Description": "Searches the top X cards of the nearest playmat by setting your hand aside and putting the cards into your hand.\n\nPut the target of your search on your set aside hand.",
"Description": "Searches the top X cards of the nearest playermat by setting your hand aside and putting the cards into your hand.\n\nPut the target of your search on your set aside hand.",
"DragSelectable": true,
"GMNotes": "",
"GUID": "17aed0",

View File

@ -22,7 +22,7 @@
"ImageURL": "https://i.imgur.com/gs1mtXJ.png",
"WidthScale": 0
},
"Description": "Allows changing of the playmat image. Provide URL to the image or leave empty for default image.",
"Description": "Allows changing of the playarea image. Provide URL to the image or leave empty for default image.",
"DragSelectable": true,
"GMNotes": "",
"GUID": "b7b45b",
@ -37,7 +37,7 @@
"LuaScriptState": "{\"selectionIndex\":1,\"typeIndex\":1}",
"MeasureMovement": false,
"Name": "Custom_Token",
"Nickname": "Playmat Image Swapper",
"Nickname": "PlayArea Image Swapper",
"Snap": true,
"Sticky": true,
"Tags": [

View File

@ -353,7 +353,7 @@
"IgnoreFoW": false,
"LayoutGroupSortIndex": 0,
"Locked": true,
"LuaScript": "require(\"playermat/Playmat\")",
"LuaScript": "require(\"playermat/Playermat\")",
"LuaScriptState_path": "Playermat1White.8b081b.luascriptstate",
"MeasureMovement": false,
"Memo": "White",

View File

@ -1 +1 @@
{"activeInvestigatorClass":"Neutral","activeInvestigatorId":"00000","isDrawButtonVisible":false,"playerColor":"White","slotData":["any","any","any","Tarot","Hand (left)","Hand (right)","Ally","any","any","any","Accessory","Arcane","Arcane","Body"]}
{"activeInvestigatorClass":"Neutral","activeInvestigatorId":"00000","isClassTextureEnabled":true,"isDrawButtonVisible":false,"playerColor":"White","slotData":["any","any","any","Tarot","Hand (left)","Hand (right)","Ally","any","any","any","Accessory","Arcane","Arcane","Body"]}

View File

@ -353,7 +353,7 @@
"IgnoreFoW": false,
"LayoutGroupSortIndex": 0,
"Locked": true,
"LuaScript": "require(\"playermat/Playmat\")",
"LuaScript": "require(\"playermat/Playermat\")",
"LuaScriptState_path": "Playermat2Orange.bd0ff4.luascriptstate",
"MeasureMovement": false,
"Memo": "Orange",

View File

@ -1 +1 @@
{"activeInvestigatorClass":"Neutral","activeInvestigatorId":"00000","isDrawButtonVisible":false,"playerColor":"Orange","slotData":["any","any","any","Tarot","Hand (left)","Hand (right)","Ally","any","any","any","Accessory","Arcane","Arcane","Body"]}
{"activeInvestigatorClass":"Neutral","activeInvestigatorId":"00000","isClassTextureEnabled":true,"isDrawButtonVisible":false,"playerColor":"Orange","slotData":["any","any","any","Tarot","Hand (left)","Hand (right)","Ally","any","any","any","Accessory","Arcane","Arcane","Body"]}

View File

@ -353,7 +353,7 @@
"IgnoreFoW": false,
"LayoutGroupSortIndex": 0,
"Locked": true,
"LuaScript": "require(\"playermat/Playmat\")",
"LuaScript": "require(\"playermat/Playermat\")",
"LuaScriptState_path": "Playermat3Green.383d8b.luascriptstate",
"MeasureMovement": false,
"Memo": "Green",

View File

@ -1 +1 @@
{"activeInvestigatorClass":"Neutral","activeInvestigatorId":"00000","isDrawButtonVisible":false,"playerColor":"Green","slotData":["any","any","any","Tarot","Hand (left)","Hand (right)","Ally","any","any","any","Accessory","Arcane","Arcane","Body"]}
{"activeInvestigatorClass":"Neutral","activeInvestigatorId":"00000","isClassTextureEnabled":true,"isDrawButtonVisible":false,"playerColor":"Green","slotData":["any","any","any","Tarot","Hand (left)","Hand (right)","Ally","any","any","any","Accessory","Arcane","Arcane","Body"]}

View File

@ -353,7 +353,7 @@
"IgnoreFoW": false,
"LayoutGroupSortIndex": 0,
"Locked": true,
"LuaScript": "require(\"playermat/Playmat\")",
"LuaScript": "require(\"playermat/Playermat\")",
"LuaScriptState_path": "Playermat4Red.0840d5.luascriptstate",
"MeasureMovement": false,
"Memo": "Red",

View File

@ -1 +1 @@
{"activeInvestigatorClass":"Neutral","activeInvestigatorId":"00000","isDrawButtonVisible":false,"playerColor":"Red","slotData":["any","any","any","Tarot","Hand (left)","Hand (right)","Ally","any","any","any","Accessory","Arcane","Arcane","Body"]}
{"activeInvestigatorClass":"Neutral","activeInvestigatorId":"00000","isClassTextureEnabled":true,"isDrawButtonVisible":false,"playerColor":"Red","slotData":["any","any","any","Tarot","Hand (left)","Hand (right)","Ally","any","any","any","Accessory","Arcane","Arcane","Body"]}

View File

@ -41,7 +41,7 @@
"LayoutGroupSortIndex": 0,
"Locked": false,
"LuaScript": "require(\"core/UniversalActionAbilityToken\")",
"LuaScriptState": "",
"LuaScriptState": "{\"class\":\"Neutral\",\"symbol\":\"Neutral\"}",
"MeasureMovement": false,
"Memo": "universalActionAbility",
"Name": "Custom_Tile",

View File

@ -4,7 +4,7 @@ local deckImporterApi = require("arkhamdb/DeckImporterApi")
local guidReferenceApi = require("core/GUIDReferenceApi")
local optionPanelApi = require("core/OptionPanelApi")
local playAreaApi = require("core/PlayAreaApi")
local playmatApi = require("playermat/PlaymatApi")
local playermatApi = require("playermat/PlayermatApi")
-- base data for token creation
local campaignTokenData = {
@ -95,7 +95,7 @@ function importFromToken(coin)
Wait.condition(
function()
local campaignBox = getObjectFromGUID(importData["box"])
campaignBox = getObjectFromGUID(importData["box"])
if #campaignBox.getObjects() > 0 then
placeCampaignFromToken(importData, coin)
else
@ -103,11 +103,11 @@ function importFromToken(coin)
end
end,
function()
local obj = getObjectFromGUID(importData["box"])
if obj == nil then
campaignBox = getObjectFromGUID(importData["box"])
if campaignBox == nil then
return false
else
return obj.type == "Bag"
return campaignBox.type == "Bag"
end
end,
2,
@ -190,10 +190,10 @@ function restoreCampaignData(importData, coin)
playAreaApi.updateSurface(importData["playarea"])
playAreaApi.setInvestigatorCount(importData["clueCount"])
-- restore Playmat slots
-- restore playermat slots
if importData["slotData"] then
for matColor, slotData in pairs(importData["slotData"]) do
playmatApi.loadSlotData(matColor, slotData)
playermatApi.loadSlotData(matColor, slotData)
end
end
@ -272,10 +272,10 @@ function createCampaignToken(_, playerColor, _)
table.insert(campaignTokenData.ContainedObjects, indexData)
end
-- get the slot symbol data for each playmat (use GUIDReferenceApi to only get this for existing playmats)
-- get the slot symbol data for each playermat (use GUIDReferenceApi to only get this for existing playermats)
campaignData.slotData = {}
for matColor, _ in pairs(guidReferenceApi.getObjectsByType("Playermat")) do
local slotData = playmatApi.getSlotData(matColor)
local slotData = playermatApi.getSlotData(matColor)
campaignData.slotData[matColor] = slotData
end
@ -306,7 +306,7 @@ end
function setTrauma(trauma)
for i, matColor in ipairs({ "White", "Orange", "Green", "Red" }) do
playmatApi.updateCounter(matColor, "DamageCounter", trauma[i])
playmatApi.updateCounter(matColor, "HorrorCounter", trauma[i + 4])
playermatApi.updateCounter(matColor, "DamageCounter", trauma[i])
playermatApi.updateCounter(matColor, "HorrorCounter", trauma[i + 4])
end
end

View File

@ -1,6 +1,6 @@
-- Cleans up the table for the next scenario in a campaign:
-- sets counters to default values (resources and doom) or trauma values (health and sanity, if not disabled) from campaign log
-- puts everything on playmats and hands into respective trashcans
-- puts everything on playermats and hands into respective trashcans
-- use the IGNORE_TAG to exclude objects from tidying (default: "CleanUpHelper_Ignore")
local blessCurseManagerApi = require("chaosbag/BlessCurseManagerApi")
@ -8,7 +8,7 @@ local chaosBagApi = require("chaosbag/ChaosBagApi")
local guidReferenceApi = require("core/GUIDReferenceApi")
local mythosAreaApi = require("core/MythosAreaApi")
local playAreaApi = require("core/PlayAreaApi")
local playmatApi = require("playermat/PlaymatApi")
local playermatApi = require("playermat/PlayermatApi")
local searchLib = require("util/SearchLib")
local soundCubeApi = require("core/SoundCubeApi")
local tokenSpawnTrackerApi = require("core/token/TokenSpawnTrackerApi")
@ -28,9 +28,9 @@ options["importTrauma"] = true
options["tidyPlayermats"] = true
options["removeDrawnLines"] = false
-- don't clean playmats for preludes
-- don't clean playermats for preludes
local scenarioName
local preludeList = {
local preludeList = {
["Prelude: Welcome to Hemlock Vale!"] = true
}
@ -149,13 +149,13 @@ end
function updateCounters()
if not getOptionValue() then return end
playmatApi.updateCounter("All", "ResourceCounter", 5)
playmatApi.updateCounter("All", "ClickableClueCounter", 0)
playmatApi.resetSkillTracker("All")
playermatApi.updateCounter("All", "ResourceCounter", 5)
playermatApi.updateCounter("All", "ClickableClueCounter", 0)
playermatApi.resetSkillTracker("All")
for i = 1, 4 do
playmatApi.updateCounter(COLORS[i], "DamageCounter", RESET_VALUES.Damage[i])
playmatApi.updateCounter(COLORS[i], "HorrorCounter", RESET_VALUES.Horror[i])
playermatApi.updateCounter(COLORS[i], "DamageCounter", RESET_VALUES.Damage[i])
playermatApi.updateCounter(COLORS[i], "HorrorCounter", RESET_VALUES.Horror[i])
end
end
@ -272,7 +272,7 @@ function discardHands()
for i = 1, 4 do
local trash = guidReferenceApi.getObjectByOwnerAndType(COLORS[i], "Trash")
if trash == nil then return end
local hand = Player[playmatApi.getPlayerColor(COLORS[i])].getHandObjects()
local hand = Player[playermatApi.getPlayerColor(COLORS[i])].getHandObjects()
for j = #hand, 1, -1 do
trash.putObject(hand[j])
end
@ -340,7 +340,7 @@ function tidyPlayerMatCoroutine()
-- get respective trash
local trash = guidReferenceApi.getObjectByOwnerAndType(COLORS[i], "Trash")
if trash == nil then
printToAll("Trashcan for " .. COLORS[i] .. " playmat could not be found! Skipping this playermat.", "Yellow")
printToAll("Trashcan for " .. COLORS[i] .. " playermat could not be found! Skipping this playermat.", "Yellow")
goto continue
end
@ -351,7 +351,7 @@ function tidyPlayerMatCoroutine()
local objList
if i < 5 then
objList = playmatApi.searchAroundPlaymat(COLORS[i])
objList = playermatApi.searchAroundPlayermat(COLORS[i])
else
-- Victory Display + Mythos Area
objList = searchLib.inArea({ -2, 2, 10 }, { 0, 270, 0 }, { 55, 1, 13.5 })

View File

@ -1,4 +1,4 @@
local playmatApi = require("playermat/PlaymatApi")
local playermatApi = require("playermat/PlayermatApi")
-- forward declaration of variables that are used across functions
local matColor, handColor, hovering
@ -36,7 +36,7 @@ function onLoad()
updateColors()
-- start loop to update card count
playmatApi.checkForDES(matColor)
playermatApi.checkForDES(matColor)
Wait.time(updateValue, 1, -1)
end
@ -49,7 +49,7 @@ function onObjectHover(hoverColor, object)
if object == self then
hovering = true
playmatApi.checkForDES(matColor)
playermatApi.checkForDES(matColor)
updateValue()
else
hovering = false
@ -58,8 +58,8 @@ end
-- updates the matcolor and handcolor variable
function updateColors()
matColor = playmatApi.getMatColorByPosition(self.getPosition())
handColor = playmatApi.getPlayerColor(matColor)
matColor = playermatApi.getMatColorByPosition(self.getPosition())
handColor = playermatApi.getPlayerColor(matColor)
self.setName(handColor .. " Hand Helper")
end
@ -74,7 +74,7 @@ function updateValue()
if Player[handColor].getHandCount() == 0 then return end
-- get state of "Dream-Enhancing Serum" from playermat
local hasDES = playmatApi.hasDES(matColor)
local hasDES = playermatApi.hasDES(matColor)
-- default to regular count if hovered
if hovering then
@ -113,5 +113,5 @@ end
-- discards a random non-hidden card from hand
function discardRandom()
playmatApi.doDiscardOne(matColor)
playermatApi.doDiscardOne(matColor)
end

View File

@ -11,9 +11,6 @@ local phaseImages = {
"http://cloud-3.steamusercontent.com/ugc/982233321870237261/C287CAED2423970F33E72D6C7415CBEC6794C533/"
}
-- these are intentionally global for remote updating
-- phaseId, broadcastChange
function onSave()
return JSON.encode({
phaseId = phaseId,
@ -21,11 +18,15 @@ function onSave()
})
end
function loadFromSaveTable(savedData)
for var, val in pairs(JSON.decode(savedData)) do
_G[var] = val
end
end
function onLoad(savedData)
if savedData and savedData ~= "" then
local loadedData = JSON.decode(savedData)
phaseId = loadedData.phaseId
broadcastChange = loadedData.broadcastChange
loadFromSaveTable(savedData)
else
phaseId = 1
broadcastChange = false

View File

@ -1,16 +1,16 @@
local deckLib = require("util/DeckLib")
local playmatApi = require("playermat/PlaymatApi")
local playermatApi = require("playermat/PlayermatApi")
local searchLib = require("util/SearchLib")
-- forward declaration of variables that are used across functions
local matColor, handColor, setAsidePosition, setAsideRotation, drawDeckPosition, topCardDetected
local quickParameters = {}
quickParameters.function_owner = self
quickParameters.font_size = 165
quickParameters.width = 275
quickParameters.height = 275
quickParameters.color = "White"
local quickParameters = {}
quickParameters.function_owner = self
quickParameters.font_size = 165
quickParameters.width = 275
quickParameters.height = 275
quickParameters.color = "White"
-- common parameters
local buttonParameters = {}
@ -20,17 +20,17 @@ buttonParameters.width = 650
buttonParameters.height = 225
buttonParameters.color = "White"
local inputParameters = {}
inputParameters.function_owner = self
inputParameters.input_function = "updateSearchNumber"
inputParameters.tooltip = "custom search amount"
inputParameters.label = "#"
inputParameters.font_size = 175
inputParameters.width = 400
inputParameters.height = inputParameters.font_size + 23
inputParameters.position = { 0, 0.11, 0 }
inputParameters.alignment = 3
inputParameters.validation = 2
local inputParameters = {}
inputParameters.function_owner = self
inputParameters.input_function = "updateSearchNumber"
inputParameters.tooltip = "custom search amount"
inputParameters.label = "#"
inputParameters.font_size = 175
inputParameters.width = 400
inputParameters.height = inputParameters.font_size + 23
inputParameters.position = { 0, 0.11, 0 }
inputParameters.alignment = 3
inputParameters.validation = 2
function onLoad()
normalView()
@ -101,12 +101,12 @@ end
-- start the search (change UI, set handCards aside, draw cards)
function startSearch(messageColor, number)
matColor = playmatApi.getMatColorByPosition(self.getPosition())
handColor = playmatApi.getPlayerColor(matColor)
matColor = playermatApi.getMatColorByPosition(self.getPosition())
handColor = playermatApi.getPlayerColor(matColor)
topCardDetected = false
-- get draw deck
local deckAreaObjects = playmatApi.getDeckAreaObjects(matColor)
local deckAreaObjects = playermatApi.getDeckAreaObjects(matColor)
if deckAreaObjects.draw == nil then
printToColor(matColor .. " draw deck could not be found!", messageColor, "Red")
return
@ -117,17 +117,17 @@ function startSearch(messageColor, number)
drawDeckPosition = bounds.center + Vector(0, bounds.size.y / 2 + 0.2, 0)
printToColor("Place target(s) of search on set aside hand.", messageColor, "Green")
-- get playmat orientation
-- get playermat orientation
local offset = -15
if matColor == "Orange" or matColor == "Red" then
offset = 15
end
-- get position and rotation for set aside cards
local handData = Player[handColor].getHandTransform()
local handCards = Player[handColor].getHandObjects()
setAsidePosition = handData.position + offset * handData.right
setAsideRotation = { handData.rotation.x, handData.rotation.y + 180, 180 }
local handData = Player[handColor].getHandTransform()
local handCards = Player[handColor].getHandObjects()
setAsidePosition = handData.position + offset * handData.right
setAsideRotation = { handData.rotation.x, handData.rotation.y + 180, 180 }
-- set y-value
setAsidePosition.y = 1.5
@ -146,7 +146,7 @@ function startSearch(messageColor, number)
searchView()
Wait.time(function()
deckAreaObjects = playmatApi.getDeckAreaObjects(matColor)
deckAreaObjects = playermatApi.getDeckAreaObjects(matColor)
deckAreaObjects.draw.deal(number, handColor)
end, 1)
end
@ -175,7 +175,7 @@ function endSearch(_, _, isRightClick)
-- delay is to wait for cards to enter deck
if not isRightClick then
Wait.time(function()
local deckAreaObjects = playmatApi.getDeckAreaObjects(matColor)
local deckAreaObjects = playermatApi.getDeckAreaObjects(matColor)
if deckAreaObjects.draw then
deckAreaObjects.draw.shuffle()
end
@ -184,6 +184,6 @@ function endSearch(_, _, isRightClick)
-- Norman Withers handling
if topCardDetected then
Wait.time(function() playmatApi.flipTopCardFromDeck(matColor) end, #handCards * 0.3 + 0.75)
Wait.time(function() playermatApi.flipTopCardFromDeck(matColor) end, #handCards * 0.3 + 0.75)
end
end

View File

@ -1,277 +1,275 @@
local searchLib = require("util/SearchLib")
function onload(savedData)
revealCardPositions = {
Vector(3.5, 0.25, 0),
Vector(-3.5, 0.25, 0)
}
revealCardPositionsSwap = {
Vector(-3.5, 0.25, 0),
Vector(3.5, 0.25, 0)
}
self.createButton({
label = 'Underworld Market\nHelper',
click_function = "none",
function_owner = self,
position = {0,-0.1,-1.6},
height = 0,
width = 0,
font_size = 145,
font_color = {1,1,1}
})
hiddenCards = 10
hiddenCardLabel = '-----'
isSetup = false
movingCards = false
self.addContextMenuItem('Reset helper', resetHelper)
if savedData ~= '' then
local loaded_data = JSON.decode(savedData)
hiddenCards = loaded_data.saved_hiddenCards
isSetup = true
refreshButtons()
end
function onSave()
return JSON.encode({ saved_hiddenCards = hiddenCards })
end
function onSave()
return JSON.encode({
saved_hiddenCards = hiddenCards
})
function onload(savedData)
revealCardPositions = {
Vector(3.5, 0.25, 0),
Vector(-3.5, 0.25, 0)
}
revealCardPositionsSwap = {
Vector(-3.5, 0.25, 0),
Vector(3.5, 0.25, 0)
}
self.createButton({
label = 'Underworld Market\nHelper',
click_function = "none",
function_owner = self,
position = { 0, -0.1, -1.6 },
height = 0,
width = 0,
font_size = 145,
font_color = { 1, 1, 1 }
})
hiddenCards = 10
hiddenCardLabel = '-----'
isSetup = false
movingCards = false
self.addContextMenuItem('Reset helper', resetHelper)
if savedData and savedData ~= '' then
local loaded_data = JSON.decode(savedData)
hiddenCards = loaded_data.saved_hiddenCards
isSetup = true
refreshButtons()
end
end
function onObjectEnterContainer(container, object)
if container ~= self then return end
if container ~= self then return end
if isSetup and object.tag == "Card" then
refreshButtons()
end
if isSetup and object.tag == "Card" then
refreshButtons()
end
if object.tag == "Deck" then
if validateDeck(object) then
takeDeckOut(object.getGUID(), self.getPosition() + Vector(0, 0.1, 0))
refreshButtons()
isSetup = true
end
elseif object.tag ~= "Card" then
broadcastToAll("The 'Underworld Market Helper' is meant to be used for cards.", "White")
if object.tag == "Deck" then
if validateDeck(object) then
takeDeckOut(object.getGUID(), self.getPosition() + Vector(0, 0.1, 0))
refreshButtons()
isSetup = true
end
elseif object.tag ~= "Card" then
broadcastToAll("The 'Underworld Market Helper' is meant to be used for cards.", "White")
end
end
function onObjectLeaveContainer(container, object)
if container ~= self then return end
if isSetup then
refreshButtons()
end
if container ~= self then return end
if isSetup then
refreshButtons()
end
end
function validateDeck(deck)
if deck.getQuantity() ~= 10 then
print('Underworld Market Helper: Deck must include exactly 10 cards.')
return false
if deck.getQuantity() ~= 10 then
print('Underworld Market Helper: Deck must include exactly 10 cards.')
return false
end
local illicitCount = 0
for _, card in ipairs(deck.getObjects()) do
decodedGMNotes = JSON.decode(card.gm_notes)
if decodedGMNotes ~= nil and string.find(decodedGMNotes.traits, "Illicit", 1, true) then
illicitCount = illicitCount + 1
end
end
local illicitCount = 0
if illicitCount ~= 10 then
print('Underworld Market Helper: Deck must include 10 Illicit cards.')
return false
end
for _, card in ipairs(deck.getObjects()) do
decodedGMNotes = JSON.decode(card.gm_notes)
if decodedGMNotes ~= nil and string.find(decodedGMNotes.traits, "Illicit", 1, true) then
illicitCount = illicitCount + 1
end
end
if illicitCount ~= 10 then
print('Underworld Market Helper: Deck must include 10 Illicit cards.')
return false
end
return true
return true
end
function refreshButtons()
local cardsList = ''
local cardsList = ''
for i, card in ipairs(self.getObjects()) do
local localCardName = card.name
for i, card in ipairs(self.getObjects()) do
local localCardName = card.name
if i <= hiddenCards then
localCardName = hiddenCardLabel
end
cardsList = cardsList .. localCardName .. '\n'
if i <= hiddenCards then
localCardName = hiddenCardLabel
end
self.clearButtons()
cardsList = cardsList .. localCardName .. '\n'
end
self.createButton({
label = 'Market Deck:',
click_function = "none",
function_owner = self,
position = {0,-0.1,-1.6},
height = 0,
width = 0,
font_size = 150,
font_color = {1,1,1}
})
self.clearButtons()
self.createButton({
label = cardsList,
click_function = "none",
function_owner = self,
position = {0,-0.1,0.15},
height = 0,
width = 0,
font_size = 115,
font_color = {1,1,1}
})
self.createButton({
label = 'Market Deck:',
click_function = "none",
function_owner = self,
position = { 0, -0.1, -1.6 },
height = 0,
width = 0,
font_size = 150,
font_color = { 1, 1, 1 }
})
self.createButton({
click_function = 'revealFirstTwoCards',
function_owner = self,
label = 'Reveal',
position = {-0.85,0,1.6},
width = 375,
height = 175,
font_size = 90
})
self.createButton({
label = cardsList,
click_function = "none",
function_owner = self,
position = { 0, -0.1, 0.15 },
height = 0,
width = 0,
font_size = 115,
font_color = { 1, 1, 1 }
})
self.createButton({
click_function = 'swap',
function_owner = self,
label = 'Swap',
position = {0,0,1.6},
width = 375,
height = 175,
font_size = 90
})
self.createButton({
click_function = 'revealFirstTwoCards',
function_owner = self,
label = 'Reveal',
position = { -0.85, 0, 1.6 },
width = 375,
height = 175,
font_size = 90
})
self.createButton({
click_function = 'finish',
function_owner = self,
label = 'Finish',
position = {0.85,0,1.6},
width = 375,
height = 175,
font_size = 90
})
self.createButton({
click_function = 'swap',
function_owner = self,
label = 'Swap',
position = { 0, 0, 1.6 },
width = 375,
height = 175,
font_size = 90
})
self.createButton({
click_function = 'finish',
function_owner = self,
label = 'Finish',
position = { 0.85, 0, 1.6 },
width = 375,
height = 175,
font_size = 90
})
end
function takeDeckOut(guid, pos)
local deck = self.takeObject({ guid = guid, position = pos, smooth = false })
local deck = self.takeObject({ guid = guid, position = pos, smooth = false })
for i = 1, #deck.getObjects() do
self.putObject(deck.takeObject({ position = pos + Vector(0, 0.1 * i, 0), smooth = false }))
end
for i = 1, #deck.getObjects() do
self.putObject(deck.takeObject({ position = pos + Vector(0, 0.1 * i, 0), smooth = false }))
end
self.shuffle()
self.shuffle()
end
function getRevealedCards()
local revealedCards = {}
local revealedCards = {}
for _, pos in ipairs(revealCardPositions) do
for _, obj in ipairs(searchLib.atPosition(self.positionToWorld(pos), "isCard")) do
table.insert(revealedCards, obj.getGUID())
end
for _, pos in ipairs(revealCardPositions) do
for _, obj in ipairs(searchLib.atPosition(self.positionToWorld(pos), "isCard")) do
table.insert(revealedCards, obj.getGUID())
end
end
return revealedCards
return revealedCards
end
function revealFirstTwoCards()
if movingCards or #getRevealedCards() > 0 then return end
if movingCards or #getRevealedCards() > 0 then return end
for i, card in ipairs(self.getObjects()) do
movingCards = true
for i, card in ipairs(self.getObjects()) do
movingCards = true
self.takeObject({
index = 0,
rotation = self.getRotation(),
position = self.positionToWorld(revealCardPositions[i]),
callback_function = function(obj)
obj.resting = true
movingCards = false
end
})
self.takeObject({
index = 0,
rotation = self.getRotation(),
position = self.positionToWorld(revealCardPositions[i]),
callback_function = function(obj)
obj.resting = true
movingCards = false
end
})
hiddenCards = hiddenCards - 1
hiddenCards = hiddenCards - 1
if i == 2 or #self.getObjects() == 0 then
break
end
if i == 2 or #self.getObjects() == 0 then
break
end
end
refreshButtons()
refreshButtons()
end
function swap()
if movingCards then return end
if movingCards then return end
local revealedCards = getRevealedCards()
local revealedCards = getRevealedCards()
if #revealedCards == 2 then
for i, revealedCardGUID in ipairs(revealedCards) do
local revealedCard = getObjectFromGUID(revealedCardGUID)
if #revealedCards == 2 then
for i, revealedCardGUID in ipairs(revealedCards) do
local revealedCard = getObjectFromGUID(revealedCardGUID)
revealedCard.setPositionSmooth(self.positionToWorld(revealCardPositionsSwap[i]), false, false)
end
revealedCard.setPositionSmooth(self.positionToWorld(revealCardPositionsSwap[i]), false, false)
end
end
end
function finish()
if movingCards then return end
if movingCards then return end
local revealedCards = getRevealedCards()
local revealedCards = getRevealedCards()
movingCards = true
movingCards = true
for i, revealedCardGUID in ipairs(revealedCards) do
self.putObject(getObjectFromGUID(revealedCardGUID))
end
for i, revealedCardGUID in ipairs(revealedCards) do
self.putObject(getObjectFromGUID(revealedCardGUID))
end
Wait.time(
function()
movingCards = false
end,
Wait.time(
function()
movingCards = false
end,
0.75)
end
function resetHelper()
for i, card in ipairs(self.getObjects()) do
self.takeObject({
index = 0,
smooth = false,
rotation = self.getRotation(),
position = self.positionToWorld(revealCardPositions[2])
})
end
self.clearButtons()
self.createButton({
label = 'Underworld Market\nHelper',
click_function = "none",
function_owner = self,
position = {0,-0.1,-1.6},
height = 0,
width = 0,
font_size = 145,
font_color = {1,1,1}
for i, card in ipairs(self.getObjects()) do
self.takeObject({
index = 0,
smooth = false,
rotation = self.getRotation(),
position = self.positionToWorld(revealCardPositions[2])
})
end
hiddenCards = 10
isSetup = false
movingCards = false
self.clearButtons()
self.reset()
self.createButton({
label = 'Underworld Market\nHelper',
click_function = "none",
function_owner = self,
position = { 0, -0.1, -1.6 },
height = 0,
width = 0,
font_size = 145,
font_color = { 1, 1, 1 }
})
print('Underworld Market Helper: Helper has been reset.')
hiddenCards = 10
isSetup = false
movingCards = false
self.reset()
print('Underworld Market Helper: Helper has been reset.')
end

View File

@ -482,7 +482,6 @@ do
---@param uri table
---@param on_success fun(status, vararg): boolean, any
---@param on_error nil|fun(status, vararg): string
---@vararg any
---@return Request
function Request.start(uri, on_success, on_error, ...)
local parameters = table.pack(...)
@ -497,7 +496,6 @@ do
---@param requests Request[]
---@param on_success fun(content: any, vararg: any)
---@param on_error fun(requests: Request, vararg: any)|nil
---@vararg any
function Request.with_all(requests, on_success, on_error, ...)
local parameters = table.pack(...)

View File

@ -3,7 +3,7 @@ require("playercards/PlayerCardSpawner")
local allCardsBagApi = require("playercards/AllCardsBagApi")
local arkhamDb = require("arkhamdb/ArkhamDb")
local guidReferenceApi = require("core/GUIDReferenceApi")
local playmatApi = require("playermat/PlaymatApi")
local playermatApi = require("playermat/PlayermatApi")
local zones = require("playermat/Zones")
local matsWithInvestigator = {}
@ -189,7 +189,7 @@ end
function loadDecks()
if not allCardsBagApi.isIndexReady() then return end
matsWithInvestigator = playmatApi.getUsedMatColors()
matsWithInvestigator = playermatApi.getUsedMatColors()
if redDeckId ~= nil and redDeckId ~= "" then
buildDeck("Red", redDeckId)
end
@ -354,7 +354,7 @@ end
---@param deck tts__Object Callback-provided spawned deck object
---@param playerColor string Color of the player to draw the cards to
function deckSpawned(deck, playerColor)
local player = Player[playmatApi.getPlayerColor(playerColor)]
local player = Player[playermatApi.getPlayerColor(playerColor)]
local handPos = player.getHandTransform(1).position -- Only one hand zone per player
local deckCards = deck.getData().ContainedObjects
@ -453,7 +453,7 @@ function removeBusyZones(playerColor, zoneDecks)
-- check for existing deck
local cardsInDeckArea = 0
for _, obj in pairs(playmatApi.getDeckAreaObjects(playerColor)) do
for _, obj in pairs(playermatApi.getDeckAreaObjects(playerColor)) do
cardsInDeckArea = cardsInDeckArea + #obj.getObjects()
end
@ -732,7 +732,7 @@ end
---@param resourceModifier number Modifier for the starting resources
function updateStartingResources(playerColor, resourceModifier)
if resourceModifier ~= 0 then
playmatApi.updateCounter(playerColor, "ResourceCounter", _, resourceModifier)
playermatApi.updateCounter(playerColor, "ResourceCounter", _, resourceModifier)
printToAll("Modified starting resources", playerColor)
end
end

View File

@ -483,13 +483,12 @@ modeData = {
}
function onSave()
local globalState = JSON.encode(SPAWNED_PLAYER_CARD_GUIDS)
return globalState
return JSON.encode(SPAWNED_PLAYER_CARD_GUIDS)
end
function onLoad(save_state)
if save_state ~= '' then
SPAWNED_PLAYER_CARD_GUIDS = JSON.decode(save_state)
function onLoad(savedData)
if savedData and savedData ~= '' then
SPAWNED_PLAYER_CARD_GUIDS = JSON.decode(savedData)
else
SPAWNED_PLAYER_CARD_GUIDS = {}
end

View File

@ -1,10 +1,10 @@
local guidReferenceApi = require("core/GUIDReferenceApi")
local playmatApi = require("playermat/PlaymatApi")
local playermatApi = require("playermat/PlayermatApi")
local ZONE, TRASH
local doomURL = "https://i.imgur.com/EoL7yaZ.png"
local IGNORE_TAG = "DoomCounter_ignore"
local TOTAL_PLAY_AREA = {
local doomURL = "https://i.imgur.com/EoL7yaZ.png"
local IGNORE_TAG = "DoomCounter_ignore"
local TOTAL_PLAY_AREA = {
upperLeft = {
x = -9,
z = -35
@ -66,15 +66,15 @@ end
-- removes doom from playermats / playarea
function removeDoom(options)
if options.Playermats then
local count = removeDoomFromList(playmatApi.searchAroundPlaymat("All"))
if count > 0 then
local count = removeDoomFromList(playermatApi.searchAroundPlayermat("All"))
if count > 0 then
broadcastToAll(count .. " doom removed from playermats.", "White")
end
end
if options.Playarea then
local count = removeDoomFromList(ZONE.getObjects())
if count > 0 then
if count > 0 then
broadcastToAll(count .. " doom removed from play area.", "White")
end
end
@ -96,7 +96,7 @@ end
-- helper function to check if a position is inside an area
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

View File

@ -2,7 +2,7 @@ local blessCurseManagerApi = require("chaosbag/BlessCurseManagerApi")
local guidReferenceApi = require("core/GUIDReferenceApi")
local navigationOverlayApi = require("core/NavigationOverlayApi")
local optionPanelApi = require("core/OptionPanelApi")
local playmatApi = require("playermat/PlaymatApi")
local playermatApi = require("playermat/PlayermatApi")
local searchLib = require("util/SearchLib")
local victoryDisplayApi = require("core/VictoryDisplayApi")
@ -26,28 +26,28 @@ function onLoad()
addHotkey("Upkeep (Multi-handed)", triggerUpkeepMultihanded)
end
-- triggers the "Upkeep" function of the calling player's playmat
-- triggers the "Upkeep" function of the calling player's playermat
function triggerUpkeep(playerColor)
if playerColor == "Black" then
broadcastToColor("Triggering 'Upkeep (Multihanded)' instead", playerColor, "Yellow")
triggerUpkeepMultihanded(playerColor)
return
end
local matColor = playmatApi.getMatColor(playerColor)
playmatApi.doUpkeepFromHotkey(matColor, playerColor)
local matColor = playermatApi.getMatColor(playerColor)
playermatApi.doUpkeepFromHotkey(matColor, playerColor)
end
-- triggers the "Upkeep" function of the calling player's playmat AND
-- for all playmats that don't have a seated player, but an investigator card
-- triggers the "Upkeep" function of the calling player's playermat AND
-- for all playermats that don't have a seated player, but an investigator card
function triggerUpkeepMultihanded(playerColor)
if playerColor ~= "Black" then
triggerUpkeep(playerColor)
end
local colors = Player.getAvailableColors()
for _, handColor in ipairs(colors) do
local matColor = playmatApi.getMatColor(handColor)
if playmatApi.returnInvestigatorId(matColor) ~= "00000" and Player[handColor].seated == false then
playmatApi.doUpkeepFromHotkey(matColor, playerColor)
local matColor = playermatApi.getMatColor(handColor)
if playermatApi.returnInvestigatorId(matColor) ~= "00000" and Player[handColor].seated == false then
playermatApi.doUpkeepFromHotkey(matColor, playerColor)
end
end
end
@ -69,11 +69,11 @@ function takeCardIntoThreatArea(playerColor, hoveredObject)
return
end
local matColor = playmatApi.getMatColor(playerColor)
local matColor = playermatApi.getMatColor(playerColor)
local mat = guidReferenceApi.getObjectByOwnerAndType(matColor, "Playermat")
-- do not continue if the threat area is already full
if playmatApi.getEncounterCardDrawPosition(matColor, false) == playmatApi.getEncounterCardDrawPosition(matColor, true) then
if playermatApi.getEncounterCardDrawPosition(matColor, false) == playermatApi.getEncounterCardDrawPosition(matColor, true) then
broadcastToColor("Threat area is full.", playerColor, "Yellow")
return
end
@ -84,10 +84,10 @@ function takeCardIntoThreatArea(playerColor, hoveredObject)
table.insert(moveTheseObjects, obj)
end
-- find out if the original card is on the green or red playmats
-- find out if the original card is on the green or red playermats
local originalMatColor = guidReferenceApi.getOwnerOfObject(hoveredObject)
-- determine modifiers for the playmats
-- determine modifiers for the playermats
local modifierY = 0
if originalMatColor == "Red" then
modifierY = 90
@ -103,7 +103,7 @@ function takeCardIntoThreatArea(playerColor, hoveredObject)
end
-- move the main card
local pos = playmatApi.getEncounterCardDrawPosition(matColor, false)
local pos = playermatApi.getEncounterCardDrawPosition(matColor, false)
hoveredObject.setPosition(pos)
hoveredObject.setRotation(hoveredObject.getRotation() - Vector(0, 270 - mat.getRotation().y - modifierY, 0))
@ -156,7 +156,7 @@ function performDiscard(playerColor, hoveredObject)
end
local discardForMatColor = getColorToDiscardFor(hoveredObject, playerColor)
playmatApi.discardListOfObjects(discardForMatColor, discardTheseObjects)
playermatApi.discardListOfObjects(discardForMatColor, discardTheseObjects)
end
-- discard the top card of hovered deck, calling discardObject function
@ -180,22 +180,22 @@ end
-- helper function to get the player to trigger the discard function for
function getColorToDiscardFor(hoveredObject, playerColor)
local pos = hoveredObject.getPosition()
local closestMatColor = playmatApi.getMatColorByPosition(pos)
local closestMatColor = playermatApi.getMatColorByPosition(pos)
-- check if actually on the closest playmat
-- check if actually on the closest playermat
local closestMat = guidReferenceApi.getObjectByOwnerAndType(closestMatColor, "Playermat")
local bounds = closestMat.getBounds()
-- define the area "near" the playmat
local bufferAroundPlaymat = 2
local areaNearPlaymat = {}
areaNearPlaymat.minX = bounds.center.x - bounds.size.x / 2 - bufferAroundPlaymat
areaNearPlaymat.maxX = bounds.center.x + bounds.size.x / 2 + bufferAroundPlaymat
areaNearPlaymat.minZ = bounds.center.z - bounds.size.z / 2 - bufferAroundPlaymat
areaNearPlaymat.maxZ = bounds.center.z + bounds.size.z / 2 + bufferAroundPlaymat
-- define the area "near" the playermat
local bufferAroundPlayermat = 2
local areaNearPlayermat = {}
areaNearPlayermat.minX = bounds.center.x - bounds.size.x / 2 - bufferAroundPlayermat
areaNearPlayermat.maxX = bounds.center.x + bounds.size.x / 2 + bufferAroundPlayermat
areaNearPlayermat.minZ = bounds.center.z - bounds.size.z / 2 - bufferAroundPlayermat
areaNearPlayermat.maxZ = bounds.center.z + bounds.size.z / 2 + bufferAroundPlayermat
-- discard to closest mat if near it
if inArea(pos, areaNearPlaymat) then
if inArea(pos, areaNearPlayermat) then
return closestMatColor
end
@ -208,7 +208,7 @@ function getColorToDiscardFor(hoveredObject, playerColor)
end
-- discard to triggering mat if previous conditions weren't met
return playmatApi.getMatColor(playerColor)
return playermatApi.getMatColor(playerColor)
end
-- moves the hovered card to the victory display
@ -286,7 +286,7 @@ function removeOneUse(playerColor, hoveredObject)
broadcastToAll(playerName .. " removed a token: " .. tokenName, playerColor)
local discardForMatColor = getColorToDiscardFor(hoveredObject, playerColor)
playmatApi.discardListOfObjects(discardForMatColor, { targetObject })
playermatApi.discardListOfObjects(discardForMatColor, { targetObject })
end
-- switches the triggering player to the next seat (clockwise)
@ -314,7 +314,7 @@ function switchSeat(playerColor, direction)
end
-- get used playermats
local usedColors = playmatApi.getUsedMatColors()
local usedColors = playermatApi.getUsedMatColors()
table.sort(usedColors, sortByHandPosition)
-- get current seat index
@ -407,7 +407,7 @@ function takeClueFromLocation(playerColor, hoveredObject)
local playerName, matColor, pos
if Player[playerColor] and Player[playerColor].seated then
playerName = Player[playerColor].steam_name
matColor = playmatApi.getMatColor(playerColor)
matColor = playermatApi.getMatColor(playerColor)
else
playerName = playerColor
matColor = playerColor
@ -415,12 +415,12 @@ function takeClueFromLocation(playerColor, hoveredObject)
if clickableClues then
pos = { x = 0.49, y = 2.66, z = 0.00 }
playmatApi.updateCounter(matColor, "ClickableClueCounter", _, 1)
playermatApi.updateCounter(matColor, "ClickableClueCounter", _, 1)
else
pos = playmatApi.transformLocalPosition({ x = -1.12, y = 0.05, z = 0.7 }, matColor)
pos = playermatApi.transformLocalPosition({ x = -1.12, y = 0.05, z = 0.7 }, matColor)
end
local rot = playmatApi.returnRotation(matColor)
local rot = playermatApi.returnRotation(matColor)
-- check if found clue is a stack or single token
if clue.getQuantity() > 1 then

View File

@ -3,7 +3,7 @@ local guidReferenceApi = require("core/GUIDReferenceApi")
local mythosAreaApi = require("core/MythosAreaApi")
local navigationOverlayApi = require("core/NavigationOverlayApi")
local playAreaApi = require("core/PlayAreaApi")
local playmatApi = require("playermat/PlaymatApi")
local playermatApi = require("playermat/PlayermatApi")
local searchLib = require("util/SearchLib")
local soundCubeApi = require("core/SoundCubeApi")
local tokenArrangerApi = require("accessories/TokenArrangerApi")
@ -196,7 +196,7 @@ function onObjectEnterZone(zone, object)
object.type == "Tile" and
object.getMemo() and
not object.getLock() then
local matcolor = playmatApi.getMatColorByPosition(object.getPosition())
local matcolor = playermatApi.getMatColorByPosition(object.getPosition())
local trash = guidReferenceApi.getObjectByOwnerAndType(matcolor, "Trash")
trash.putObject(object)
elseif zone.type == "Hand" and object.hasTag("CardWithHelper") then
@ -219,10 +219,10 @@ function onObjectNumberTyped(hoveredObject, playerColor, number)
if hoveredObject.type ~= "Deck" and hoveredObject.type ~= "Card" then return end
-- check whether the hovered object is part of a players draw objects
for _, color in ipairs(playmatApi.getUsedMatColors()) do
local deckAreaObjects = playmatApi.getDeckAreaObjects(color)
for _, color in ipairs(playermatApi.getUsedMatColors()) do
local deckAreaObjects = playermatApi.getDeckAreaObjects(color)
if deckAreaObjects.topCard == hoveredObject or deckAreaObjects.draw == hoveredObject then
playmatApi.drawCardsWithReshuffle(color, number)
playermatApi.drawCardsWithReshuffle(color, number)
return true
end
end
@ -238,9 +238,9 @@ function onObjectNumberTyped(hoveredObject, playerColor, number)
end
end
-- TTS event, used to redraw the playmat slot symbols after a small delay to account for the custom font loading
-- 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() playmatApi.redrawSlotSymbols("All") end, 0.2)
Wait.time(function() playermatApi.redrawSlotSymbols("All") end, 0.2)
end
---------------------------------------------------------
@ -381,7 +381,7 @@ function returnAndRedraw(_, tokenGUID)
local returnedToken = getObjectFromGUID(tokenGUID)
local tokenName = returnedToken.getName()
local indexOfReturnedToken = getTokenIndex(returnedToken)
local matColor = playmatApi.getMatColorByPosition(returnedToken.getPosition())
local matColor = playermatApi.getMatColorByPosition(returnedToken.getPosition())
local mat = guidReferenceApi.getObjectByOwnerAndType(matColor, "Playermat")
local takeParameters = {
@ -461,7 +461,7 @@ function drawChaosToken(params)
local matGUID = params.mat.getGUID()
-- return token(s) on other playmat first
-- return token(s) on other playermat first
if chaosTokensLastMatGUID ~= nil and chaosTokensLastMatGUID ~= matGUID and #chaosTokens ~= 0 then
returnChaosTokens()
chaosTokensLastMatGUID = nil
@ -563,8 +563,8 @@ function handleStatTrackerClick(_, _, isRightClick)
playerColor = "White"
playerName = "Overall"
else
local matColor = playmatApi.getMatColorByPosition(getObjectFromGUID(key).getPosition())
playerColor = playmatApi.getPlayerColor(matColor)
local matColor = playermatApi.getMatColorByPosition(getObjectFromGUID(key).getPosition())
playerColor = playermatApi.getPlayerColor(matColor)
playerName = Player[playerColor].steam_name or playerColor
local playerSquidCount = personalStats["Auto-fail"] or 0
@ -1346,8 +1346,7 @@ function contentDownloadCallback(request, params)
if pos then
spawnTable.position = pos
else
broadcastToAll(
"Please make space in the area below the tentacle stand in the upper middle of the table and try again.", "Red")
broadcastToAll("Please make space in the area below the tentacle stand in the upper middle of the table and try again.", "Red")
return
end
end
@ -1498,9 +1497,10 @@ function playermatRemovalSelected(player, selectedIndex, id)
if mat then
-- confirmation dialog about deletion
player.pingTable(mat.getPosition())
player.showConfirmDialog(
"Do you really want to remove " .. matColor .. "'s playermat and related objects? This can't be reversed.",
function() removePlayermat(matColor) end)
player.showConfirmDialog("Do you really want to remove " .. matColor .. "'s playermat and related objects? This can't be reversed.",
function()
removePlayermat(matColor)
end)
else
-- info dialog that it is already deleted
player.showInfoDialog(matColor .. "'s playermat has already been removed.")
@ -1517,7 +1517,7 @@ function removePlayermat(matColor)
if not matObjects.Playermat then return end
-- remove action tokens
local actionTokens = playmatApi.searchAroundPlaymat(matColor, "isUniversalToken")
local actionTokens = playermatApi.searchAroundPlayermat(matColor, "isUniversalToken")
for _, obj in ipairs(actionTokens) do
obj.destruct()
end
@ -1557,19 +1557,24 @@ function applyOptionPanelChange(id, state)
-- option: Snap tags
if id == "useSnapTags" then
playmatApi.setLimitSnapsByType(state, "All")
playermatApi.setLimitSnapsByType(state, "All")
-- option: Draw 1 button
elseif id == "showDrawButton" then
playmatApi.showDrawButton(state, "All")
playermatApi.showDrawButton(state, "All")
-- option: Use class texture
elseif id == "useClassTexture" then
playermatApi.useClassTexture(state, "All")
-- option: Clickable clue counters
elseif id == "useClueClickers" then
playmatApi.clickableClues(state, "All")
playermatApi.clickableClues(state, "All")
-- update master clue counter
local counter = guidReferenceApi.getObjectByOwnerAndType("Mythos", "MasterClueCounter")
counter.setVar("useClickableCounters", state)
elseif id == "enableCardHelpers" then
toggleCardHelpers(state)
@ -1616,7 +1621,7 @@ end
---@param helperName string Name of the helper object
---@param state boolean Contains the state of the option: true = spawn it, false = remove it
function spawnOrRemoveHelperForPlayermats(helperName, state)
for color, data in pairs(playmatApi.getHelperSpawnData("All", helperName)) do
for color, data in pairs(playermatApi.getHelperSpawnData("All", helperName)) do
spawnOrRemoveHelper(state, helperName, data.position, data.rotation, color)
end
end
@ -1709,6 +1714,7 @@ function onClick_defaultSettings()
showHandHelper = false,
showSearchAssistant = false,
showTitleSplash = true,
useClassTexture = true,
useClueClickers = false,
useResourceCounters = "disabled",
useSnapTags = true

View File

@ -1,4 +1,4 @@
local playmatApi = require("playermat/PlaymatApi")
local playermatApi = require("playermat/PlayermatApi")
-- variables are intentionally global to be accessible
count = 0
@ -31,12 +31,12 @@ end
-- removes all player clues by calling the respective function from the counting bowls / clickers
function removeAllPlayerClues()
printToAll(count .. " clue(s) from playermats removed.", "White")
playmatApi.removeClues("All")
playermatApi.removeClues("All")
self.editButton({ index = 0, label = "0" })
end
-- gets the counted values from the counting bowls / clickers and sums them up
function sumClues()
count = playmatApi.getClueCount(useClickableCounters, "All")
count = playermatApi.getClueCount(useClickableCounters, "All")
self.editButton({ index = 0, label = tostring(count) })
end

View File

@ -1,7 +1,7 @@
local deckLib = require("util/DeckLib")
local guidReferenceApi = require("core/GUIDReferenceApi")
local playAreaApi = require("core/PlayAreaApi")
local playmatApi = require("playermat/PlaymatApi")
local playermatApi = require("playermat/PlayermatApi")
local searchLib = require("util/SearchLib")
local tokenArrangerApi = require("accessories/TokenArrangerApi")
local tokenChecker = require("core/token/TokenChecker")
@ -22,7 +22,14 @@ local ENCOUNTER_DISCARD_POSITION = { x = -3.85, y = 1, z = 10.38 }
local isReshuffling = false
local collisionEnabled = false
local currentScenario, useFrontData, tokenData
local TRASH, DATA_HELPER
function onSave()
return JSON.encode({
currentScenario = currentScenario,
useFrontData = useFrontData,
tokenData = tokenData
})
end
function onLoad(savedData)
if savedData and savedData ~= "" then
@ -31,20 +38,9 @@ function onLoad(savedData)
useFrontData = loadedState.useFrontData or true
tokenData = loadedState.tokenData or {}
end
TRASH = guidReferenceApi.getObjectByOwnerAndType("Mythos", "Trash")
DATA_HELPER = guidReferenceApi.getObjectByOwnerAndType("Mythos", "DataHelper")
Wait.time(function() collisionEnabled = true end, 0.1)
end
function onSave()
return JSON.encode({
currentScenario = currentScenario,
useFrontData = useFrontData,
tokenData = tokenData
})
end
---------------------------------------------------------
-- collison and container event handling
---------------------------------------------------------
@ -179,9 +175,10 @@ function drawEncounterCard(params)
end
end
-- draw the provided card to the requesting playmat
-- draw the provided card to the requesting playermat
function actualEncounterCardDraw(card, params)
local metadata = JSON.decode(card.getGMNotes()) or {}
local DATA_HELPER = guidReferenceApi.getObjectByOwnerAndType("Mythos", "DataHelper")
-- draw hidden cards facedown
local faceUpRotation = 0
@ -189,7 +186,7 @@ function actualEncounterCardDraw(card, params)
faceUpRotation = 180
end
local rot = playmatApi.returnRotation(params.matColor):setAt("z", faceUpRotation)
local rot = playermatApi.returnRotation(params.matColor):setAt("z", faceUpRotation)
deckLib.placeOrMergeIntoDeck(card, params.position, rot)
end
@ -249,6 +246,7 @@ end
-- removes tokens from the provided card/deck
function removeTokensFromObject(object)
local TRASH = guidReferenceApi.getObjectByOwnerAndType("Mythos", "Trash")
for _, obj in ipairs(searchLib.onObject(object)) do
if obj.getGUID() ~= "4ee1f2" and -- table
obj ~= self and

View File

@ -1,4 +1,4 @@
local playmatApi = require("playermat/PlaymatApi")
local playermatApi = require("playermat/PlayermatApi")
fullButtonData = {
{ id = "1", width = "84", height = "33", offset = "1 2" }, -- 1. Act/Agenda
@ -44,10 +44,10 @@ playButtonData = {
cameraData = {
{ position = { -1.6, 1.55, 0 }, distance = 18 }, -- 1. Act/Agenda
{ position = { -28, 1.55, 0 }, distance = -1 }, -- 2. Map
{ position = { -31.6, 1.55, 26.4 }, distance = -1 }, -- 3. Green playmat
{ position = { -55, 1.55, 12.05 }, distance = -1 }, -- 4. White playmat
{ position = { -55, 1.55, -11.48 }, distance = -1 }, -- 5. Orange playmat
{ position = { -31.6, 1.55, -26.4 }, distance = -1 }, -- 6. Red playmat
{ position = { -31.6, 1.55, 26.4 }, distance = -1 }, -- 3. Green playermat
{ position = { -55, 1.55, 12.05 }, distance = -1 }, -- 4. White playermat
{ position = { -55, 1.55, -11.48 }, distance = -1 }, -- 5. Orange playermat
{ position = { -31.6, 1.55, -26.4 }, distance = -1 }, -- 6. Red playermat
{ position = { -3, 1.55, 30 }, distance = 16 }, -- 7. Victory / SetAside
{ position = { -3, 1.55, -26.76 }, distance = 16 }, -- 8. Guide
{ position = { -11.83, 1.55, 0 }, distance = 10 }, -- 9. Player count
@ -89,13 +89,9 @@ function onLoad(savedData)
pitch = loadedData.pitch
distance = loadedData.distance
else
local allColors = Player.getColors()
for _, color in ipairs(allColors) do
-- default state for claims
-- initialize tables with defaults
for _, color in ipairs(Player.getColors()) do
claims[color] = {}
-- default state for visibility
visibility[color] = { full = false, play = false }
end
end
@ -338,19 +334,19 @@ function loadCamera(player, camera)
end
-- swap to that color if it isn't claimed by someone else and it's currently unoccopied
if #getSeatedPlayers() == 1 or (not isClaimed and isPlaymatAvailable(matColor)) then
local newPlayerColor = playmatApi.getPlayerColor(matColor)
if #getSeatedPlayers() == 1 or (not isClaimed and isPlayermatAvailable(matColor)) then
local newPlayerColor = playermatApi.getPlayerColor(matColor)
copyVisibility({ startColor = player.color, targetColor = newPlayerColor })
player.changeColor(newPlayerColor)
player = Player[newPlayerColor]
end
-- search on the playmat for objects
local bounds = getDynamicViewBounds(playmatApi.searchAroundPlaymat(matColor))
-- search on the playermat for objects
local bounds = getDynamicViewBounds(playermatApi.searchAroundPlayermat(matColor))
lookHere = {
position = { bounds.middleX, 0, bounds.middleZ },
yaw = playmatApi.returnRotation(matColor).y + 180,
yaw = playermatApi.returnRotation(matColor).y + 180,
distance = 0.42 * math.max(bounds.diffX, bounds.diffZ) + 7
}
end
@ -371,9 +367,9 @@ function loadCamera(player, camera)
Wait.frames(function() player.lookAt(lookHere) end, 2)
end
-- helper function to check if a playmat is available for a color swap
function isPlaymatAvailable(matColor)
local newPlayerColor = playmatApi.getPlayerColor(matColor)
-- helper function to check if a playermat is available for a color swap
function isPlayermatAvailable(matColor)
local newPlayerColor = playermatApi.getPlayerColor(matColor)
for _, color in ipairs(getSeatedPlayers()) do
if color == newPlayerColor then
return false

View File

@ -133,7 +133,7 @@ function onObjectPickUp(_, object)
local metadata = JSON.decode(object.getGMNotes()) or {}
if metadata.type == "Location" then
-- onCollisionExit sometimes comes 1 frame after onObjectPickUp (rather than before it or in
-- the same frame). This causes a mismatch in the data between dragging the on-table, and
-- the same frame). This causes a mismatch in the data between dragging the on-table, and
-- that one frame draws connectors on the card which then show up as shadows for snap points.
-- Waiting ensures we always do thing in the expected Exit->PickUp order
Wait.frames(function()
@ -240,7 +240,7 @@ end
---@param card tts__Object Card to (maybe) stop tracking
function maybeUntrackLocation(card)
-- Locked objects no longer collide (hence triggering an exit event) but are still in the play
-- area. If the object is now locked, don't remove it.
-- area. If the object is now locked, don't remove it.
if locations[card.getGUID()] ~= nil and not card.locked then
locations[card.getGUID()] = nil
rebuildConnectionList()
@ -415,7 +415,7 @@ end
---@param target tts__Object Target card object to connect
---@param vectorOwner tts__Object The object which these lines will be set to. Used for relative
--- positioning and scaling, as well as highlighting connections during a drag operation
---@param lines table List of vector line elements. Mutable, will be updated to add this connector
---@param lines table List of vector line elements. Mutable, will be updated to add this connector
function addOneWayVector(origin, target, vectorOwner, lines)
-- Start with the BiDi then add the arrow lines to it
addBidirectionalVector(origin, target, vectorOwner, lines)
@ -445,9 +445,9 @@ end
-- Draws an arrowhead at the given position.
---@param arrowheadPos tts__Vector Centerpoint of the arrowhead to draw (NOT the tip of the arrow)
---@param originPos tts__Vector Origin point of the connection, used to position the arrow arms
---@param vectorOwner tts__Object The object which these lines will be set to. Used for relative
---@param vectorOwner tts__Object The object which these lines will be set to. Used for relative
--- positioning and scaling, as well as highlighting connections during a drag operation
---@param lines table List of vector line elements. Mutable, will be updated to add this arrow
---@param lines table List of vector line elements. Mutable, will be updated to add this arrow
function addArrowLines(arrowheadPos, originPos, vectorOwner, lines)
local arrowArm1 = Vector(arrowheadPos):moveTowards(originPos, ARROW_ARM_LENGTH):sub(arrowheadPos):rotateOver("y", -1 * ARROW_ANGLE):add(arrowheadPos)
local arrowArm2 = Vector(arrowheadPos):moveTowards(originPos, ARROW_ARM_LENGTH):sub(arrowheadPos):rotateOver("y", ARROW_ANGLE):add(arrowheadPos)
@ -462,7 +462,7 @@ function addArrowLines(arrowheadPos, originPos, vectorOwner, lines)
})
end
-- count victory points on locations in play area
-- Count victory points from locations in play area
---@param highlightOff boolean True if highlighting should be enabled
---@return. Returns the total amount of VP found in the play area
function countVP(highlightOff)
@ -488,14 +488,15 @@ function countVP(highlightOff)
return totalVP
end
-- checks if a card has clues on it, returns true if clues are on it
-- Checks if a card has clues on it
---@param card tts__Object Card to check for clues
---@return boolean hasClues True if card has clues on it
function cardHasClues(card)
local searchResult = searchLib.onObject(card, "isClue")
return #searchResult > 0
end
-- highlights all locations in the play area without metadata
-- Highlights all locations in the play area without metadata
---@param state boolean True if highlighting should be enabled
function highlightMissingData(state)
for i, obj in pairs(missingData) do
@ -549,7 +550,7 @@ function shiftContents(playerColor, direction)
Wait.time(drawBaseConnections, 0.1)
end
-- sets the image of the playarea
-- Sets the image of the playarea
---@param newURL string URL for the new surface image
function updateSurface(newURL)
local customInfo = self.getCustomObject()
@ -569,6 +570,7 @@ function updateSurface(newURL)
guid = customDataHelper.getGUID()
end
self.script_state = onSave()
self.reload()
if guid ~= nil then
@ -646,7 +648,7 @@ function round(num, numDecimalPlaces)
return math.floor(num * mult + 0.5) / mult
end
-- rebuilds local snap points (could be useful in the future again)
-- Rebuilds local snap points (could be useful in the future again)
function buildSnaps()
local upperleft = { x = 1.53, z = -1.09 }
local lowerright = { x = -1.53, z = 1.55 }

View File

@ -10,13 +10,13 @@ do
return guidReferenceApi.getObjectByOwnerAndType("Mythos", "InvestigatorCounter")
end
-- Returns the current value of the investigator counter from the playmat
-- Returns the current value of the investigator counter from the playermat
---@return number: Number of investigators currently set on the counter
PlayAreaApi.getInvestigatorCount = function()
return getInvestigatorCounter().getVar("val")
end
-- Updates the current value of the investigator counter from the playmat
-- Updates the current value of the investigator counter from the playermat
---@param count number Number of investigators to set on the counter
PlayAreaApi.setInvestigatorCount = function(count)
getInvestigatorCounter().call("updateVal", count)
@ -57,7 +57,7 @@ do
getPlayArea().call("onScenarioChanged", scenarioName)
end
-- Sets this playmat's snap points to limit snapping to locations or not.
-- Sets this playermat's snap points to limit snapping to locations or not.
-- If matchTypes is false, snap points will be reset to snap all cards.
---@param matchCardTypes boolean Whether snap points should only snap for the matching card types
PlayAreaApi.setLimitSnapsByType = function(matchCardTypes)

View File

@ -3,7 +3,12 @@ local optionPanelApi = require("core/OptionPanelApi")
local playAreaApi = require("core/PlayAreaApi")
local typeIndex, selectionIndex, plainNameCache
function onSave() return JSON.encode({ typeIndex = typeIndex, selectionIndex = selectionIndex }) end
function onSave()
return JSON.encode({
typeIndex = typeIndex,
selectionIndex = selectionIndex
})
end
function onLoad(savedData)
if savedData and savedData ~= "" then
@ -192,7 +197,7 @@ end
function getPlainName(str)
-- remove prefix type 1
str = str:gsub("%w+%-%w%s%-%s", "") -- matches "II-B - Thousand Shapes of Horror 1"
-- remove prefix type 2
str = str:gsub("%w+%-%w%s", "") -- matches "59-Z Congress of Keys 1"

View File

@ -2,7 +2,7 @@ do
local guidReferenceApi = require("core/GUIDReferenceApi")
local optionPanelApi = require("core/OptionPanelApi")
local playAreaApi = require("core/PlayAreaApi")
local playmatApi = require("playermat/PlaymatApi")
local playermatApi = require("playermat/PlayermatApi")
local searchLib = require("util/SearchLib")
local tokenSpawnTrackerApi = require("core/token/TokenSpawnTrackerApi")
@ -133,13 +133,13 @@ do
local TokenManager = {}
local internal = {}
-- Spawns tokens for the card. This function is built to just throw a card at it and let it do
-- the work once a card has hit an area where it might spawn tokens. It will check to see if
-- Spawns tokens for the card. This function is built to just throw a card at it and let it do
-- the work once a card has hit an area where it might spawn tokens. It will check to see if
-- the card has already spawned, find appropriate data from either the uses metadata or the Data
-- Helper, and spawn the tokens.
---@param card tts__Object Card to maybe spawn tokens for
---@param extraUses table A table of <use type>=<count> which will modify the number of tokens
--- spawned for that type. e.g. Akachi's playmat should pass "Charge"=1
--- spawned for that type. e.g. Akachi's playermat should pass "Charge"=1
TokenManager.spawnForCard = function(card, extraUses)
if tokenSpawnTrackerApi.hasSpawnedTokens(card.getGUID()) then
return
@ -155,10 +155,10 @@ do
-- Spawns a set of tokens on the given card.
---@param card tts__Object Card to spawn tokens on
---@param tokenType string Type of token to spawn (template needs to be in source bag)
---@param tokenCount number How many tokens to spawn. For damage or horror this value will be set to the
---@param tokenCount number How many tokens to spawn. For damage or horror this value will be set to the
-- spawned state object rather than spawning multiple tokens
---@param shiftDown? number An offset for the z-value of this group of tokens
---@param subType? string Subtype of token to spawn. This will only differ from the tokenName for resource tokens
---@param subType? string Subtype of token to spawn. This will only differ from the tokenName for resource tokens
TokenManager.spawnTokenGroup = function(card, tokenType, tokenCount, shiftDown, subType)
local optionPanel = optionPanelApi.getOptions()
@ -244,8 +244,8 @@ do
if tokenType == "resource" and stateID ~= nil and stateID ~= 1 then
callback = function(spawned) spawned.setState(stateID) end
elseif tokenType == "universalActionAbility" then
local matColor = playmatApi.getMatColorByPosition(card.getPosition())
local class = playmatApi.returnInvestigatorClass(matColor)
local matColor = playermatApi.getMatColorByPosition(card.getPosition())
local class = playermatApi.returnInvestigatorClass(matColor)
callback = function(spawned) spawned.call("updateClassAndSymbol", { class = class, symbol = subType or class }) end
end
@ -294,7 +294,7 @@ do
-- Checks a card for metadata to maybe replenish it
---@param card tts__Object Card object to be replenished
---@param uses table The already decoded metadata.uses (to avoid decoding again)
---@param mat tts__Object The playmat the card is placed on (for rotation and casting)
---@param mat tts__Object The playermat the card is placed on (for rotation and casting)
TokenManager.maybeReplenishCard = function(card, uses, mat)
-- TODO: support for cards with multiple uses AND replenish (as of yet, no official card needs that)
if uses[1].count and uses[1].replenish then
@ -302,7 +302,7 @@ do
end
end
-- Delegate function to the token spawn tracker. Exists to avoid circular dependencies in some
-- Delegate function to the token spawn tracker. Exists to avoid circular dependencies in some
-- callers.
---@param card tts__Object Card object to reset the tokens for
TokenManager.resetTokensSpawned = function(card)
@ -347,7 +347,7 @@ do
end
end
-- Copies the data from the DataHelper. Will only happen once.
-- Copies the data from the DataHelper. Will only happen once.
internal.initDataHelperData = function()
if playerCardData ~= nil then
return
@ -357,11 +357,11 @@ do
locationData = dataHelper.getTable('LOCATIONS_DATA')
end
-- Spawn tokens for a card based on the uses metadata. This will consider the face up/down state
-- Spawn tokens for a card based on the uses metadata. This will consider the face up/down state
-- of the card for both locations and standard cards.
---@param card tts__Object Card to maybe spawn tokens for
---@param extraUses table A table of <use type>=<count> which will modify the number of tokens
--- spawned for that type. e.g. Akachi's playmat should pass "Charge"=1
--- spawned for that type. e.g. Akachi's playermat should pass "Charge"=1
internal.spawnTokensFromUses = function(card, extraUses)
local uses = internal.getUses(card)
if uses == nil then return end
@ -380,7 +380,7 @@ do
tokenSpawnTrackerApi.markTokensSpawned(card.getGUID())
end
-- Spawn tokens for a card based on the data helper data. This will consider the face up/down state
-- Spawn tokens for a card based on the data helper data. This will consider the face up/down state
-- of the card for both locations and standard cards.
---@param card tts__Object Card to maybe spawn tokens for
internal.spawnTokensFromDataHelper = function(card)
@ -397,7 +397,7 @@ do
-- Spawn tokens for a player card using data retrieved from the Data Helper.
---@param card tts__Object Card to maybe spawn tokens for
---@param playerData table Player card data structure retrieved from the DataHelper. Should be
---@param playerData table Player card data structure retrieved from the DataHelper. Should be
-- the right data for this card.
internal.spawnPlayerCardTokensFromDataHelper = function(card, playerData)
local token = playerData.tokenType
@ -408,7 +408,7 @@ do
-- Spawn tokens for a location using data retrieved from the Data Helper.
---@param card tts__Object Card to maybe spawn tokens for
---@param locationData table Location data structure retrieved from the DataHelper. Should be
---@param locationData table Location data structure retrieved from the DataHelper. Should be
-- the right data for this card.
internal.spawnLocationTokensFromDataHelper = function(card, locationData)
local clueCount = internal.getClueCountFromData(card, locationData)
@ -481,7 +481,7 @@ do
---@param card tts__Object Card object to be replenished
---@param uses table The already decoded metadata.uses (to avoid decoding again)
---@param mat tts__Object The playmat the card is placed on (for rotation and casting)
---@param mat tts__Object The playermat the card is placed on (for rotation and casting)
internal.replenishTokens = function(card, uses, mat)
local cardPos = card.getPosition()

View File

@ -23,7 +23,9 @@ inputParameters.scale = { 0.1, 1, 0.1 }
inputParameters.color = { 0.9, 0.7, 0.5 }
inputParameters.font_color = { 0, 0, 0 }
function onSave() return JSON.encode({ spawnAll, searchExact, inputParameters.value }) end
function onSave()
return JSON.encode({ spawnAll, searchExact, inputParameters.value })
end
function onLoad(savedData)
local loadedData = JSON.decode(savedData)

View File

@ -76,7 +76,7 @@ Thus it should be implemented like this:
local blessCurseManagerApi = require("chaosbag/BlessCurseManagerApi")
local chaosBagApi = require("chaosbag/ChaosBagApi")
local guidReferenceApi = require("core/GUIDReferenceApi")
local playmatApi = require("playermat/PlaymatApi")
local playermatApi = require("playermat/PlayermatApi")
local tokenArrangerApi = require("accessories/TokenArrangerApi")
local sealedTokens = {}
@ -280,7 +280,7 @@ function resolveSealed()
broadcastToAll("No tokens sealed.", "Red")
return
end
local closestMatColor = playmatApi.getMatColorByPosition(self.getPosition())
local closestMatColor = playermatApi.getMatColorByPosition(self.getPosition())
local mat = guidReferenceApi.getObjectByOwnerAndType(closestMatColor, "Playermat")
local guidToBeResolved = table.remove(sealedTokens)
chaosBagApi.drawChaosToken(mat, true, _, guidToBeResolved)

View File

@ -1,7 +1,7 @@
require("playercards/CardsWithHelper")
local chaosBagApi = require("chaosbag/ChaosBagApi")
local guidReferenceApi = require("core/GUIDReferenceApi")
local playmatApi = require("playermat/PlaymatApi")
local playermatApi = require("playermat/PlayermatApi")
local isHelperEnabled = false
@ -37,9 +37,9 @@ end
function resolveToken(player, _, tokenType)
local matColor
if player.color == "Black" then
matColor = playmatApi.getMatColorByPosition(self.getPosition())
matColor = playermatApi.getMatColorByPosition(self.getPosition())
else
matColor = playmatApi.getMatColor(player.color)
matColor = playermatApi.getMatColor(player.color)
end
local mat = guidReferenceApi.getObjectByOwnerAndType(matColor, "Playermat")

View File

@ -1,5 +1,5 @@
require("playercards/CardsWithHelper")
local playmatApi = require("playermat/PlaymatApi")
local playermatApi = require("playermat/PlayermatApi")
-- common button parameters
local buttonParameters = {}
@ -109,9 +109,9 @@ function createButtons()
end
function findUpgradeSheet()
local matColor = playmatApi.getMatColorByPosition(self.getPosition())
local result = playmatApi.searchAroundPlaymat(matColor, "isCard")
for _, card in ipairs(result) do
local matColor = playermatApi.getMatColorByPosition(self.getPosition())
local result = playermatApi.searchAroundPlaymat(matColor, "isCard")
for j, card in ipairs(result) do
local metadata = JSON.decode(card.getGMNotes()) or {}
if metadata.id == "09041-c" then
return card

View File

@ -1,4 +1,4 @@
local playmatApi = require("playermat/PlaymatApi")
local playermatApi = require("playermat/PlayermatApi")
local searchLib = require("util/SearchLib")
local tokenManager = require("core/token/TokenManager")
@ -46,8 +46,8 @@ end
function takeAll(playerColor)
searchSelf()
local matColor = playmatApi.getMatColorByPosition(self.getPosition())
playmatApi.updateCounter(matColor, "ResourceCounter", _, foundTokens)
local matColor = playermatApi.getMatColorByPosition(self.getPosition())
playermatApi.updateCounter(matColor, "ResourceCounter", _, foundTokens)
if clickableResourceCounter then
clickableResourceCounter.call("updateVal", 0)

View File

@ -1,5 +1,5 @@
local mythosAreaApi = require("core/MythosAreaApi")
local playmatApi = require("playermat/PlaymatApi")
local playermatApi = require("playermat/PlayermatApi")
function onLoad()
-- get class via metadata and proceed menu accordingly:
@ -29,8 +29,8 @@ function contextFunc(playerColor, amount)
-- check for players with a deck and only display them as option
for _, color in ipairs(Player.getAvailableColors()) do
local matColor = playmatApi.getMatColor(color)
local deckAreaObjects = playmatApi.getDeckAreaObjects(matColor)
local matColor = playermatApi.getMatColor(color)
local deckAreaObjects = playermatApi.getDeckAreaObjects(matColor)
if deckAreaObjects.draw or deckAreaObjects.topCard then
local playerName = Player[color].steam_name

View File

@ -1,4 +1,4 @@
local playmatApi = require("playermat/PlaymatApi")
local playermatApi = require("playermat/PlayermatApi")
function onLoad()
self.addContextMenuItem("Discard 10 cards", shortSupply)
@ -6,12 +6,12 @@ end
-- called by context menu entry
function shortSupply(color)
local matColor = playmatApi.getMatColorByPosition(self.getPosition())
local matColor = playermatApi.getMatColorByPosition(self.getPosition())
-- get draw deck and discard position
local deckAreaObjects = playmatApi.getDeckAreaObjects(matColor)
local deckAreaObjects = playermatApi.getDeckAreaObjects(matColor)
local drawDeck = deckAreaObjects.draw
local discardPos = playmatApi.getDiscardPosition(matColor)
local discardPos = playermatApi.getDiscardPosition(matColor)
-- error handling
if discardPos == nil then

View File

@ -1,5 +1,5 @@
local deckLib = require("util/DeckLib")
local playmatApi = require("playermat/PlaymatApi")
local playermatApi = require("playermat/PlayermatApi")
function onLoad()
self.addContextMenuItem("Return this card", returnSelf)
@ -18,9 +18,9 @@ end
-- places this card below the deck of the player that triggered it
function placeBelowDeck(playerColor)
local matColor = playmatApi.getMatColor(playerColor)
local deckPos = playmatApi.getDrawPosition(matColor)
local deckRot = playmatApi.returnRotation(matColor)
local matColor = playermatApi.getMatColor(playerColor)
local deckPos = playermatApi.getDrawPosition(matColor)
local deckRot = playermatApi.returnRotation(matColor)
deckRot = deckRot:setAt("z", 180)
deckLib.placeOrMergeIntoDeck(self, Vector(deckPos), deckRot, true)
end

View File

@ -1,5 +1,5 @@
require("playercards/CardsWithHelper")
local playmatApi = require("playermat/PlaymatApi")
local playermatApi = require("playermat/PlayermatApi")
local buttonParameters = {
click_function = "shutOff",
@ -46,8 +46,8 @@ function shutOff()
end
function updateButton()
local matColor = playmatApi.getMatColorByPosition(self.getPosition())
local resources = playmatApi.getCounterValue(matColor, "ResourceCounter")
local matColor = playermatApi.getMatColorByPosition(self.getPosition())
local resources = playermatApi.getCounterValue(matColor, "ResourceCounter")
local count = tostring(math.floor(resources / modValue))
self.editButton({ index = 0, label = count })
end

View File

@ -19,7 +19,7 @@
-- selectedUpgrades holds the state of checkboxes and text input, each element being:
-- selectedUpgrades[row] = { xp = #, text = "" }
local playmatApi = require("playermat/PlaymatApi")
local playermatApi = require("playermat/PlayermatApi")
-- Y position for UI elements. Visibility of checkboxes moves the checkbox inside the card object
-- when not selected.
@ -230,7 +230,7 @@ function clickCheckbox(row, col)
selectedUpgrades[row].xp = col
end
updateCheckboxes(row)
playmatApi.syncAllCustomizableCards()
playermatApi.syncAllCustomizableCards()
end
-- Updates saved value for given text box when it loses focus

View File

@ -1,10 +1,10 @@
local guidReferenceApi = require("core/GUIDReferenceApi")
local playmatApi = require("playermat/PlaymatApi")
local playermatApi = require("playermat/PlayermatApi")
local searchLib = require("util/SearchLib")
exposedValue = 0
local playmat
local playermat
local searchParam = {}
function onLoad()
@ -19,14 +19,14 @@ function onLoad()
font_size = 2000
})
-- get closest playmat
local matColor = playmatApi.getMatColorByPosition(self.getPosition())
playmat = guidReferenceApi.getObjectByOwnerAndType(matColor, "Playermat")
-- get closest playermat
local matColor = playermatApi.getMatColorByPosition(self.getPosition())
playermat = guidReferenceApi.getObjectByOwnerAndType(matColor, "Playermat")
-- get search parameters (threat area excluded)
local localPos = playmat.positionToLocal(playmat.getPosition())
searchParam.pos = playmat.positionToWorld(localPos + Vector(0, 0, 0.4))
searchParam.rot = playmat.getRotation() + Vector(0, 90, 0)
local localPos = playermat.positionToLocal(playermat.getPosition())
searchParam.pos = playermat.positionToWorld(localPos + Vector(0, 0, 0.4))
searchParam.rot = playermat.getRotation() + Vector(0, 90, 0)
searchParam.size = Vector(8, 1, 27)
searchParam.filter = "isClue"
@ -34,7 +34,7 @@ function onLoad()
Wait.time(countItems, 1.5, -1)
end
-- activated once per second, counts clues on the playmat
-- activated once per second, counts clues on the playermat
function countItems()
local totalValue = 0
for _, item in ipairs(getClues()) do

View File

@ -46,7 +46,7 @@ local DRAWN_ENCOUNTER_POSITION = { x = 1.365, y = 0.5, z = -0.625 }
-- global position of encounter discard pile
local ENCOUNTER_DISCARD_POSITION = { x = -3.85, y = 1.5, z = 10.38 }
-- used for the buttons on the right side of the playmat
-- used for the buttons on the right side of the playermat
-- starts off with the data for the "Upkeep" button and will then be changed
local buttonParameters = {
label = "Upkeep",
@ -60,6 +60,16 @@ local buttonParameters = {
font_size = 180
}
-- table of texture URLs
local nameToTexture = {
Guardian = "http://cloud-3.steamusercontent.com/ugc/2444972799638881117/169F4520A94FB186B54E0F2BF4BAC809844C923E/",
Mystic = "http://cloud-3.steamusercontent.com/ugc/2444972799638880413/B59966123EA41649EDCBD614167E590C8C105582/",
Neutral = "http://cloud-3.steamusercontent.com/ugc/2462982115659543571/5D778EA4BC682DAE97E8F59A991BCF8CB3979B04/",
Rogue = "http://cloud-3.steamusercontent.com/ugc/2444972799638880905/CFC02BF5A6140B9B4B92312AD6DC74D8DD61180B/",
Seeker = "http://cloud-3.steamusercontent.com/ugc/2444972799638881117/169F4520A94FB186B54E0F2BF4BAC809844C923E/",
Survivor = "http://cloud-3.steamusercontent.com/ugc/2444972799638880687/EEDF8F8BC3266069FECB09775845BE2501310C17/"
}
-- translation table for slot names to characters for special font
local slotNameToChar = {
["any"] = "",
@ -86,12 +96,11 @@ local defaultSlotData = {
-- global variables for access
activeInvestigatorClass = "Neutral"
activeInvestigatorId = "00000"
local isDrawButtonVisible = false
-- global variable to report "Dream-Enhancing Serum" status
hasDES = false
local isClassTextureEnabled = true
local isDrawButtonVisible = false
-- table of type-object reference pairs of all owned objects
local ownedObjects = {}
local matColor = self.getMemo()
@ -100,6 +109,7 @@ function onSave()
return JSON.encode({
activeInvestigatorClass = activeInvestigatorClass,
activeInvestigatorId = activeInvestigatorId,
isClassTextureEnabled = isClassTextureEnabled,
isDrawButtonVisible = isDrawButtonVisible,
playerColor = playerColor,
slotData = slotData
@ -111,6 +121,7 @@ function onLoad(savedData)
local loadedData = JSON.decode(savedData)
activeInvestigatorClass = loadedData.activeInvestigatorClass
activeInvestigatorId = loadedData.activeInvestigatorId
isClassTextureEnabled = loadedData.isClassTextureEnabled
isDrawButtonVisible = loadedData.isDrawButtonVisible
playerColor = loadedData.playerColor
slotData = loadedData.slotData
@ -169,7 +180,7 @@ function searchArea(origin, size, filter)
return searchLib.inArea(origin, self.getRotation(), size, filter)
end
-- finds all objects on the playmat and associated set aside zone.
-- finds all objects on the playermat and associated set aside zone.
function searchAroundSelf(filter)
local scale = self.getScale()
local bounds = self.getBoundsNormalized()
@ -180,11 +191,11 @@ function searchAroundSelf(filter)
bounds.size.z = bounds.size.z + SEARCH_AROUND_SELF_Z_BUFFER
-- 'setAsideDirection' accounts for the set aside zone being on the left or right,
-- depending on the table position of the playmat
-- depending on the table position of the playermat
local setAsideDirection = bounds.center.z > 0 and 1 or -1
-- Since the cast is centered on the position, shift left or right to keep
-- the non-set aside edge of the cast at the edge of the playmat
-- the non-set aside edge of the cast at the edge of the playermat
local localCenter = self.positionToLocal(bounds.center)
localCenter.x = localCenter.x + setAsideDirection * SEARCH_AROUND_SELF_X_BUFFER / 2 / scale.x
localCenter.z = localCenter.z - SEARCH_AROUND_SELF_Z_BUFFER / 2 / scale.z
@ -391,8 +402,8 @@ function doUpkeep(_, clickedByColor, isRightClick)
j = j + 1
Wait.time(function() deckLib.placeOrMergeIntoDeck(cardsToDiscard[i], returnGlobalDiscardPosition(), self.getRotation()) end, j * 0.1)
end
--add some time if there are any cards to discard, if not, draw up to 5 immediately
-- add some time if there are any cards to discard, if not, draw up to 5 immediately
if j > 0 then
k = 0.7 + (j * 0.1)
else
@ -751,7 +762,7 @@ function changeColor(clickedByColor)
end
---------------------------------------------------------
-- playmat token spawning
-- playermat token spawning
---------------------------------------------------------
-- Finds all customizable cards in this play area and updates their metadata based on the selections
@ -907,10 +918,12 @@ function maybeUpdateActiveInvestigator(card)
notes.combatIcons,
notes.agilityIcons
})
updateTexture()
elseif activeInvestigatorId ~= "00000" then
activeInvestigatorClass = "Neutral"
activeInvestigatorId = "00000"
ownedObjects.InvestigatorSkillTracker.call("updateStats", { 1, 1, 1, 1 })
updateTexture()
else
return
end
@ -964,7 +977,7 @@ function maybeUpdateActiveInvestigator(card)
count[type] = count[type] + 1
if count[type] > 2 then
print("More than two extra tokens of the same type are not supported.")
printToColor("More than two extra tokens of the same type are not supported.", playerColor)
else
local localSpawnPos = tokenSpawnPos[type][count[type]]
local globalSpawnPos = self.positionToWorld(localSpawnPos):add(Vector(0, 0.2, 0))
@ -978,6 +991,50 @@ function maybeUpdateActiveInvestigator(card)
end
end
-- updates the texture of the playermat
---@param overrideName? string Force a specific texture
function updateTexture(overrideName)
local name = "Neutral"
-- use class specific texture if enabled
if isClassTextureEnabled then
name = activeInvestigatorClass
end
-- get new texture URL
local newUrl = nameToTexture[name]
-- override name if valid
if nameToTexture[overrideName] then
newUrl = nameToTexture[overrideName]
end
-- apply texture
local customInfo = self.getCustomObject()
if customInfo.image ~= newUrl then
-- temporarily lock objects so they don't fall through the mat
local objectsToUnlock = {}
for _, obj in ipairs(searchAroundSelf()) do
if not obj.getLock() then
obj.setLock(true)
table.insert(objectsToUnlock, obj)
end
end
self.script_state = onSave()
customInfo.image = newUrl
self.setCustomObject(customInfo)
local reloadedMat = self.reload()
-- unlock objects when mat is reloaded
Wait.condition(function()
for _, obj in ipairs(objectsToUnlock) do
obj.setLock(false)
end
end, function() return reloadedMat.loading_custom == false end)
end
end
---------------------------------------------------------
-- manipulation of owned objects
---------------------------------------------------------
@ -1009,7 +1066,7 @@ function resetSkillTracker()
if obj ~= nil then
obj.call("updateStats", { 1, 1, 1, 1 })
else
printToAll("Skill tracker for " .. matColor .. " playmat could not be found.", "Yellow")
printToAll("Skill tracker for " .. matColor .. " playermat could not be found.", "Yellow")
end
end
@ -1079,7 +1136,7 @@ function showDrawButton(visible)
end
end
-- shows / hides a clickable clue counter for this playmat and sets the correct amount of clues
-- shows / hides a clickable clue counter for this playermat and sets the correct amount of clues
---@param showCounter boolean Whether the clickable clue counter should be visible
function clickableClues(showCounter)
local clickerPos = ownedObjects.ClickableClueCounter.getPosition()
@ -1111,6 +1168,14 @@ function clickableClues(showCounter)
end
end
-- Toggles the use of class textures
---@param state boolean Whether the class texture should be used or not
function useClassTexture(state)
if state == isClassTextureEnabled then return end
isClassTextureEnabled = state
updateTexture()
end
-- removes all clues (moving tokens to the trash and setting counters to 0)
function removeClues()
ownedObjects.ClueCounter.call("removeAllClues", ownedObjects.Trash)

View File

@ -1,347 +0,0 @@
do
local PlaymatApi = {}
local guidReferenceApi = require("core/GUIDReferenceApi")
local searchLib = require("util/SearchLib")
local localInvestigatorPosition = { x = -1.17, y = 1, z = -0.01 }
-- Convenience function to look up a mat's object by color, or get all mats.
---@param matColor string Color of the playmat - White, Orange, Green, Red or All
---@return table: Single-element if only single playmat is requested
local function getMatForColor(matColor)
if matColor == "All" then
return guidReferenceApi.getObjectsByType("Playermat")
else
return { matColor = guidReferenceApi.getObjectByOwnerAndType(matColor, "Playermat") }
end
end
-- Returns the color of the closest playmat
---@param startPos table Starting position to get the closest mat from
PlaymatApi.getMatColorByPosition = function(startPos)
local result, smallestDistance
for matColor, mat in pairs(getMatForColor("All")) do
local distance = Vector.between(startPos, mat.getPosition()):magnitude()
if smallestDistance == nil or distance < smallestDistance then
smallestDistance = distance
result = matColor
end
end
return result
end
-- Returns the color of the player's hand that is seated next to the playmat
---@param matColor string Color of the playmat - White, Orange, Green or Red (does not support "All")
PlaymatApi.getPlayerColor = function(matColor)
for _, mat in pairs(getMatForColor(matColor)) do
return mat.getVar("playerColor")
end
end
-- Returns the color of the playmat that owns the playercolor's hand
---@param handColor string Color of the playmat
PlaymatApi.getMatColor = function(handColor)
for matColor, mat in pairs(getMatForColor("All")) do
local playerColor = mat.getVar("playerColor")
if playerColor == handColor then
return matColor
end
end
end
-- Instructs a playmat to check for DES
---@param matColor string Color of the playmat - White, Orange, Green, Red or All
PlaymatApi.checkForDES = function(matColor)
for _, mat in pairs(getMatForColor(matColor)) do
mat.call("checkForDES")
end
end
-- Returns if there is the card "Dream-Enhancing Serum" on the requested playmat
---@param matColor string Color of the playmat - White, Orange, Green or Red (does not support "All")
---@return boolean: whether DES is present on the playmat
PlaymatApi.hasDES = function(matColor)
for _, mat in pairs(getMatForColor(matColor)) do
return mat.getVar("hasDES")
end
end
-- gets the slot data for the playmat
---@param matColor string Color of the playmat - White, Orange, Green or Red (does not support "All")
PlaymatApi.getSlotData = function(matColor)
for _, mat in pairs(getMatForColor(matColor)) do
return mat.getTable("slotData")
end
end
-- sets the slot data for the playmat
---@param matColor string Color of the playmat - White, Orange, Green or Red (does not support "All")
---@param newSlotData table New slot data for the playmat
PlaymatApi.loadSlotData = function(matColor, newSlotData)
for _, mat in pairs(getMatForColor(matColor)) do
mat.setTable("slotData", newSlotData)
mat.call("redrawSlotSymbols")
return
end
end
-- Performs a search of the deck area of the requested playmat and returns the result as table
---@param matColor string Color of the playmat - White, Orange, Green or Red (does not support "All")
PlaymatApi.getDeckAreaObjects = function(matColor)
for _, mat in pairs(getMatForColor(matColor)) do
return mat.call("getDeckAreaObjects")
end
end
-- Flips the top card of the deck (useful after deck manipulation for Norman Withers)
---@param matColor string Color of the playmat - White, Orange, Green or Red (does not support "All")
PlaymatApi.flipTopCardFromDeck = function(matColor)
for _, mat in pairs(getMatForColor(matColor)) do
return mat.call("flipTopCardFromDeck")
end
end
-- Returns the position of the discard pile of the requested playmat
---@param matColor string Color of the playmat - White, Orange, Green or Red (does not support "All")
PlaymatApi.getDiscardPosition = function(matColor)
for _, mat in pairs(getMatForColor(matColor)) do
return mat.call("returnGlobalDiscardPosition")
end
end
-- Returns the position of the draw pile of the requested playmat
---@param matColor string Color of the playmat - White, Orange, Green or Red (does not support "All")
PlaymatApi.getDrawPosition = function(matColor)
for _, mat in pairs(getMatForColor(matColor)) do
return mat.call("returnGlobalDrawPosition")
end
end
-- Transforms a local position into a global position
---@param localPos table Local position to be transformed
---@param matColor string Color of the playmat - White, Orange, Green or Red (does not support "All")
PlaymatApi.transformLocalPosition = function(localPos, matColor)
for _, mat in pairs(getMatForColor(matColor)) do
return mat.positionToWorld(localPos)
end
end
-- Returns the rotation of the requested playmat
---@param matColor string Color of the playmat - White, Orange, Green or Red (does not support "All")
PlaymatApi.returnRotation = function(matColor)
for _, mat in pairs(getMatForColor(matColor)) do
return mat.getRotation()
end
end
-- Returns a table with spawn data (position and rotation) for a helper object
---@param matColor string Color of the playmat - White, Orange, Green, Red or All
---@param helperName string Name of the helper object
PlaymatApi.getHelperSpawnData = function(matColor, helperName)
local resultTable = {}
local localPositionTable = {
["Hand Helper"] = {0.05, 0, -1.182},
["Search Assistant"] = {-0.3, 0, -1.182}
}
for color, mat in pairs(getMatForColor(matColor)) do
resultTable[color] = {
position = mat.positionToWorld(localPositionTable[helperName]),
rotation = mat.getRotation()
}
end
return resultTable
end
-- Triggers the Upkeep for the requested playmat
---@param matColor string Color of the playmat - White, Orange, Green, Red or All
---@param playerColor string Color of the calling player (for messages)
PlaymatApi.doUpkeepFromHotkey = function(matColor, playerColor)
for _, mat in pairs(getMatForColor(matColor)) do
mat.call("doUpkeepFromHotkey", playerColor)
end
end
-- Handles discarding for the requested playmat for the provided list of objects
---@param matColor string Color of the playmat - White, Orange, Green or Red (does not support "All")
---@param objList table List of objects to discard
PlaymatApi.discardListOfObjects = function(matColor, objList)
for _, mat in pairs(getMatForColor(matColor)) do
mat.call("discardListOfObjects", objList)
end
end
-- Returns the active investigator id
---@param matColor string Color of the playmat - White, Orange, Green or Red (does not support "All")
PlaymatApi.returnInvestigatorId = function(matColor)
for _, mat in pairs(getMatForColor(matColor)) do
return mat.getVar("activeInvestigatorId")
end
end
-- Returns the class of the active investigator
---@param matColor string Color of the playmat - White, Orange, Green or Red (does not support "All")
PlaymatApi.returnInvestigatorClass = function(matColor)
for _, mat in pairs(getMatForColor(matColor)) do
return mat.getVar("activeInvestigatorClass")
end
end
-- Returns the position for encounter card drawing
---@param matColor string Color of the playmat - White, Orange, Green or Red (does not support "All")
---@param stack boolean If true, returns the leftmost position instead of the first empty from the right
PlaymatApi.getEncounterCardDrawPosition = function(matColor, stack)
for _, mat in pairs(getMatForColor(matColor)) do
return Vector(mat.call("getEncounterCardDrawPosition", stack))
end
end
-- Sets the requested playmat's snap points to limit snapping to matching card types or not. If
-- matchTypes is true, the main card slot snap points will only snap assets, while the
-- investigator area point will only snap Investigators. If matchTypes is false, snap points will
-- be reset to snap all cards.
---@param matchCardTypes boolean Whether snap points should only snap for the matching card types
---@param matColor string Color of the playmat - White, Orange, Green, Red or All
PlaymatApi.setLimitSnapsByType = function(matchCardTypes, matColor)
for _, mat in pairs(getMatForColor(matColor)) do
mat.call("setLimitSnapsByType", matchCardTypes)
end
end
-- Sets the requested playmat's draw 1 button to visible
---@param isDrawButtonVisible boolean Whether the draw 1 button should be visible or not
---@param matColor string Color of the playmat - White, Orange, Green, Red or All
PlaymatApi.showDrawButton = function(isDrawButtonVisible, matColor)
for _, mat in pairs(getMatForColor(matColor)) do
mat.call("showDrawButton", isDrawButtonVisible)
end
end
-- Shows or hides the clickable clue counter for the requested playmat
---@param showCounter boolean Whether the clickable counter should be present or not
---@param matColor string Color of the playmat - White, Orange, Green, Red or All
PlaymatApi.clickableClues = function(showCounter, matColor)
for _, mat in pairs(getMatForColor(matColor)) do
mat.call("clickableClues", showCounter)
end
end
-- Removes all clues (to the trash for tokens and counters set to 0) for the requested playmat
---@param matColor string Color of the playmat - White, Orange, Green, Red or All
PlaymatApi.removeClues = function(matColor)
for _, mat in pairs(getMatForColor(matColor)) do
mat.call("removeClues")
end
end
-- Reports the clue count for the requested playmat
---@param useClickableCounters boolean Controls which type of counter is getting checked
PlaymatApi.getClueCount = function(useClickableCounters, matColor)
local count = 0
for _, mat in pairs(getMatForColor(matColor)) do
count = count + mat.call("getClueCount", useClickableCounters)
end
return count
end
-- Updates the specified owned counter
---@param matColor string Color of the playmat - White, Orange, Green, Red or All
---@param type string Counter to target
---@param newValue number Value to set the counter to
---@param modifier number If newValue is not provided, the existing value will be adjusted by this modifier
PlaymatApi.updateCounter = function(matColor, type, newValue, modifier)
for _, mat in pairs(getMatForColor(matColor)) do
mat.call("updateCounter", { type = type, newValue = newValue, modifier = modifier })
end
end
-- Triggers the draw function for the specified playmat
---@param matColor string Color of the playmat - White, Orange, Green, Red or All
---@param number number Amount of cards to draw
PlaymatApi.drawCardsWithReshuffle = function(matColor, number)
for _, mat in pairs(getMatForColor(matColor)) do
mat.call("drawCardsWithReshuffle", number)
end
end
-- Returns the resource counter amount
---@param matColor string Color of the playmat - White, Orange, Green or Red (does not support "All")
---@param type string Counter to target
PlaymatApi.getCounterValue = function(matColor, type)
for _, mat in pairs(getMatForColor(matColor)) do
return mat.call("getCounterValue", type)
end
end
-- Returns a list of mat colors that have an investigator placed
PlaymatApi.getUsedMatColors = function()
local usedColors = {}
for matColor, mat in pairs(getMatForColor("All")) do
local searchPos = mat.positionToWorld(localInvestigatorPosition)
local searchResult = searchLib.atPosition(searchPos, "isCardOrDeck")
if #searchResult > 0 then
table.insert(usedColors, matColor)
end
end
return usedColors
end
-- Returns investigator name
---@param matColor string Color of the playmat - White, Orange, Green or Red (does not support "All")
PlaymatApi.getInvestigatorName = function(matColor)
for _, mat in pairs(getMatForColor(matColor)) do
local searchPos = mat.positionToWorld(localInvestigatorPosition)
local searchResult = searchLib.atPosition(searchPos, "isCardOrDeck")
if #searchResult == 1 then
return searchResult[1].getName()
end
end
return ""
end
-- Resets the specified skill tracker to "1, 1, 1, 1"
---@param matColor string Color of the playmat - White, Orange, Green, Red or All
PlaymatApi.resetSkillTracker = function(matColor)
for _, mat in pairs(getMatForColor(matColor)) do
mat.call("resetSkillTracker")
end
end
-- Redraws the XML for the slot symbols based on the slotData table
---@param matColor string Color of the playmat - White, Orange, Green, Red or All
PlaymatApi.redrawSlotSymbols = function(matColor)
for _, mat in pairs(getMatForColor(matColor)) do
mat.call("redrawSlotSymbols")
end
end
-- Finds all objects on the playmat and associated set aside zone and returns a table
---@param matColor string Color of the playmat - White, Orange, Green, Red or All
---@param filter string Name of the filte function (see util/SearchLib)
PlaymatApi.searchAroundPlaymat = function(matColor, filter)
local objList = {}
for _, mat in pairs(getMatForColor(matColor)) do
for _, obj in ipairs(mat.call("searchAroundSelf", filter)) do
table.insert(objList, obj)
end
end
return objList
end
-- Discard a non-hidden card from the corresponding player's hand
---@param matColor string Color of the playmat - White, Orange, Green, Red or All
PlaymatApi.doDiscardOne = function(matColor)
for _, mat in pairs(getMatForColor(matColor)) do
mat.call("doDiscardOne")
end
end
-- Triggers the metadata sync for all playmats
PlaymatApi.syncAllCustomizableCards = function()
for _, mat in pairs(getMatForColor("All")) do
mat.call("syncAllCustomizableCards")
end
end
return PlaymatApi
end

View File

@ -20,7 +20,7 @@
-- SetAside5: Hunch Deck for Joe Diamond
-- SetAside6: currently unused
do
local playmatApi = require("playermat/PlaymatApi")
local playermatApi = require("playermat/PlayermatApi")
local Zones = { }
local commonZones = {}
@ -126,7 +126,7 @@ do
and playerColor ~= "Green") then
return nil
end
return playmatApi.transformLocalPosition(zoneData[playerColor][zoneName], playerColor)
return playermatApi.transformLocalPosition(zoneData[playerColor][zoneName], playerColor)
end
-- Return the global rotation for a card on the given player mat, based on its zone.
@ -136,7 +136,7 @@ do
-- Y rotation to orient the card on the given player mat as well as a
-- Z rotation to place the card face up or face down.
Zones.getDefaultCardRotation = function(playerColor, zoneName)
local cardRotation = playmatApi.returnRotation(playerColor)
local cardRotation = playermatApi.returnRotation(playerColor)
if zoneName == "Deck" then
cardRotation = cardRotation + Vector(0, 0, 180)
end

View File

@ -1,4 +1,4 @@
local playmatApi = require("playermat/PlaymatApi")
local playermatApi = require("playermat/PlayermatApi")
local searchLib = require("util/SearchLib")
local tokenManager = require("core/token/TokenManager")
local TOKEN_INDEX = {}
@ -79,8 +79,8 @@ function onScriptingButtonDown(index, playerColor)
end
-- check for nearest investigator card and change action token state to its class
elseif tokenType == "universalActionAbility" then
local matColor = playmatApi.getMatColorByPosition(position)
local class = playmatApi.returnInvestigatorClass(matColor)
local matColor = playermatApi.getMatColorByPosition(position)
local class = playermatApi.returnInvestigatorClass(matColor)
callback = function(spawned) spawned.call("updateClassAndSymbol", { class = class, symbol = class }) end
end

View File

@ -288,6 +288,21 @@
</Cell>
</Row>
<!-- Option: use class-specific texture -->
<Row class="option-text"
tooltip="Controls whether a class-specific playermat texture should be automatically loaded.">
<Cell class="option-text">
<Panel class="singleColumn-wrapper">
<Text class="option-header">Use class-specific texture</Text>
</Panel>
</Cell>
<Cell class="option-button">
<Button class="optionToggle"
id="useClassTexture"
onClick="onClick_toggleOption"/>
</Cell>
</Row>
<!-- Option: use clickable clue-counters -->
<Row class="option-text"
tooltip="Instead of automatically counting clues in the respective area on your playermat,&#xA;this displays a clickable counter for clues.">
@ -323,7 +338,7 @@
</Cell>
</Row>
<!-- Option: remove a player mat -->
<!-- Option: remove a playermat -->
<Row class="option-text"
tooltip="Remove an unused playermat for more table space.&#xA;Displayed are the default colors.">
<Cell class="option-singleColumn">