Merge branch 'main' into spawner

This commit is contained in:
Chr1Z93 2024-02-14 22:20:18 +01:00
commit b2fa2597df
59 changed files with 466 additions and 984 deletions

View File

@ -108,7 +108,8 @@
"BarkhamHorror.308439",
"ChaosBagStatTracker.766620",
"TokenSpawnTool.36b4ee",
"OfficialStandaloneChallengeScenarios.0ef5c8",
"StandaloneScenarios.77a5f9",
"ChallengeScenarios.9f6801",
"TarotDeck.77f1e5",
"TarotDeckScripted.a230f9",
"Fan-MadeAccessories.aa8b38",
@ -129,6 +130,7 @@
"ScriptingTrigger.a2f932",
"EdgeoftheEarth.895eaa",
"TheDream-Eaters.a16a1a",
"TheFeastofHemlockVale.c740af",
"ReturntoTheCircleUndone.757324",
"OtherDoominPlay.652ff3",
"Playermat1White.8b081b",
@ -168,7 +170,6 @@
"PhaseTrackerCache.49922d",
"PhaseTrackerCache.16832f",
"PhaseTrackerCache.645841",
"TokenSource.124381",
"GameData.3dbe47",
"SCEDTour.0e5aa8",
@ -234,7 +235,7 @@
0,
0
],
"SaveName": "Arkham SCE - 3.5.0",
"SaveName": "Arkham SCE - 3.6.0",
"Sky": "Sky_Museum",
"SkyURL": "https://i.imgur.com/GkQqaOF.jpg",
"SnapPoints_path": "SnapPoints.json",

View File

@ -207,118 +207,6 @@
"z": -32.233
}
},
{
"Position": {
"x": 65,
"y": 1.481,
"z": -55
}
},
{
"Position": {
"x": 65,
"y": 1.481,
"z": -71
}
},
{
"Position": {
"x": 65,
"y": 1.481,
"z": -87
}
},
{
"Position": {
"x": 52,
"y": 1.481,
"z": -87
}
},
{
"Position": {
"x": 52,
"y": 1.481,
"z": -71
}
},
{
"Position": {
"x": 52,
"y": 1.481,
"z": -55
}
},
{
"Position": {
"x": 39,
"y": 1.481,
"z": -55
}
},
{
"Position": {
"x": 39,
"y": 1.481,
"z": -71
}
},
{
"Position": {
"x": 39,
"y": 1.481,
"z": -87
}
},
{
"Position": {
"x": 26,
"y": 1.481,
"z": -87
}
},
{
"Position": {
"x": 26,
"y": 1.481,
"z": -71
}
},
{
"Position": {
"x": 26,
"y": 1.481,
"z": -55
}
},
{
"Position": {
"x": 13,
"y": 1.481,
"z": -55
}
},
{
"Position": {
"x": 13,
"y": 1.481,
"z": -71
}
},
{
"Position": {
"x": 0,
"y": 1.481,
"z": -55
}
},
{
"Position": {
"x": 0,
"y": 1.481,
"z": -71
}
},
{
"Position": {
"x": -28.643,
@ -343,13 +231,6 @@
"z": 180
}
},
{
"Position": {
"x": 6.5,
"y": 1.481,
"z": -87
}
},
{
"Position": {
"x": -27,
@ -368,5 +249,173 @@
"y": 315,
"z": 0
}
},
{
"Position": {
"x": 65,
"y": 1.481,
"z": -52
}
},
{
"Position": {
"x": 65,
"y": 1.481,
"z": -65
}
},
{
"Position": {
"x": 65,
"y": 1.481,
"z": -78
}
},
{
"Position": {
"x": 65,
"y": 1.481,
"z": -91
}
},
{
"Position": {
"x": 50.2,
"y": 1.481,
"z": -52
}
},
{
"Position": {
"x": 50.2,
"y": 1.481,
"z": -65
}
},
{
"Position": {
"x": 50.2,
"y": 1.481,
"z": -78
}
},
{
"Position": {
"x": 50.2,
"y": 1.481,
"z": -91
}
},
{
"Position": {
"x": 35.4,
"y": 1.481,
"z": -52
}
},
{
"Position": {
"x": 35.4,
"y": 1.481,
"z": -65
}
},
{
"Position": {
"x": 35.4,
"y": 1.481,
"z": -78
}
},
{
"Position": {
"x": 35.4,
"y": 1.481,
"z": -91
}
},
{
"Position": {
"x": 20.6,
"y": 1.481,
"z": -52
}
},
{
"Position": {
"x": 20.6,
"y": 1.481,
"z": -65
}
},
{
"Position": {
"x": 5.8,
"y": 1.481,
"z": -52
}
},
{
"Position": {
"x": 5.8,
"y": 1.481,
"z": -65
}
},
{
"Position": {
"x": -9,
"y": 1.481,
"z": -52
}
},
{
"Position": {
"x": 20.6,
"y": 1.481,
"z": -78
}
},
{
"Position": {
"x": 20.6,
"y": 1.481,
"z": -91
}
},
{
"Position": {
"x": 5.8,
"y": 1.481,
"z": -78
}
},
{
"Position": {
"x": 5.8,
"y": 1.481,
"z": -91
}
},
{
"Position": {
"x": -9,
"y": 1.481,
"z": -65
}
},
{
"Position": {
"x": -9,
"y": 1.481,
"z": -78
}
},
{
"Position": {
"x": -9,
"y": 1.481,
"z": -91
}
}
]

View File

@ -1 +1 @@
{"greenDeck":"","investigators":true,"loadNewest":true,"orangeDeck":"","private":true,"redDeck":"","whiteDeck":""}
{"greenDeck":"","investigators":true,"loadNewest":true,"orangeDeck":"","privateDeck":true,"redDeck":"","whiteDeck":""}

View File

@ -42,15 +42,15 @@
"Sticky": true,
"Tooltip": true,
"Transform": {
"posX": 6.5,
"posX": -1.6,
"posY": 1.481,
"posZ": -87,
"posZ": -58.5,
"rotX": 0,
"rotY": 270,
"rotZ": 0,
"scaleX": 10,
"scaleX": 13,
"scaleY": 1,
"scaleZ": 10
"scaleZ": 13
},
"Value": 0,
"XmlUI": ""

View File

@ -54,8 +54,8 @@
"IgnoreFoW": false,
"LayoutGroupSortIndex": 0,
"Locked": false,
"LuaScriptState_path": "OfficialStandaloneChallengeScenarios.0ef5c8/ChallengeScenarios.9f6801.luascriptstate",
"LuaScript_path": "OfficialStandaloneChallengeScenarios.0ef5c8/ChallengeScenarios.9f6801.ttslua",
"LuaScriptState_path": "ChallengeScenarios.9f6801.luascriptstate",
"LuaScript_path": "ChallengeScenarios.9f6801.ttslua",
"MaterialIndex": -1,
"MeasureMovement": false,
"MeshIndex": -1,
@ -66,14 +66,14 @@
"Tooltip": true,
"Transform": {
"posX": -9,
"posY": 1.482,
"posZ": -76,
"posY": 1.481,
"posZ": -91,
"rotX": 0,
"rotY": 270,
"rotZ": 0,
"scaleX": 0.8,
"scaleY": 0.1,
"scaleZ": 0.8
"scaleX": 1,
"scaleY": 0.14,
"scaleZ": 1
},
"Value": 0,
"XmlUI": ""

View File

@ -56,7 +56,7 @@
"Transform": {
"posX": 65,
"posY": 1.481,
"posZ": -55,
"posZ": -52,
"rotX": 0,
"rotY": 270,
"rotZ": 0,

View File

@ -54,9 +54,9 @@
],
"Tooltip": true,
"Transform": {
"posX": 39,
"posX": 20.6,
"posY": 1.486,
"posZ": -87,
"posZ": -65,
"rotX": 0,
"rotY": 270,
"rotZ": 0,

View File

@ -1,60 +0,0 @@
{
"AltLookAngle": {
"x": 0,
"y": 0,
"z": 0
},
"Autoraise": true,
"ColorDiffuse": {
"b": 1,
"g": 1,
"r": 1
},
"CustomImage": {
"CustomTile": {
"Stackable": false,
"Stretch": true,
"Thickness": 0.1,
"Type": 3
},
"ImageScalar": 1,
"ImageSecondaryURL": "",
"ImageURL": "http://cloud-3.steamusercontent.com/ugc/2115061845796985108/F0ADB7094641DA966FFA3AF0CC6987D33D2D9591/",
"WidthScale": 0
},
"Description": "Use the buttons to show / hide a playmat.",
"DragSelectable": true,
"GMNotes": "",
"GUID": "a758b2",
"Grid": true,
"GridProjection": false,
"Hands": false,
"HideWhenFaceDown": false,
"IgnoreFoW": false,
"LayoutGroupSortIndex": 0,
"Locked": false,
"LuaScript": "require(\"accessories/PlayermatHider\")",
"LuaScriptState": "",
"MeasureMovement": false,
"Name": "Custom_Tile",
"Nickname": "PlayermatHider",
"Snap": true,
"Sticky": true,
"Tags": [
"CleanUpHelper_ignore"
],
"Tooltip": true,
"Transform": {
"posX": 0,
"posY": 2,
"posZ": 0,
"rotX": 0,
"rotY": 270,
"rotZ": 0,
"scaleX": 5,
"scaleY": 1,
"scaleZ": 5
},
"Value": 0,
"XmlUI": "\u003cInclude src=\"accessories/PlayermatHider.xml\"/\u003e"
}

View File

@ -1,75 +0,0 @@
{
"AltLookAngle": {
"x": 0,
"y": 0,
"z": 0
},
"Autoraise": true,
"Bag": {
"Order": 0
},
"ColorDiffuse": {
"b": 1,
"g": 0.99217,
"r": 1
},
"ContainedObjects_order": [
"StandaloneScenarios.77a5f9",
"ChallengeScenarios.9f6801"
],
"ContainedObjects_path": "OfficialStandaloneChallengeScenarios.0ef5c8",
"CustomMesh": {
"CastShadows": true,
"ColliderURL": "",
"Convex": true,
"CustomShader": {
"FresnelStrength": 0,
"SpecularColor": {
"b": 1,
"g": 1,
"r": 1
},
"SpecularIntensity": 0,
"SpecularSharpness": 2
},
"DiffuseURL": "http://cloud-3.steamusercontent.com/ugc/1758068588410895356/0B5F0CCD29DEC12514840D7B9CD2329B635A79A6/",
"MaterialIndex": 3,
"MeshURL": "http://cloud-3.steamusercontent.com/ugc/2278324073260846176/33EFCAF30567F8756F665BE5A2A6502E9C61C7F7/",
"NormalURL": "",
"TypeIndex": 6
},
"Description": "",
"DragSelectable": true,
"GMNotes": "",
"GUID": "0ef5c8",
"Grid": true,
"GridProjection": false,
"Hands": false,
"HideWhenFaceDown": false,
"IgnoreFoW": false,
"LayoutGroupSortIndex": 0,
"Locked": false,
"LuaScriptState_path": "OfficialStandaloneChallengeScenarios.0ef5c8.luascriptstate",
"LuaScript_path": "OfficialStandaloneChallengeScenarios.0ef5c8.ttslua",
"MaterialIndex": -1,
"MeasureMovement": false,
"MeshIndex": -1,
"Name": "Custom_Model_Bag",
"Nickname": "Official Standalone/Challenge Scenarios",
"Snap": true,
"Sticky": true,
"Tooltip": true,
"Transform": {
"posX": 0,
"posY": 1.866,
"posZ": -71,
"rotX": 0,
"rotY": 270,
"rotZ": 0,
"scaleX": 1.76,
"scaleY": 0.11,
"scaleZ": 1.49
},
"Value": 0,
"XmlUI": ""
}

View File

@ -1 +0,0 @@
{"ml":{"77a5f9":{"lock":false,"pos":{"x":-9,"y":1.4815,"z":-66},"rot":{"x":0,"y":270,"z":0}},"9f6801":{"lock":false,"pos":{"x":-9,"y":1.4815,"z":-76},"rot":{"x":0,"y":270,"z":0}}}}

View File

@ -1,504 +0,0 @@
-- Utility memory bag by Directsun
-- Version 2.5.2
-- Fork of Memory Bag 2.0 by MrStump
function updateSave()
local data_to_save = {["ml"]=memoryList}
saved_data = JSON.encode(data_to_save)
self.script_state = saved_data
end
function combineMemoryFromBagsWithin()
local bagObjList = self.getObjects()
for _, bagObj in ipairs(bagObjList) do
local data = bagObj.lua_script_state
if data ~= nil then
local j = JSON.decode(data)
if j ~= nil and j.ml ~= nil then
for guid, entry in pairs(j.ml) do
memoryList[guid] = entry
end
end
end
end
end
function updateMemoryWithMoves()
memoryList = memoryListBackup
--get the first transposed object's coordinates
local obj = getObjectFromGUID(moveGuid)
-- p1 is where needs to go, p2 is where it was
local refObjPos = memoryList[moveGuid].pos
local deltaPos = findOffsetDistance(obj.getPosition(), refObjPos, nil)
local movedRotation = obj.getRotation()
for guid, entry in pairs(memoryList) do
memoryList[guid].pos.x = entry.pos.x - deltaPos.x
memoryList[guid].pos.y = entry.pos.y - deltaPos.y
memoryList[guid].pos.z = entry.pos.z - deltaPos.z
-- memoryList[guid].rot.x = movedRotation.x
-- memoryList[guid].rot.y = movedRotation.y
-- memoryList[guid].rot.z = movedRotation.z
end
--theList[obj.getGUID()] = {
-- pos={x=round(pos.x,4), y=round(pos.y,4), z=round(pos.z,4)},
-- rot={x=round(rot.x,4), y=round(rot.y,4), z=round(rot.z,4)},
-- lock=obj.getLock()
--}
moveList = {}
end
function onload(saved_data)
fresh = true
if saved_data ~= "" then
local loaded_data = JSON.decode(saved_data)
--Set up information off of loaded_data
memoryList = loaded_data.ml
else
--Set up information for if there is no saved saved data
memoryList = {}
end
moveList = {}
moveGuid = nil
if next(memoryList) == nil then
createSetupButton()
else
fresh = false
createMemoryActionButtons()
end
end
--Beginning Setup
--Make setup button
function createSetupButton()
self.createButton({
label="Setup", click_function="buttonClick_setup", function_owner=self,
position={0,0.1,-6}, rotation={0,0,0}, height=500, width=1200,
font_size=350, color={0,0,0}, font_color={1,1,1}
})
end
--Triggered by Transpose button
function buttonClick_transpose()
moveGuid = nil
broadcastToAll("Select one object and move it- all objects will move relative to the new location", {0.75, 0.75, 1})
memoryListBackup = duplicateTable(memoryList)
memoryList = {}
moveList = {}
self.clearButtons()
createButtonsOnAllObjects(true)
createSetupActionButtons(true)
end
--Triggered by setup button,
function buttonClick_setup()
memoryListBackup = duplicateTable(memoryList)
memoryList = {}
self.clearButtons()
createButtonsOnAllObjects(false)
createSetupActionButtons(false)
end
function getAllObjectsInMemory()
local objTable = {}
local curObj = {}
for guid in pairs(memoryListBackup) do
curObj = getObjectFromGUID(guid)
table.insert(objTable, curObj)
end
return objTable
-- return getAllObjects()
end
--Creates selection buttons on objects
function createButtonsOnAllObjects(move)
local howManyButtons = 0
local objsToHaveButtons = {}
if move == true then
objsToHaveButtons = getAllObjectsInMemory()
else
objsToHaveButtons = getAllObjects()
end
for _, obj in ipairs(objsToHaveButtons) do
if obj ~= self then
local dummyIndex = howManyButtons
--On a normal bag, the button positions aren't the same size as the bag.
globalScaleFactor = 1 * 1/self.getScale().x
--Super sweet math to set button positions
local selfPos = self.getPosition()
local objPos = obj.getPosition()
local deltaPos = findOffsetDistance(selfPos, objPos, obj)
local objPos = rotateLocalCoordinates(deltaPos, self)
objPos.x = -objPos.x * globalScaleFactor
objPos.y = objPos.y * globalScaleFactor + 4
objPos.z = objPos.z * globalScaleFactor
--Offset rotation of bag
local rot = self.getRotation()
rot.y = -rot.y + 180
--Create function
local funcName = "selectButton_" .. howManyButtons
local func = function() buttonClick_selection(dummyIndex, obj, move) end
local color = {0.75,0.25,0.25,0.6}
local colorMove = {0,0,1,0.6}
if move == true then
color = colorMove
end
self.setVar(funcName, func)
self.createButton({
click_function=funcName, function_owner=self,
position=objPos, rotation=rot, height=1000, width=1000,
color=color,
})
howManyButtons = howManyButtons + 1
end
end
end
--Creates submit and cancel buttons
function createSetupActionButtons(move)
self.createButton({
label="Cancel", click_function="buttonClick_cancel", function_owner=self,
position={0,1,-2}, rotation={0,0,0}, height=240, width=550,
font_size=150, color={0,0,0}, font_color={1,1,1}
})
self.createButton({
label="Submit", click_function="buttonClick_submit", function_owner=self,
position={-1.2,1,-2}, rotation={0,0,0}, height=240, width=570,
font_size=150, color={0,0,0}, font_color={1,1,1}
})
if move == false then
self.createButton({
label="Add", click_function="buttonClick_add", function_owner=self,
position={-1.2,1,2}, rotation={0,0,0}, height=240, width=550,
font_size=150, color={0,0,0}, font_color={0.25,1,0.25}
})
if fresh == false then
self.createButton({
label="Set New", click_function="buttonClick_setNew", function_owner=self,
position={0,1,2}, rotation={0,0,0}, height=240, width=600,
font_size=150, color={0,0,0}, font_color={0.75,0.75,1}
})
self.createButton({
label="Remove", click_function="buttonClick_remove", function_owner=self,
position={1.3,1,2}, rotation={0,0,0}, height=240, width=600,
font_size=150, color={0,0,0}, font_color={1,0.25,0.25}
})
end
end
self.createButton({
label="Reset", click_function="buttonClick_reset", function_owner=self,
position={1.2,1,-2}, rotation={0,0,0}, height=240, width=500,
font_size=150, color={0,0,0}, font_color={1,1,1}
})
end
--During Setup
--Checks or unchecks buttons
function buttonClick_selection(index, obj, move)
local colorMove = {0,0,1,0.6}
local color = {0,1,0,0.6}
previousGuid = selectedGuid
selectedGuid = obj.getGUID()
theList = memoryList
if move == true then
theList = moveList
if previousGuid ~= nil and previousGuid ~= selectedGuid then
local prevObj = getObjectFromGUID(previousGuid)
prevObj.highlightOff()
self.editButton({index=previousIndex, color=colorMove})
theList[previousGuid] = nil
end
previousIndex = index
end
if theList[selectedGuid] == nil then
self.editButton({index=index, color=color})
--Adding pos/rot to memory table
local pos, rot = obj.getPosition(), obj.getRotation()
--I need to add it like this or it won't save due to indexing issue
theList[obj.getGUID()] = {
pos={x=round(pos.x,4), y=round(pos.y,4), z=round(pos.z,4)},
rot={x=round(rot.x,4), y=round(rot.y,4), z=round(rot.z,4)},
lock=obj.getLock()
}
obj.highlightOn({0,1,0})
else
color = {0.75,0.25,0.25,0.6}
if move == true then
color = colorMove
end
self.editButton({index=index, color=color})
theList[obj.getGUID()] = nil
obj.highlightOff()
end
end
--Cancels selection process
function buttonClick_cancel()
memoryList = memoryListBackup
moveList = {}
self.clearButtons()
if next(memoryList) == nil then
createSetupButton()
else
createMemoryActionButtons()
end
removeAllHighlights()
broadcastToAll("Selection Canceled", {1,1,1})
moveGuid = nil
end
--Saves selections
function buttonClick_submit()
fresh = false
if next(moveList) ~= nil then
for guid in pairs(moveList) do
moveGuid = guid
end
if memoryListBackup[moveGuid] == nil then
broadcastToAll("Item selected for moving is not already in memory", {1, 0.25, 0.25})
else
broadcastToAll("Moving all items in memory relative to new objects position!", {0.75, 0.75, 1})
self.clearButtons()
createMemoryActionButtons()
local count = 0
for guid in pairs(moveList) do
moveGuid = guid
count = count + 1
local obj = getObjectFromGUID(guid)
if obj ~= nil then obj.highlightOff() end
end
updateMemoryWithMoves()
updateSave()
buttonClick_place()
end
elseif next(memoryList) == nil and moveGuid == nil then
memoryList = memoryListBackup
broadcastToAll("No selections made.", {0.75, 0.25, 0.25})
end
combineMemoryFromBagsWithin()
self.clearButtons()
createMemoryActionButtons()
local count = 0
for guid in pairs(memoryList) do
count = count + 1
local obj = getObjectFromGUID(guid)
if obj ~= nil then obj.highlightOff() end
end
broadcastToAll(count.." Objects Saved", {1,1,1})
updateSave()
moveGuid = nil
end
function combineTables(first_table, second_table)
for k,v in pairs(second_table) do first_table[k] = v end
end
function buttonClick_add()
fresh = false
combineTables(memoryList, memoryListBackup)
broadcastToAll("Adding internal bags and selections to existing memory", {0.25, 0.75, 0.25})
combineMemoryFromBagsWithin()
self.clearButtons()
createMemoryActionButtons()
local count = 0
for guid in pairs(memoryList) do
count = count + 1
local obj = getObjectFromGUID(guid)
if obj ~= nil then obj.highlightOff() end
end
broadcastToAll(count.." Objects Saved", {1,1,1})
updateSave()
end
function buttonClick_remove()
broadcastToAll("Removing Selected Entries From Memory", {1.0, 0.25, 0.25})
self.clearButtons()
createMemoryActionButtons()
local count = 0
for guid in pairs(memoryList) do
count = count + 1
memoryListBackup[guid] = nil
local obj = getObjectFromGUID(guid)
if obj ~= nil then obj.highlightOff() end
end
broadcastToAll(count.." Objects Removed", {1,1,1})
memoryList = memoryListBackup
updateSave()
end
function buttonClick_setNew()
broadcastToAll("Setting new position relative to items in memory", {0.75, 0.75, 1})
self.clearButtons()
createMemoryActionButtons()
local count = 0
for _, obj in ipairs(getAllObjects()) do
guid = obj.guid
if memoryListBackup[guid] ~= nil then
count = count + 1
memoryListBackup[guid].pos = obj.getPosition()
memoryListBackup[guid].rot = obj.getRotation()
memoryListBackup[guid].lock = obj.getLock()
end
end
broadcastToAll(count.." Objects Saved", {1,1,1})
memoryList = memoryListBackup
updateSave()
end
--Resets bag to starting status
function buttonClick_reset()
fresh = true
memoryList = {}
self.clearButtons()
createSetupButton()
removeAllHighlights()
broadcastToAll("Tool Reset", {1,1,1})
updateSave()
end
--After Setup
--Creates recall and place buttons
function createMemoryActionButtons()
self.createButton({
label="Place", click_function="buttonClick_place", function_owner=self,
position={0.7,1,2}, rotation={0,0,0}, height=280, width=600,
font_size=200, color={0,0,0}, font_color={1,1,1}
})
self.createButton({
label="Recall", click_function="buttonClick_recall", function_owner=self,
position={-0.7,1,2}, rotation={0,0,0}, height=280, width=650,
font_size=200, color={0,0,0}, font_color={1,1,1}
})
self.createButton({
label="Setup", click_function="buttonClick_setup", function_owner=self,
position={0,1,-2}, rotation={0,0,0}, height=240, width=500,
font_size=150, color={0,0,0}, font_color={1,1,1}
})
--- self.createButton({
--- label="Move", click_function="buttonClick_transpose", function_owner=self,
--- position={-2.8,0.3,0}, rotation={0,0,0}, height=350, width=800,
--- font_size=250, color={0,0,0}, font_color={0.75,0.75,1}
--- })
end
--Sends objects from bag/table to their saved position/rotation
function buttonClick_place()
local bagObjList = self.getObjects()
for guid, entry in pairs(memoryList) do
local obj = getObjectFromGUID(guid)
--If obj is out on the table, move it to the saved pos/rot
if obj ~= nil then
obj.setPositionSmooth(entry.pos)
obj.setRotationSmooth(entry.rot)
obj.setLock(entry.lock)
else
--If obj is inside of the bag
for _, bagObj in ipairs(bagObjList) do
if bagObj.guid == guid then
local item = self.takeObject({
guid=guid, position=entry.pos, rotation=entry.rot, smooth=false
})
item.setLock(entry.lock)
break
end
end
end
end
broadcastToAll("Objects Placed", {1,1,1})
end
--Recalls objects to bag from table
function buttonClick_recall()
for guid, entry in pairs(memoryList) do
local obj = getObjectFromGUID(guid)
if obj ~= nil then self.putObject(obj) end
end
broadcastToAll("Objects Recalled", {1,1,1})
end
--Utility functions
--Find delta (difference) between 2 x/y/z coordinates
function findOffsetDistance(p1, p2, obj)
local yOffset = 0
if obj ~= nil then
local bounds = obj.getBounds()
yOffset = (bounds.size.y - bounds.offset.y)
end
local deltaPos = {}
deltaPos.x = (p2.x-p1.x)
deltaPos.y = (p2.y-p1.y) + yOffset
deltaPos.z = (p2.z-p1.z)
return deltaPos
end
--Used to rotate a set of coordinates by an angle
function rotateLocalCoordinates(desiredPos, obj)
local objPos, objRot = obj.getPosition(), obj.getRotation()
local angle = math.rad(objRot.y)
local x = desiredPos.x * math.cos(angle) - desiredPos.z * math.sin(angle)
local z = desiredPos.x * math.sin(angle) + desiredPos.z * math.cos(angle)
--return {x=objPos.x+x, y=objPos.y+desiredPos.y, z=objPos.z+z}
return {x=x, y=desiredPos.y, z=z}
end
function rotateMyCoordinates(desiredPos, obj)
local angle = math.rad(obj.getRotation().y)
local x = desiredPos.x * math.sin(angle)
local z = desiredPos.z * math.cos(angle)
return {x=x, y=desiredPos.y, z=z}
end
--Coroutine delay, in seconds
function wait(time)
local start = os.time()
repeat coroutine.yield(0) until os.time() > start + time
end
--Duplicates a table (needed to prevent it making reference to the same objects)
function duplicateTable(oldTable)
local newTable = {}
for k, v in pairs(oldTable) do
newTable[k] = v
end
return newTable
end
--Moves scripted highlight from all objects
function removeAllHighlights()
for _, obj in ipairs(getAllObjects()) do
obj.highlightOff()
end
end
--Round number (num) to the Nth decimal (dec)
function round(num, dec)
local mult = 10^(dec or 0)
return math.floor(num * mult + 0.5) / mult
end

View File

@ -54,9 +54,9 @@
],
"Tooltip": true,
"Transform": {
"posX": 13,
"posX": 35.4,
"posY": 1.866,
"posZ": -71,
"posZ": -65,
"rotX": 0,
"rotY": 270,
"rotZ": 0,

View File

@ -54,9 +54,9 @@
],
"Tooltip": true,
"Transform": {
"posX": 52,
"posX": 65,
"posY": 1.866,
"posZ": -71,
"posZ": -91,
"rotX": 0,
"rotY": 270,
"rotZ": 0,

View File

@ -54,9 +54,9 @@
],
"Tooltip": true,
"Transform": {
"posX": 26,
"posX": 50.2,
"posY": 1.866,
"posZ": -71,
"posZ": -91,
"rotX": 0,
"rotY": 270,
"rotZ": 0,

View File

@ -54,9 +54,9 @@
],
"Tooltip": true,
"Transform": {
"posX": 39,
"posX": 50.2,
"posY": 1.866,
"posZ": -71,
"posZ": -65,
"rotX": 0,
"rotY": 270,
"rotZ": 0,

View File

@ -56,7 +56,7 @@
"Transform": {
"posX": 65,
"posY": 1.866,
"posZ": -71,
"posZ": -65,
"rotX": 0,
"rotY": 270,
"rotZ": 0,

View File

@ -11,15 +11,15 @@
"r": 1
},
"CustomImage": {
"CustomToken": {
"MergeDistancePixels": 15,
"CustomTile": {
"Stackable": false,
"StandUp": false,
"Thickness": 0.1
"Stretch": true,
"Thickness": 0.1,
"Type": 3
},
"ImageScalar": 1,
"ImageSecondaryURL": "",
"ImageURL": "http://cloud-3.steamusercontent.com/ugc/1857193769888710611/7DFDDFD0F0AFB7A31F29843D196BE9E36D89A60F/",
"ImageURL": "http://cloud-3.steamusercontent.com/ugc/2342503777976621188/4C119690DEF2B128E6EC309A880984E55D80350C/",
"WidthScale": 0
},
"Description": "Allows searching for card(s) by name. Use the buttons to toggle the spawn / search mode.\n\nSee context menu for additional information.",
@ -36,21 +36,21 @@
"LuaScript": "require(\"playercards/CardSearch\")",
"LuaScriptState": "[true,false,\"\"]",
"MeasureMovement": false,
"Name": "Custom_Token",
"Name": "Custom_Tile",
"Nickname": "Search-A-Card",
"Snap": true,
"Sticky": true,
"Tooltip": true,
"Transform": {
"posX": 60,
"posY": 1.531,
"posY": 1.481,
"posZ": 56,
"rotX": 0,
"rotY": 270,
"rotZ": 0,
"scaleX": 1.25,
"scaleX": 4,
"scaleY": 1,
"scaleZ": 1.35
"scaleZ": 4
},
"Value": 0,
"XmlUI": ""

View File

@ -57,8 +57,8 @@
"IgnoreFoW": false,
"LayoutGroupSortIndex": 0,
"Locked": false,
"LuaScriptState_path": "OfficialStandaloneChallengeScenarios.0ef5c8/StandaloneScenarios.77a5f9.luascriptstate",
"LuaScript_path": "OfficialStandaloneChallengeScenarios.0ef5c8/StandaloneScenarios.77a5f9.ttslua",
"LuaScriptState_path": "StandaloneScenarios.77a5f9.luascriptstate",
"LuaScript_path": "StandaloneScenarios.77a5f9.ttslua",
"MaterialIndex": -1,
"MeasureMovement": false,
"MeshIndex": -1,
@ -68,15 +68,15 @@
"Sticky": true,
"Tooltip": true,
"Transform": {
"posX": -9,
"posX": 5.8,
"posY": 1.481,
"posZ": -66,
"posZ": -91,
"rotX": 0,
"rotY": 270,
"rotZ": 0,
"scaleX": 0.8,
"scaleY": 0.1,
"scaleZ": 0.8
"scaleX": 1,
"scaleY": 0.14,
"scaleZ": 1
},
"Value": 0,
"XmlUI": ""

View File

@ -71,9 +71,9 @@
"Sticky": true,
"Tooltip": true,
"Transform": {
"posX": 12.25,
"posY": 1.481,
"posZ": -36.014,
"posX": 59.773,
"posY": 2.202,
"posZ": -28.411,
"rotX": 0,
"rotY": 270,
"rotZ": 0,

View File

@ -54,9 +54,9 @@
],
"Tooltip": true,
"Transform": {
"posX": 13,
"posX": 35.4,
"posY": 1.486,
"posZ": -55,
"posZ": -52,
"rotX": 0,
"rotY": 270,
"rotZ": 0,

View File

@ -54,9 +54,9 @@
],
"Tooltip": true,
"Transform": {
"posX": 65,
"posX": 35.4,
"posY": 1.486,
"posZ": -87,
"posZ": -78,
"rotX": 0,
"rotY": 270,
"rotZ": 0,

View File

@ -54,9 +54,9 @@
],
"Tooltip": true,
"Transform": {
"posX": 52,
"posX": 65,
"posY": 1.481,
"posZ": -55,
"posZ": -78,
"rotX": 0,
"rotY": 270,
"rotZ": 0,

View File

@ -0,0 +1,69 @@
{
"AltLookAngle": {
"x": 0,
"y": 0,
"z": 0
},
"Autoraise": true,
"ColorDiffuse": {
"a": 0.27451,
"b": 1,
"g": 1,
"r": 1
},
"CustomMesh": {
"CastShadows": true,
"ColliderURL": "https://raw.githubusercontent.com/RobMayer/TTSLibrary/master/advboxes/core_h_COL.obj",
"Convex": true,
"CustomShader": {
"FresnelStrength": 0,
"SpecularColor": {
"b": 1,
"g": 1,
"r": 1
},
"SpecularIntensity": 0,
"SpecularSharpness": 2
},
"DiffuseURL": "http://cloud-3.steamusercontent.com/ugc/2342503777949914349/98CA11F8C5250E8F4A1DA877CD496C6FFB87AF0E/",
"MaterialIndex": 3,
"MeshURL": "https://raw.githubusercontent.com/RobMayer/TTSLibrary/master/advboxes/core_h_MSH.obj",
"NormalURL": "",
"TypeIndex": 0
},
"Description": "",
"DragSelectable": true,
"GMNotes": "campaigns/the_feast_of_hemlock_vale.json",
"GUID": "c740af",
"Grid": true,
"GridProjection": false,
"Hands": false,
"HideWhenFaceDown": false,
"IgnoreFoW": false,
"LayoutGroupSortIndex": 0,
"Locked": false,
"LuaScript": "require(\"core/DownloadBox\")",
"LuaScriptState": "",
"MeasureMovement": false,
"Name": "Custom_Model",
"Nickname": "The Feast of Hemlock Vale",
"Snap": true,
"Sticky": true,
"Tags": [
"CampaignBox"
],
"Tooltip": true,
"Transform": {
"posX": 20.6,
"posY": 1.486,
"posZ": -91,
"rotX": 0,
"rotY": 270,
"rotZ": 0,
"scaleX": 1,
"scaleY": 0.14,
"scaleZ": 1
},
"Value": 0,
"XmlUI": ""
}

View File

@ -54,9 +54,9 @@
],
"Tooltip": true,
"Transform": {
"posX": 26,
"posX": 50.2,
"posY": 1.486,
"posZ": -55,
"posZ": -78,
"rotX": 0,
"rotY": 270,
"rotZ": 0,

View File

@ -54,9 +54,9 @@
],
"Tooltip": true,
"Transform": {
"posX": 52,
"posX": 20.6,
"posY": 1.486,
"posZ": -87,
"posZ": -52,
"rotX": 0,
"rotY": 270,
"rotZ": 0,

View File

@ -54,9 +54,9 @@
],
"Tooltip": true,
"Transform": {
"posX": 39,
"posX": 50.2,
"posY": 1.481,
"posZ": -55,
"posZ": -52,
"rotX": 0,
"rotY": 270,
"rotZ": 0,

View File

@ -54,9 +54,9 @@
],
"Tooltip": true,
"Transform": {
"posX": 26,
"posX": 20.6,
"posY": 1.486,
"posZ": -87,
"posZ": -78,
"rotX": 0,
"rotY": 270,
"rotZ": 0,

View File

@ -1,21 +0,0 @@
local guidReferenceApi = require("core/GUIDReferenceApi")
local playmatApi = require("playermat/PlaymatApi")
function onClick_hide(player, matColor)
local objects = guidReferenceApi.getObjectsByOwner(matColor)
if not objects.Playermat then return end
player.showConfirmDialog("Really remove this playmat and related objects? This can't be reversed.",
function()
-- remove action tokens
local actionTokens = playmatApi.searchAroundPlaymat(matColor, "isActionToken")
for _, obj in ipairs(actionTokens) do
obj.destruct()
end
-- remove mat owned objects
for _, obj in pairs(objects) do
obj.destruct()
end
end)
end

View File

@ -310,6 +310,10 @@ do
-- remove spaces
line = line:gsub("%s", "")
-- remove balanced brackets
line = line:gsub("%b()", "")
line = line:gsub("%b[]", "")
-- get instructor
local instructor = ""
for word in line:gmatch("%a+:") do
@ -408,7 +412,7 @@ do
-- Gets the ArkhamDB config info from the configuration object.
---@return table: configuration data
internal.getConfiguration = function()
local configuation = getObjectsWithTag("import_configuration_provider")[1].getTable("configuration")
local configuration = getObjectsWithTag("import_configuration_provider")[1].getTable("configuration")
printPriority = configuration.priority
return configuration
end

View File

@ -3,7 +3,6 @@ require("playercards/PlayerCardSpawner")
local allCardsBagApi = require("playercards/AllCardsBagApi")
local arkhamDb = require("arkhamdb/ArkhamDb")
local playAreaApi = require("core/PlayAreaApi")
local playmatApi = require("playermat/PlaymatApi")
local zones = require("playermat/Zones")

View File

@ -1,5 +1,7 @@
local searchLib = require("util/SearchLib")
local idList = {}
function onLoad()
local buttonParameters = {}
buttonParameters.function_owner = self
@ -23,26 +25,13 @@ function onLoad()
end
function generate(_, playerColor)
local idList = {}
idList = {}
for _, obj in ipairs(searchLib.onObject(self, "isCardOrDeck")) do
if obj.type == "Card" then
local cardMetadata = JSON.decode(obj.getGMNotes())
if cardMetadata then
local id = getIdFromData(cardMetadata)
if id then
table.insert(idList, id)
end
end
processCard(JSON.decode(obj.getGMNotes()), obj.getName())
elseif obj.type == "Deck" then
for _, deepObj in ipairs(obj.getData().ContainedObjects) do
local cardMetadata = JSON.decode(deepObj.GMNotes)
if cardMetadata then
local id = getIdFromData(cardMetadata)
if id then
table.insert(idList, id)
end
end
processCard(JSON.decode(deepObj.GMNotes), deepObj.Nickname)
end
end
end
@ -54,10 +43,13 @@ function generate(_, playerColor)
broadcastToColor("Created deck instruction for " .. #idList .. " card(s). Copy it from the input field.", playerColor, "Green")
end
-- sort the idList
table.sort(idList, sortById)
-- construct the string
local description = "++SCED import instructions++\n- add: "
for _, id in ipairs(idList) do
description = description .. id .. ", "
for _, entry in ipairs(idList) do
description = description .. entry.id .. " (**" .. entry.name .. "**)" .. ", "
end
-- remove last delimiter (last two characters)
@ -74,4 +66,24 @@ function getIdFromData(metadata)
end
end
function processCard(metadata, name)
if metadata then
local id = getIdFromData(metadata)
if id then
table.insert(idList, {id = id, name = name})
end
end
end
function sortById(a, b)
local numA = tonumber(a.id)
local numB = tonumber(b.id)
if numA and numB then
return numA < numB
else
return a.name < b.name
end
end
function none() end

View File

@ -1,7 +1,7 @@
local guidReferenceApi = require("core/GUIDReferenceApi")
local playmatApi = require("playermat/PlaymatApi")
local ZONE, TRASH, loopID
local ZONE, TRASH
local doomURL = "https://i.imgur.com/EoL7yaZ.png"
local IGNORE_TAG = "DoomCounter_ignore"
local TOTAL_PLAY_AREA = {
@ -32,7 +32,7 @@ function onLoad()
TRASH = guidReferenceApi.getObjectByOwnerAndType("Mythos", "Trash")
ZONE = guidReferenceApi.getObjectByOwnerAndType("Mythos", "PlayAreaZone")
loopID = Wait.time(updateCounter, 2, -1)
Wait.time(updateCounter, 2, -1)
end
-- main function

View File

@ -37,11 +37,10 @@ local chaosTokensLastMatGUID = nil
local tokenDrawingStats = { ["Overall"] = {} }
local bagSearchers = {}
local MAT_COLORS = { "White", "Orange", "Green", "Red" }
local hideTitleSplashWaitFunctionId = nil
-- online functionality related variables
local MOD_VERSION = "3.5.0"
local MOD_VERSION = "3.6.0"
local SOURCE_REPO = 'https://raw.githubusercontent.com/chr1z93/loadable-objects/main'
local library, requestObj, modMeta
local acknowledgedUpgradeVersions = {}

View File

@ -1,118 +1,121 @@
require("playercards/PlayerCardSpawner")
local allCardsBagApi = require("playercards/AllCardsBagApi")
local allCardsBagApi = require("playercards/AllCardsBagApi")
local buttonParameters = {}
buttonParameters.function_owner = self
buttonParameters.height = 200
buttonParameters.width = 1200
buttonParameters.font_size = 75
local BUTTON_LABELS = {}
BUTTON_LABELS["spawn"] = {}
BUTTON_LABELS["spawn"][true] = "All matching cards"
BUTTON_LABELS["spawn"][false] = "First matching card"
BUTTON_LABELS["search"] = {}
BUTTON_LABELS["search"][true] = "Name equals search term"
BUTTON_LABELS["search"][false] = "Name contains search term"
local BUTTON_LABELS = {}
local inputParameters = {}
inputParameters.label = "Click to enter card name"
inputParameters.input_function = "input_func"
inputParameters.function_owner = self
inputParameters.alignment = 2
inputParameters.position = { x = 0, y = 0.1, z = -0.62 }
inputParameters.width = 3750
inputParameters.height = 380
inputParameters.font_size = 350
inputParameters.scale = { 0.1, 1, 0.1 }
inputParameters.color = { 0.9, 0.7, 0.5 }
inputParameters.font_color = { 0, 0, 0 }
BUTTON_LABELS["spawn"] = {}
BUTTON_LABELS["spawn"][true] = "Mode: Spawn all matching cards "
BUTTON_LABELS["spawn"][false] = "Mode: Spawn first matching card"
BUTTON_LABELS["search"] = {}
BUTTON_LABELS["search"][true] = "Mode: Name matches search term"
BUTTON_LABELS["search"][false] = "Mode: Name contains search term"
local inputParameters = {}
inputParameters.label = "Click to enter card name"
inputParameters.input_function = "input_func"
inputParameters.function_owner = self
inputParameters.alignment = 2
inputParameters.position = { 0, 0.05, -1.6 }
inputParameters.width = 1200
inputParameters.height = 130
inputParameters.font_size = 107
-- main code
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)
spawnAll = loadedData[1] or false
searchExact = loadedData[2] or false
inputParameters.value = loadedData[3] or ""
local loadedData = JSON.decode(savedData)
spawnAll = loadedData[1] or false
searchExact = loadedData[2] or false
inputParameters.value = loadedData[3] or ""
self.createInput(inputParameters)
-- index 0: button for spawn mode
buttonParameters.click_function = "search"
buttonParameters.label = "Spawn matching card(s)!"
buttonParameters.position = { 0, 0.06, 1.15 }
self.createButton(buttonParameters)
-- shared parameters
local buttonParameters = {}
buttonParameters.function_owner = self
buttonParameters.font_size = 180
buttonParameters.scale = { 0.1, 1, 0.1 }
buttonParameters.hover_color = { 0.4, 0.6, 0.8 }
buttonParameters.color = { 0.9, 0.7, 0.5 }
-- index 1: button for spawn mode
buttonParameters.click_function = "spawnMode"
buttonParameters.label = BUTTON_LABELS["spawn"][spawnAll]
buttonParameters.position[3] = buttonParameters.position[3] + 0.4
self.createButton(buttonParameters)
-- index 0: button for spawn mode
buttonParameters.click_function = "toggleSpawnMode"
buttonParameters.label = BUTTON_LABELS["spawn"][spawnAll]
buttonParameters.position = { x = 0.16, y = 0.1, z = 0.565 }
buttonParameters.height = 375
buttonParameters.width = 2300
self.createButton(buttonParameters)
-- index 2: button for search mode
buttonParameters.click_function = "searchMode"
buttonParameters.label = BUTTON_LABELS["search"][searchExact]
buttonParameters.position[3] = buttonParameters.position[3] + 0.4
self.createButton(buttonParameters)
-- index 1: button for search mode
buttonParameters.click_function = "toggleSearchMode"
buttonParameters.label = BUTTON_LABELS["search"][searchExact]
buttonParameters.position = { x = 0.16, y = 0.1, z = 0.652 }
self.createButton(buttonParameters)
self.createInput(inputParameters)
-- index 2: start search
buttonParameters.click_function = "startSearch"
buttonParameters.label = ""
buttonParameters.position = { x = 0, y = 0, z = 0.806 }
buttonParameters.height = 600
buttonParameters.width = 2800
self.createButton(buttonParameters)
end
function spawnMode()
spawnAll = not spawnAll
self.editButton({ index = 1, label = BUTTON_LABELS["spawn"][spawnAll] })
function toggleSpawnMode()
spawnAll = not spawnAll
self.editButton({ index = 0, label = BUTTON_LABELS["spawn"][spawnAll] })
end
function searchMode()
searchExact = not searchExact
self.editButton({ index = 2, label = BUTTON_LABELS["search"][searchExact] })
function toggleSearchMode()
searchExact = not searchExact
self.editButton({ index = 1, label = BUTTON_LABELS["search"][searchExact] })
end
-- if "Enter press" (\n) is found, start search and recreate input
function input_func(_, _, input, stillEditing)
if not stillEditing then
inputParameters.value = input
elseif string.find(input, "%\n") ~= nil then
inputParameters.value = input.gsub(input, "%\n", "")
search()
self.removeInput(0)
self.createInput(inputParameters)
end
if not stillEditing then
inputParameters.value = input
elseif string.find(input, "%\n") ~= nil then
inputParameters.value = input.gsub(input, "%\n", "")
startSearch()
self.removeInput(0)
self.createInput(inputParameters)
end
end
function search()
if inputParameters.value == nil or string.len(inputParameters.value) == 0 then
printToAll("Please enter a search string.", "Yellow")
return
end
function startSearch()
if inputParameters.value == nil or string.len(inputParameters.value) == 0 then
printToAll("Please enter a search string.", "Yellow")
return
end
if string.len(inputParameters.value) < 3 then
printToAll("Please enter a longer search string.", "Yellow")
return
end
if string.len(inputParameters.value) < 3 then
printToAll("Please enter a longer search string.", "Yellow")
return
end
if not allCardsBagApi.isBagPresent() then
printToAll("Player card bag couldn't be found.", "Red")
return
end
if not allCardsBagApi.isBagPresent() then
printToAll("Player card bag couldn't be found.", "Red")
return
end
-- search all objects in bag
local cardList = allCardsBagApi.getCardsByName(inputParameters.value, searchExact)
if cardList == nil or #cardList == 0 then
printToAll("No match found.", "Red")
return
end
if (#cardList > 100) then
printToAll("Matched more than 100 cards, please try a more specific search.", "Yellow")
return
end
-- search all objects in bag
local cardList = allCardsBagApi.getCardsByName(inputParameters.value, searchExact)
if cardList == nil or #cardList == 0 then
printToAll("No match found.", "Red")
return
end
if (#cardList > 100) then
printToAll("Matched more than 100 cards, please try a more specific search.", "Yellow")
return
end
-- sort table by name (reverse for multiple results, because bottom card spawns first)
table.sort(cardList, function(k1, k2) return spawnAll == (k1.data.Nickname > k2.data.Nickname) end)
-- sort table by name (reverse for multiple results, because bottom card spawns first)
table.sort(cardList, function(k1, k2) return spawnAll == (k1.data.Nickname > k2.data.Nickname) end)
local rot = self.getRotation()
local pos = self.positionToWorld(Vector(0, 2, -0.225))
Spawner.spawnCards(cardList, pos, rot, true)
local rot = self.getRotation()
local pos = self.positionToWorld(Vector(0, 2, -0.08))
Spawner.spawnCards(cardList, pos, rot, true)
end

View File

@ -99,10 +99,7 @@ local starterDeckMode = STARTER_DECK_MODE_CARDS_ONLY
local helpVisibleToPlayers = { }
function onSave()
local saveState = {
spawnBagState = spawnBag.getStateForSave(),
}
return JSON.encode(saveState)
return JSON.encode({ spawnBagState = spawnBag.getStateForSave() })
end
function onLoad(savedData)

View File

@ -10,11 +10,11 @@ Spawner = { }
-- investigator, standard, and mini, spawning them in that order with larger cards on bottom. If
-- there are different types, the provided callback will be called once for each type as it spawns
-- either a card or deck.
---@param cardList Table A list of Player Card data structures (data/metadata)
---@param pos Position table where the cards should be spawned (global)
---@param rot Rotation table for the orientation of the spawned cards (global)
---@param sort Boolean true if this list of cards should be sorted before spawning
---@param callback Function callback to be called after the card/deck spawns.
---@param cardList table A list of Player Card data structures (data/metadata)
---@param pos tts__Vector table where the cards should be spawned (global)
---@param rot tts__Vector table for the orientation of the spawned cards (global)
---@param sort boolean True if this list of cards should be sorted before spawning
---@param callback? function Callback to be called after the card/deck spawns.
Spawner.spawnCards = function(cardList, pos, rot, sort, callback)
if (sort) then
table.sort(cardList, Spawner.cardComparator)
@ -80,7 +80,7 @@ end
---@param cardList table A list of Player Card data structures (data/metadata)
---@param pos table Position where the cards should be spawned (global)
---@param rot table Rotation for the orientation of the spawned cards (global)
---@param callback function callback to be called after the card/deck spawns.
---@param callback? function callback to be called after the card/deck spawns.
Spawner.spawn = function(cardList, pos, rot, callback)
if #cardList == 0 then return end
@ -94,19 +94,20 @@ Spawner.spawn = function(cardList, pos, rot, callback)
data = cardList[1].data,
position = pos,
rotation = rot,
callback_function = callback,
callback_function = callback
})
return
end
-- For multiple cards, construct a deck and spawn that
local deck = Spawner.buildDeckDataTemplate()
-- Decks won't inherently scale to the cards in them. The card list being spawned should be all
-- the same type/size by this point, so use the first card to set the size
deck.Transform = {
scaleX = cardList[1].data.Transform.scaleX,
scaleY = 1,
scaleZ = cardList[1].data.Transform.scaleZ,
scaleZ = cardList[1].data.Transform.scaleZ
}
local sidewaysDeck = true
@ -121,6 +122,7 @@ Spawner.spawn = function(cardList, pos, rot, callback)
deck.AltLookAngle = { x = 0, y = 180, z = 90 }
rot = { rot.x, rot.y - 90, rot.z }
end
spawnObjectData({
data = deck,
position = pos,
@ -194,9 +196,9 @@ Spawner.buildDeckDataTemplate = function()
end
-- Returns the first ID which does not exist in the given table, starting at startId and increasing
---@param objectTable Table keyed by strings which are numbers
---@param startId First possible ID.
---@return String ID >= startId
---@param objectTable table keyed by strings which are numbers
---@param startId string possible ID.
---@return string id >= startId
Spawner.findNextAvailableId = function(objectTable, startId)
local id = startId
while (objectTable[id] ~= nil) do

View File

@ -78,8 +78,7 @@ do
}
end
-- Places the given spawnSpec on the table. See SpawnBag.ttslua header for spawnSpec table data and
-- examples
-- Places the given spawnSpec on the table. See comment at the start of the file for spawnSpec table data and examples
SpawnBag.spawn = function(spawnSpec)
-- Limit to one placement at a time
if (placedSpecs[spawnSpec.name]) then

View File

@ -1,6 +1,11 @@
local guidReferenceApi = require("core/GUIDReferenceApi")
local playmatApi = require("playermat/PlaymatApi")
local searchLib = require("util/SearchLib")
exposedValue = 0
local playmat
function onLoad()
self.createButton({
label = "",
@ -12,10 +17,16 @@ function onLoad()
font_color = { 0, 0, 0 },
font_size = 2000
})
loopID = Wait.time(countItems, 1.5, -1)
-- get closest playmat
local matColor = playmatApi.getMatColorByPosition(self.getPosition())
playmat = guidReferenceApi.getObjectByOwnerAndType(matColor, "Playermat")
-- start loop
Wait.time(countItems, 1.5, -1)
end
-- Activated once per second, counts items in bowls
-- activated once per second, counts clues on the playmat
function countItems()
local totalValue = 0
for _, item in ipairs(getClues()) do
@ -32,5 +43,5 @@ function removeAllClues(trash)
end
function getClues()
return searchLib.inArea(self.getPosition(), self.getRotation(), { 2, 1, 2 }, "isClue")
return searchLib.onObject(playmat, "isClue")
end

View File

@ -300,14 +300,12 @@ function doUpkeep(_, clickedByColor, isRightClick)
-- flip investigator mini-card and summoned servitor mini-card
-- (all characters allowed to account for custom IDs - e.g. 'Z0000' for TTS Zoop generated IDs)
if activeInvestigatorId ~= nil then
local miniId = string.match(activeInvestigatorId, ".....") .. "-m"
for _, obj in ipairs(getObjects()) do
if obj.type == "Card" and obj.is_face_down then
local notes = JSON.decode(obj.getGMNotes())
if notes ~= nil and notes.type == "Minicard" and (notes.id == miniId or notes.id == "09080-m") then
obj.flip()
end
local miniId = string.match(activeInvestigatorId, ".....") .. "-m"
for _, obj in ipairs(getObjects()) do
if obj.type == "Card" and obj.is_face_down then
local notes = JSON.decode(obj.getGMNotes())
if notes ~= nil and notes.type == "Minicard" and (notes.id == miniId or notes.id == "09080-m") then
obj.flip()
end
end
end