Merge branch 'main' into optionpanel
This commit is contained in:
commit
9dff6886ea
@ -57,8 +57,8 @@
|
||||
"Cluetokens.11e0cf",
|
||||
"Doomtokens.b015d8",
|
||||
"DoomCounter.85c4c6",
|
||||
"Custom_Tile.2eca7c",
|
||||
"Custom_Tile.fb09d4",
|
||||
"RoundSequenceActionDescription.2eca7c",
|
||||
"RoundSequenceActionDescription.fb09d4",
|
||||
"3DText.65eb7e",
|
||||
"InvestigatorCount.f182ee",
|
||||
"ScriptingTrigger.c506bf",
|
||||
@ -96,7 +96,6 @@
|
||||
"Resourcetokens.0168ae",
|
||||
"Horrortokens.ae1a4e",
|
||||
"DamageTokens.b0ef6c",
|
||||
"Connectionmarkers.b118af",
|
||||
"Trash.4b8594",
|
||||
"Trash.5f896a",
|
||||
"Trash.147e80",
|
||||
@ -109,7 +108,6 @@
|
||||
"Doomtokens.16fcd6",
|
||||
"DamageTokens.93f4a0",
|
||||
"Resourcetokens.fd617a",
|
||||
"Connectionmarkers.5dcccb",
|
||||
"Cluetokens.31fa39",
|
||||
"Horrortokens.c3ecf4",
|
||||
"Doomtokens.47ffc3",
|
||||
@ -252,7 +250,8 @@
|
||||
"TokenSpawnTracker.e3ffc9",
|
||||
"TokenSource.124381",
|
||||
"GameData.3dbe47",
|
||||
"SCEDTour.0e5aa8"
|
||||
"SCEDTour.0e5aa8",
|
||||
"PlayerCards.2d30ee"
|
||||
],
|
||||
"PlayArea": 1,
|
||||
"PlayerCounts": [
|
||||
|
@ -107,12 +107,12 @@
|
||||
{
|
||||
"Name": "NextArrow",
|
||||
"Type": 0,
|
||||
"URL": "https://i.imgur.com/gXRiKmu.png"
|
||||
"URL": "https://i.imgur.com/MztSQis.png"
|
||||
},
|
||||
{
|
||||
"Name": "Exit",
|
||||
"Type": 0,
|
||||
"URL": "https://i.imgur.com/i0VMjPD.png"
|
||||
"URL": "https://i.imgur.com/8qmTXwt.png"
|
||||
},
|
||||
{
|
||||
"Name": "Inv-Mandy",
|
||||
|
@ -3817,54 +3817,6 @@
|
||||
"z": 65.419
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -22.602,
|
||||
"y": 1.635,
|
||||
"z": 22.44
|
||||
},
|
||||
"Rotation": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -25.571,
|
||||
"y": 1.639,
|
||||
"z": 22.44
|
||||
},
|
||||
"Rotation": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -28.485,
|
||||
"y": 1.642,
|
||||
"z": 22.44
|
||||
},
|
||||
"Rotation": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -31.454,
|
||||
"y": 1.645,
|
||||
"z": 22.44
|
||||
},
|
||||
"Rotation": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -50.852,
|
||||
@ -3985,106 +3937,6 @@
|
||||
"z": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -28.509,
|
||||
"y": 1.64,
|
||||
"z": -22.42
|
||||
},
|
||||
"Rotation": {
|
||||
"x": 0,
|
||||
"y": 180,
|
||||
"z": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -25.509,
|
||||
"y": 1.64,
|
||||
"z": -22.42
|
||||
},
|
||||
"Rotation": {
|
||||
"x": 0,
|
||||
"y": 180,
|
||||
"z": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -22.606,
|
||||
"y": 1.64,
|
||||
"z": -22.42
|
||||
},
|
||||
"Rotation": {
|
||||
"x": 0,
|
||||
"y": 180,
|
||||
"z": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -19.651,
|
||||
"y": 1.64,
|
||||
"z": -22.42
|
||||
},
|
||||
"Rotation": {
|
||||
"x": 0,
|
||||
"y": 180,
|
||||
"z": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -34.383,
|
||||
"y": 1.651,
|
||||
"z": 22.439
|
||||
},
|
||||
"Rotation": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -16.691,
|
||||
"y": 1.64,
|
||||
"z": -22.417
|
||||
},
|
||||
"Rotation": {
|
||||
"x": 0,
|
||||
"y": 180,
|
||||
"z": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -34.26,
|
||||
"y": 1.651,
|
||||
"z": 23.6
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -33.12,
|
||||
"y": 1.65,
|
||||
"z": 23.6
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -16.78,
|
||||
"y": 1.64,
|
||||
"z": -23.58
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -17.92,
|
||||
"y": 1.64,
|
||||
"z": -23.58
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -52.07,
|
||||
@ -4127,20 +3979,6 @@
|
||||
"z": -21.55
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -20.049,
|
||||
"y": 1.64,
|
||||
"z": -24.78
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -30.997,
|
||||
"y": 1.647,
|
||||
"z": 24.81
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": 45.336,
|
||||
@ -4203,5 +4041,285 @@
|
||||
"y": 1.481,
|
||||
"z": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -24.91,
|
||||
"y": 1.55,
|
||||
"z": -24.84
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -35.77,
|
||||
"y": 1.55,
|
||||
"z": 24.86
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -37.9,
|
||||
"y": 1.55,
|
||||
"z": 23.72
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -39.04,
|
||||
"y": 1.55,
|
||||
"z": 23.72
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -22.78,
|
||||
"y": 1.55,
|
||||
"z": -23.72
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -21.64,
|
||||
"y": 1.55,
|
||||
"z": -23.72
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -21.502,
|
||||
"y": 1.55,
|
||||
"z": -22.44
|
||||
},
|
||||
"Rotation": {
|
||||
"x": 0,
|
||||
"y": 180,
|
||||
"z": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -24.462,
|
||||
"y": 1.55,
|
||||
"z": -22.44
|
||||
},
|
||||
"Rotation": {
|
||||
"x": 0,
|
||||
"y": 180,
|
||||
"z": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -27.407,
|
||||
"y": 1.55,
|
||||
"z": -22.44
|
||||
},
|
||||
"Rotation": {
|
||||
"x": 0,
|
||||
"y": 180,
|
||||
"z": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -30.365,
|
||||
"y": 1.55,
|
||||
"z": -22.44
|
||||
},
|
||||
"Rotation": {
|
||||
"x": 0,
|
||||
"y": 180,
|
||||
"z": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -33.332,
|
||||
"y": 1.55,
|
||||
"z": -22.44
|
||||
},
|
||||
"Rotation": {
|
||||
"x": 0,
|
||||
"y": 180,
|
||||
"z": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -36.216,
|
||||
"y": 1.55,
|
||||
"z": -22.44
|
||||
},
|
||||
"Rotation": {
|
||||
"x": 0,
|
||||
"y": 180,
|
||||
"z": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -39.14,
|
||||
"y": 1.55,
|
||||
"z": -22.44
|
||||
},
|
||||
"Rotation": {
|
||||
"x": 0,
|
||||
"y": 180,
|
||||
"z": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -39.271,
|
||||
"y": 1.55,
|
||||
"z": 22.44
|
||||
},
|
||||
"Rotation": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -36.213,
|
||||
"y": 1.55,
|
||||
"z": 22.439
|
||||
},
|
||||
"Rotation": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -33.287,
|
||||
"y": 1.55,
|
||||
"z": 22.44
|
||||
},
|
||||
"Rotation": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -30.332,
|
||||
"y": 1.55,
|
||||
"z": 22.44
|
||||
},
|
||||
"Rotation": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -27.388,
|
||||
"y": 1.55,
|
||||
"z": 22.44
|
||||
},
|
||||
"Rotation": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -24.473,
|
||||
"y": 1.55,
|
||||
"z": 22.504
|
||||
},
|
||||
"Rotation": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -21.541,
|
||||
"y": 1.55,
|
||||
"z": 22.504
|
||||
},
|
||||
"Rotation": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -45.4,
|
||||
"y": 1.481,
|
||||
"z": 21.5
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -45.4,
|
||||
"y": 1.481,
|
||||
"z": 23.75
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -45.4,
|
||||
"y": 1.481,
|
||||
"z": 26
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -45.4,
|
||||
"y": 1.481,
|
||||
"z": 28.25
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -45.4,
|
||||
"y": 1.481,
|
||||
"z": 30.5
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -45.4,
|
||||
"y": 1.481,
|
||||
"z": -21.5
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -45.4,
|
||||
"y": 1.481,
|
||||
"z": -23.75
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -45.4,
|
||||
"y": 1.481,
|
||||
"z": -26
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -45.4,
|
||||
"y": 1.481,
|
||||
"z": -28.25
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -45.4,
|
||||
"y": 1.481,
|
||||
"z": -30.5
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -33,8 +33,8 @@
|
||||
"IgnoreFoW": false,
|
||||
"LayoutGroupSortIndex": 0,
|
||||
"Locked": false,
|
||||
"LuaScript": "",
|
||||
"LuaScriptState": "",
|
||||
"LuaScript_path": "AllPlayerCards.15bb07/ShortSupply.e5f541.ttslua",
|
||||
"MeasureMovement": false,
|
||||
"Name": "Card",
|
||||
"Nickname": "Short Supply",
|
||||
|
36
objects/AllPlayerCards.15bb07/ShortSupply.e5f541.ttslua
Normal file
36
objects/AllPlayerCards.15bb07/ShortSupply.e5f541.ttslua
Normal file
@ -0,0 +1,36 @@
|
||||
local playmatAPI = require("playermat/PlaymatApi")
|
||||
|
||||
function onLoad()
|
||||
self.addContextMenuItem("Discard 10 cards", shortSupply)
|
||||
end
|
||||
|
||||
-- called by context menu entry
|
||||
function shortSupply(color)
|
||||
local matColor = playmatAPI.getMatColorByPosition(self.getPosition())
|
||||
|
||||
-- get draw deck and discard position
|
||||
local drawDeck = playmatAPI.getDrawDeck(matColor)
|
||||
local discardPos = playmatAPI.getDiscardPosition(matColor)
|
||||
|
||||
-- error handling
|
||||
if discardPos == nil then
|
||||
broadcastToColor("Couldn't retrieve discard position from playermat!", color, "Red")
|
||||
return
|
||||
end
|
||||
|
||||
if drawDeck == nil then
|
||||
broadcastToColor("Deck not found!", color, "Yellow")
|
||||
return
|
||||
elseif drawDeck.tag ~= "Deck" then
|
||||
broadcastToColor("Deck only contains a single card!", color, "Yellow")
|
||||
return
|
||||
end
|
||||
|
||||
-- discard cards
|
||||
broadcastToColor("Discarding top 10 cards for player color '" .. matColor .. "'.", color, "White")
|
||||
discardPos.y = 0.5
|
||||
for i = 1, 10 do
|
||||
discardPos.y = discardPos.y + 0.05 * i
|
||||
drawDeck.takeObject({ flip = true, position = discardPos })
|
||||
end
|
||||
end
|
@ -51,9 +51,9 @@
|
||||
"Sticky": true,
|
||||
"Tooltip": false,
|
||||
"Transform": {
|
||||
"posX": -32.193,
|
||||
"posX": -36.867,
|
||||
"posY": 1.52,
|
||||
"posZ": 30.977,
|
||||
"posZ": 31.025,
|
||||
"rotX": 0,
|
||||
"rotY": 10,
|
||||
"rotZ": 0,
|
||||
|
@ -51,9 +51,9 @@
|
||||
"Sticky": true,
|
||||
"Tooltip": false,
|
||||
"Transform": {
|
||||
"posX": -59.426,
|
||||
"posX": -59.402,
|
||||
"posY": 1.52,
|
||||
"posZ": -22.721,
|
||||
"posZ": -22.586,
|
||||
"rotX": 0,
|
||||
"rotY": 280,
|
||||
"rotZ": 0,
|
||||
|
@ -51,9 +51,9 @@
|
||||
"Sticky": true,
|
||||
"Tooltip": false,
|
||||
"Transform": {
|
||||
"posX": -18.87,
|
||||
"posX": -23.89,
|
||||
"posY": 1.52,
|
||||
"posZ": -30.977,
|
||||
"posZ": -31.107,
|
||||
"rotX": 0,
|
||||
"rotY": 190,
|
||||
"rotZ": 0,
|
||||
|
@ -51,9 +51,9 @@
|
||||
"Sticky": true,
|
||||
"Tooltip": false,
|
||||
"Transform": {
|
||||
"posX": -59.426,
|
||||
"posX": -59.45,
|
||||
"posY": 1.52,
|
||||
"posZ": 9.395,
|
||||
"posZ": 9.589,
|
||||
"rotX": 0,
|
||||
"rotY": 280,
|
||||
"rotZ": 0,
|
||||
|
@ -45,7 +45,7 @@
|
||||
],
|
||||
"Tooltip": false,
|
||||
"Transform": {
|
||||
"posX": -18.87,
|
||||
"posX": -23.89,
|
||||
"posY": 1.3,
|
||||
"posZ": -30.977,
|
||||
"rotX": 0,
|
||||
|
@ -45,7 +45,7 @@
|
||||
],
|
||||
"Tooltip": false,
|
||||
"Transform": {
|
||||
"posX": -32.193,
|
||||
"posX": -36.87,
|
||||
"posY": 1.3,
|
||||
"posZ": 30.977,
|
||||
"rotX": 0,
|
||||
|
@ -46,9 +46,9 @@
|
||||
"Sticky": true,
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": -42.227,
|
||||
"posY": 1.611,
|
||||
"posZ": -31.182,
|
||||
"posX": -45.4,
|
||||
"posY": 1.561,
|
||||
"posZ": -28.25,
|
||||
"rotX": 0,
|
||||
"rotY": 180,
|
||||
"rotZ": 0,
|
||||
|
@ -46,9 +46,9 @@
|
||||
"Sticky": true,
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": -44.101,
|
||||
"posY": 1.632,
|
||||
"posZ": 31.207,
|
||||
"posX": -45.4,
|
||||
"posY": 1.561,
|
||||
"posZ": 28.25,
|
||||
"rotX": 0,
|
||||
"rotY": 0,
|
||||
"rotZ": 0,
|
||||
|
@ -1,61 +0,0 @@
|
||||
{
|
||||
"AltLookAngle": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"Autoraise": true,
|
||||
"ColorDiffuse": {
|
||||
"b": 1,
|
||||
"g": 1,
|
||||
"r": 1
|
||||
},
|
||||
"ContainedObjects_order": [
|
||||
"Custom_Tile.7234af"
|
||||
],
|
||||
"ContainedObjects_path": "Connectionmarkers.5dcccb",
|
||||
"CustomMesh": {
|
||||
"CastShadows": true,
|
||||
"ColliderURL": "",
|
||||
"Convex": true,
|
||||
"DiffuseURL": "http://cloud-3.steamusercontent.com/ugc/949588657208009702/1786DA3A72B61BF39ADE9577B177797450011602/",
|
||||
"MaterialIndex": 3,
|
||||
"MeshURL": "https://pastebin.com/raw/ALrYhQGb",
|
||||
"NormalURL": "",
|
||||
"TypeIndex": 7
|
||||
},
|
||||
"Description": "",
|
||||
"DragSelectable": true,
|
||||
"GMNotes": "",
|
||||
"GUID": "5dcccb",
|
||||
"Grid": true,
|
||||
"GridProjection": false,
|
||||
"Hands": false,
|
||||
"HideWhenFaceDown": false,
|
||||
"IgnoreFoW": false,
|
||||
"LayoutGroupSortIndex": 0,
|
||||
"Locked": true,
|
||||
"LuaScript": "",
|
||||
"LuaScriptState": "",
|
||||
"MaterialIndex": -1,
|
||||
"MeasureMovement": false,
|
||||
"MeshIndex": -1,
|
||||
"Name": "Custom_Model_Infinite_Bag",
|
||||
"Nickname": "Connection markers",
|
||||
"Snap": true,
|
||||
"Sticky": true,
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": -44.559,
|
||||
"posY": 1.636,
|
||||
"posZ": -26.724,
|
||||
"rotX": 0,
|
||||
"rotY": 180,
|
||||
"rotZ": 0,
|
||||
"scaleX": 0.8,
|
||||
"scaleY": 1,
|
||||
"scaleZ": 0.8
|
||||
},
|
||||
"Value": 0,
|
||||
"XmlUI": ""
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
{
|
||||
"AltLookAngle": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"Autoraise": true,
|
||||
"ColorDiffuse": {
|
||||
"b": 1,
|
||||
"g": 1,
|
||||
"r": 1
|
||||
},
|
||||
"ContainedObjects_order": [
|
||||
"Custom_Tile.7234af"
|
||||
],
|
||||
"ContainedObjects_path": "Connectionmarkers.b118af",
|
||||
"CustomMesh": {
|
||||
"CastShadows": true,
|
||||
"ColliderURL": "",
|
||||
"Convex": true,
|
||||
"DiffuseURL": "http://cloud-3.steamusercontent.com/ugc/949588657208009702/1786DA3A72B61BF39ADE9577B177797450011602/",
|
||||
"MaterialIndex": 3,
|
||||
"MeshURL": "https://pastebin.com/raw/ALrYhQGb",
|
||||
"NormalURL": "",
|
||||
"TypeIndex": 7
|
||||
},
|
||||
"Description": "",
|
||||
"DragSelectable": true,
|
||||
"GMNotes": "",
|
||||
"GUID": "b118af",
|
||||
"Grid": true,
|
||||
"GridProjection": false,
|
||||
"Hands": false,
|
||||
"HideWhenFaceDown": false,
|
||||
"IgnoreFoW": false,
|
||||
"LayoutGroupSortIndex": 0,
|
||||
"Locked": true,
|
||||
"LuaScript": "",
|
||||
"LuaScriptState": "",
|
||||
"MaterialIndex": -1,
|
||||
"MeasureMovement": false,
|
||||
"MeshIndex": -1,
|
||||
"Name": "Custom_Model_Infinite_Bag",
|
||||
"Nickname": "Connection markers",
|
||||
"Snap": true,
|
||||
"Sticky": true,
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": -41.769,
|
||||
"posY": 1.648,
|
||||
"posZ": 26.75,
|
||||
"rotX": 0,
|
||||
"rotY": 0,
|
||||
"rotZ": 0,
|
||||
"scaleX": 0.8,
|
||||
"scaleY": 1,
|
||||
"scaleZ": 0.8
|
||||
},
|
||||
"Value": 0,
|
||||
"XmlUI": ""
|
||||
}
|
@ -36,9 +36,9 @@
|
||||
"Sticky": true,
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": -60.574,
|
||||
"posY": 1.249,
|
||||
"posZ": 70.866,
|
||||
"posX": -61,
|
||||
"posY": 1.27,
|
||||
"posZ": 74,
|
||||
"rotX": 0,
|
||||
"rotY": 270,
|
||||
"rotZ": 0,
|
||||
|
@ -42,11 +42,11 @@
|
||||
"Sticky": true,
|
||||
"Tooltip": false,
|
||||
"Transform": {
|
||||
"posX": -32.31,
|
||||
"posX": -37.182,
|
||||
"posY": 1.52,
|
||||
"posZ": 29.006,
|
||||
"posZ": 29.089,
|
||||
"rotX": 0,
|
||||
"rotY": 11,
|
||||
"rotY": 10,
|
||||
"rotZ": 1,
|
||||
"scaleX": 0.26,
|
||||
"scaleY": 1,
|
||||
|
@ -42,11 +42,11 @@
|
||||
"Sticky": true,
|
||||
"Tooltip": false,
|
||||
"Transform": {
|
||||
"posX": -18.706,
|
||||
"posX": -23.497,
|
||||
"posY": 1.52,
|
||||
"posZ": -29.027,
|
||||
"posZ": -29.078,
|
||||
"rotX": 0,
|
||||
"rotY": 195,
|
||||
"rotY": 190,
|
||||
"rotZ": 0,
|
||||
"scaleX": 0.26,
|
||||
"scaleY": 1,
|
||||
|
@ -42,11 +42,11 @@
|
||||
"Sticky": true,
|
||||
"Tooltip": false,
|
||||
"Transform": {
|
||||
"posX": -57.512,
|
||||
"posX": -57.507,
|
||||
"posY": 1.52,
|
||||
"posZ": -22.921,
|
||||
"posZ": -22.894,
|
||||
"rotX": 0,
|
||||
"rotY": 285,
|
||||
"rotY": 280,
|
||||
"rotZ": 0,
|
||||
"scaleX": 0.26,
|
||||
"scaleY": 1,
|
||||
|
@ -42,11 +42,11 @@
|
||||
"Sticky": true,
|
||||
"Tooltip": false,
|
||||
"Transform": {
|
||||
"posX": -57.488,
|
||||
"posX": -57.472,
|
||||
"posY": 1.52,
|
||||
"posZ": 9.184,
|
||||
"posZ": 9.273,
|
||||
"rotX": 0,
|
||||
"rotY": 282,
|
||||
"rotY": 280,
|
||||
"rotZ": 0,
|
||||
"scaleX": 0.26,
|
||||
"scaleY": 1,
|
||||
|
@ -56,9 +56,9 @@
|
||||
"Sticky": true,
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": -44.558,
|
||||
"posY": 1.635,
|
||||
"posZ": -28.959,
|
||||
"posX": -45.4,
|
||||
"posY": 1.581,
|
||||
"posZ": -23.75,
|
||||
"rotX": 0,
|
||||
"rotY": 180,
|
||||
"rotZ": 0,
|
||||
|
@ -56,9 +56,9 @@
|
||||
"Sticky": true,
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": -41.77,
|
||||
"posY": 1.648,
|
||||
"posZ": 28.985,
|
||||
"posX": -45.4,
|
||||
"posY": 1.581,
|
||||
"posZ": 23.75,
|
||||
"rotX": 0,
|
||||
"rotY": 0,
|
||||
"rotZ": 0,
|
||||
|
@ -43,9 +43,9 @@
|
||||
"Sticky": true,
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": -60.384,
|
||||
"posY": 1.325,
|
||||
"posZ": 86.713,
|
||||
"posX": -61,
|
||||
"posY": 1.27,
|
||||
"posZ": 89,
|
||||
"rotX": 0,
|
||||
"rotY": 270,
|
||||
"rotZ": 0,
|
||||
|
@ -46,9 +46,9 @@
|
||||
"Sticky": true,
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": -41.77,
|
||||
"posY": 1.649,
|
||||
"posZ": 31.207,
|
||||
"posX": -45.4,
|
||||
"posY": 1.581,
|
||||
"posZ": 30.5,
|
||||
"rotX": 0,
|
||||
"rotY": 0,
|
||||
"rotZ": 0,
|
||||
|
@ -46,9 +46,9 @@
|
||||
"Sticky": true,
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": -44.558,
|
||||
"posY": 1.634,
|
||||
"posZ": -31.182,
|
||||
"posX": -45.4,
|
||||
"posY": 1.581,
|
||||
"posZ": -30.5,
|
||||
"rotX": 0,
|
||||
"rotY": 180,
|
||||
"rotZ": 0,
|
||||
|
@ -17,7 +17,7 @@
|
||||
"ChaosBagManager.023240",
|
||||
"TokenArranger.022907",
|
||||
"CYOACampaignGuides.e87ea2",
|
||||
"AttachmentHelper.d45664",
|
||||
"AttachmentHelper.7f4976",
|
||||
"ArkhamFantasy-PixelArtMini-Cards.e17c9e",
|
||||
"jaqenZannsNavigationOverlay.a8affa",
|
||||
"DrawTokenButtonTooltipRenamer.cc77a8",
|
||||
|
@ -0,0 +1,51 @@
|
||||
{
|
||||
"AltLookAngle": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"Autoraise": true,
|
||||
"ColorDiffuse": {
|
||||
"b": 1,
|
||||
"g": 0.37256,
|
||||
"r": 0.30589
|
||||
},
|
||||
"ContainedObjects_order": [
|
||||
"AttachmentHelper.d45664"
|
||||
],
|
||||
"ContainedObjects_path": "AttachmentHelper.7f4976",
|
||||
"Description": "Provides card-sized bags that are useful for cards that are attached facedown (e.g. Backpack).",
|
||||
"DragSelectable": true,
|
||||
"GMNotes": "",
|
||||
"GUID": "7f4976",
|
||||
"Grid": true,
|
||||
"GridProjection": false,
|
||||
"Hands": false,
|
||||
"HideWhenFaceDown": false,
|
||||
"IgnoreFoW": false,
|
||||
"LayoutGroupSortIndex": 0,
|
||||
"Locked": false,
|
||||
"LuaScript": "",
|
||||
"LuaScriptState": "",
|
||||
"MaterialIndex": -1,
|
||||
"MeasureMovement": false,
|
||||
"MeshIndex": -1,
|
||||
"Name": "Infinite_Bag",
|
||||
"Nickname": "Attachment Helper",
|
||||
"Snap": true,
|
||||
"Sticky": true,
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": 27.677,
|
||||
"posY": 4.472,
|
||||
"posZ": -31.034,
|
||||
"rotX": 0,
|
||||
"rotY": 0,
|
||||
"rotZ": 0,
|
||||
"scaleX": 1,
|
||||
"scaleY": 1,
|
||||
"scaleZ": 1
|
||||
},
|
||||
"Value": 0,
|
||||
"XmlUI": ""
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
{
|
||||
"AltLookAngle": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"Autoraise": true,
|
||||
"Bag": {
|
||||
"Order": 0
|
||||
},
|
||||
"ColorDiffuse": {
|
||||
"b": 1,
|
||||
"g": 1,
|
||||
"r": 1
|
||||
},
|
||||
"CustomMesh": {
|
||||
"CastShadows": true,
|
||||
"ColliderURL": "http://cloud-3.steamusercontent.com/ugc/1754695414379239413/0B8E68F3B7311DCF2138FB701F78D1D93FBA4CAB/",
|
||||
"Convex": true,
|
||||
"DiffuseURL": "http://cloud-3.steamusercontent.com/ugc/1750192233783143973/D526236AAE16BDBB98D3F30E27BAFC1D3E21F4AC/",
|
||||
"MaterialIndex": 1,
|
||||
"MeshURL": "http://cloud-3.steamusercontent.com/ugc/1754695414379239413/0B8E68F3B7311DCF2138FB701F78D1D93FBA4CAB/",
|
||||
"NormalURL": "",
|
||||
"TypeIndex": 6
|
||||
},
|
||||
"Description": "Drop cards here to display name, cost and skill icons.\n\nSee context menu for options.",
|
||||
"DragSelectable": true,
|
||||
"GMNotes": "",
|
||||
"GUID": "d45664",
|
||||
"Grid": true,
|
||||
"GridProjection": false,
|
||||
"Hands": false,
|
||||
"HideWhenFaceDown": false,
|
||||
"IgnoreFoW": false,
|
||||
"LayoutGroupSortIndex": 0,
|
||||
"Locked": false,
|
||||
"LuaScriptState": "[[],true,true]",
|
||||
"LuaScript_path": "Fan-MadeAccessories.aa8b38/AttachmentHelper.7f4976/AttachmentHelper.d45664.ttslua",
|
||||
"MaterialIndex": -1,
|
||||
"MeasureMovement": false,
|
||||
"MeshIndex": -1,
|
||||
"Name": "Custom_Model_Bag",
|
||||
"Nickname": "Attachment Helper",
|
||||
"Number": 0,
|
||||
"Snap": true,
|
||||
"Sticky": true,
|
||||
"Tags": [
|
||||
"Asset",
|
||||
"scesetup_memory_object"
|
||||
],
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": 19.228,
|
||||
"posY": 3.822,
|
||||
"posZ": -19.636,
|
||||
"rotX": 0,
|
||||
"rotY": 270,
|
||||
"rotZ": 359,
|
||||
"scaleX": 0.8,
|
||||
"scaleY": 1,
|
||||
"scaleZ": 0.8
|
||||
},
|
||||
"Value": 0,
|
||||
"XmlUI": ""
|
||||
}
|
@ -0,0 +1,202 @@
|
||||
local OPTION_TEXT = {
|
||||
"Ancestral Knowledge",
|
||||
"Astronomical Atlas",
|
||||
"Crystallizer of Dreams",
|
||||
"Diana Stanley",
|
||||
"Gloria Goldberg",
|
||||
"Sefina Rousseau",
|
||||
"Wooden Sledge"
|
||||
}
|
||||
|
||||
local IMAGE_LIST = {
|
||||
-- Ancestral Knowledge
|
||||
"http://cloud-3.steamusercontent.com/ugc/1915746489207287888/2F9F6F211ED0F98E66C9D35D93221E4C7FB6DD3C/",
|
||||
-- Astronomical Atlas
|
||||
"http://cloud-3.steamusercontent.com/ugc/1754695853007989004/9153BC204FC707AE564ECFAC063A11CB8C2B5D1E/",
|
||||
-- Crystallizer of Dreams
|
||||
"http://cloud-3.steamusercontent.com/ugc/1915746489207280958/100F16441939E5E23818651D1EB5C209BF3125B9/",
|
||||
-- Diana Stanley
|
||||
"http://cloud-3.steamusercontent.com/ugc/1754695635919071208/1AB7222850201630826BFFBA8F2BD0065E2D572F/",
|
||||
-- Gloria Goldberg
|
||||
"http://cloud-3.steamusercontent.com/ugc/1754695635919102502/453D4426118C8A6DE2EA281184716E26CA924C84/",
|
||||
-- Sefina Rousseau
|
||||
"http://cloud-3.steamusercontent.com/ugc/1754695635919099826/3C3CBFFAADB2ACA9957C736491F470AE906CC953/",
|
||||
-- Wooden Sledge
|
||||
"http://cloud-3.steamusercontent.com/ugc/1750192233783143973/D526236AAE16BDBB98D3F30E27BAFC1D3E21F4AC/"
|
||||
}
|
||||
|
||||
-- save state and options to restore onLoad
|
||||
function onSave() return JSON.encode({ cardsInBag, showCost, showIcons }) end
|
||||
|
||||
-- load variables and create context menu
|
||||
function onLoad(savedData)
|
||||
local loadedData = JSON.decode(savedData)
|
||||
cardsInBag = loadedData[1] or {}
|
||||
showCost = loadedData[2] or true
|
||||
showIcons = loadedData[3] or true
|
||||
|
||||
recreateButtons()
|
||||
|
||||
self.addContextMenuItem("Select image", selectImage)
|
||||
self.addContextMenuItem("Toggle cost", function(color)
|
||||
showCost = not showCost
|
||||
printToColor("Show cost of cards: " .. tostring(showCost), color, "White")
|
||||
refresh()
|
||||
end)
|
||||
|
||||
self.addContextMenuItem("Toggle skill icons", function(color)
|
||||
showIcons = not showIcons
|
||||
printToColor("Show skill icons of cards: " .. tostring(showIcons), color, "White")
|
||||
refresh()
|
||||
end)
|
||||
|
||||
self.addContextMenuItem("More Information", function()
|
||||
printToAll("------------------------------", "White")
|
||||
printToAll("Attachment Helper by Chr1Z", "Orange")
|
||||
printToAll("original by bankey", "White")
|
||||
end)
|
||||
end
|
||||
|
||||
function selectImage(color)
|
||||
Player[color].showOptionsDialog("Select image:", OPTION_TEXT, 1, function(_, option_index)
|
||||
local customInfo = self.getCustomObject()
|
||||
customInfo.diffuse = IMAGE_LIST[option_index]
|
||||
self.setCustomObject(customInfo)
|
||||
self.reload()
|
||||
end)
|
||||
end
|
||||
|
||||
-- called for every card that enters
|
||||
function onObjectEnterContainer(container, object)
|
||||
if container == self then
|
||||
if object.tag ~= "Card" then
|
||||
broadcastToAll("The 'Attachment Helper' is meant to be used for single cards.", "White")
|
||||
else
|
||||
findCard(object.getGUID(), object.getName(), object.getGMNotes())
|
||||
end
|
||||
-- TODO: implement splitting of decks that get thrown in here
|
||||
recreateButtons()
|
||||
end
|
||||
end
|
||||
|
||||
-- removes leaving cards from the "cardInBag" table
|
||||
function onObjectLeaveContainer(container, object)
|
||||
if container == self then
|
||||
local guid = object.getGUID()
|
||||
local found = false
|
||||
for i, card in ipairs(cardsInBag) do
|
||||
if card.id == guid then
|
||||
table.remove(cardsInBag, i)
|
||||
found = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if found ~= true then
|
||||
local name = object.getName()
|
||||
for i, card in ipairs(cardsInBag) do
|
||||
if card.name == name then
|
||||
table.remove(cardsInBag, i)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
recreateButtons()
|
||||
end
|
||||
end
|
||||
|
||||
-- refreshes displayed buttons based on contained cards
|
||||
function refresh()
|
||||
cardsInBag = {}
|
||||
for _, object in ipairs(self.getObjects()) do
|
||||
findCard(object.guid, object.name, object.gm_notes)
|
||||
end
|
||||
recreateButtons()
|
||||
end
|
||||
|
||||
-- gets cost and icons for a card
|
||||
function findCard(guid, name, GMNotes)
|
||||
local cost = ""
|
||||
local icons = {}
|
||||
local metadata = {}
|
||||
local displayName = name
|
||||
|
||||
if displayName == nil or displayName == "" then displayName = "unnamed" end
|
||||
if showCost or showIcons then metadata = JSON.decode(GMNotes) end
|
||||
|
||||
if showCost then
|
||||
if GMNotes ~= "" then cost = metadata.cost end
|
||||
if cost == nil or cost == "" then cost = "–" end
|
||||
displayName = "[" .. cost .. "] " .. displayName
|
||||
end
|
||||
|
||||
if showIcons then
|
||||
if GMNotes ~= "" then
|
||||
icons[1] = metadata.wildIcons
|
||||
icons[2] = metadata.willpowerIcons
|
||||
icons[3] = metadata.intellectIcons
|
||||
icons[4] = metadata.combatIcons
|
||||
icons[5] = metadata.agilityIcons
|
||||
end
|
||||
|
||||
local IconTypes = { "Wild", "Willpower", "Intellect", "Combat", "Agility" }
|
||||
local found = false
|
||||
for i = 1, 5 do
|
||||
if icons[i] ~= nil and icons[i] ~= "" then
|
||||
if found == false then
|
||||
displayName = displayName .. "\n" .. IconTypes[i] .. ": " .. icons[i]
|
||||
found = true
|
||||
else
|
||||
displayName = displayName .. " " .. IconTypes[i] .. ": " .. icons[i]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
table.insert(cardsInBag, { name = name, displayName = displayName, id = guid })
|
||||
end
|
||||
|
||||
-- recreates buttons with up-to-date labels
|
||||
function recreateButtons()
|
||||
self.clearButtons()
|
||||
local verticalPosition = 1.65
|
||||
|
||||
for _, card in ipairs(cardsInBag) do
|
||||
local id = card.id
|
||||
local funcName = "removeCard" .. id
|
||||
self.setVar(funcName, function() removeCard(id) end)
|
||||
self.createButton({
|
||||
label = card.displayName,
|
||||
click_function = funcName,
|
||||
function_owner = self,
|
||||
position = { 0, 0, verticalPosition },
|
||||
height = 200,
|
||||
width = 1200,
|
||||
font_size = string.len(card.displayName) > 20 and 75 or 100
|
||||
})
|
||||
verticalPosition = verticalPosition - 0.5
|
||||
end
|
||||
|
||||
local countLabel = "Attachment\nHelper"
|
||||
if #cardsInBag ~= 0 then countLabel = #cardsInBag end
|
||||
|
||||
self.createButton({
|
||||
label = countLabel,
|
||||
click_function = "none",
|
||||
function_owner = self,
|
||||
position = { 0, 0, -1.35 },
|
||||
height = 0,
|
||||
width = 0,
|
||||
font_size = 225,
|
||||
font_color = { 1, 1, 1 }
|
||||
})
|
||||
end
|
||||
|
||||
-- click-function for buttons to take a card out of the bag
|
||||
function removeCard(cardGUID)
|
||||
self.takeObject({
|
||||
guid = cardGUID,
|
||||
rotation = self.getRotation(),
|
||||
position = self.getPosition() + Vector(0, 0.25, 0),
|
||||
callback_function = function(obj) obj.resting = true end
|
||||
})
|
||||
end
|
@ -41,6 +41,7 @@
|
||||
"Snap": true,
|
||||
"Sticky": true,
|
||||
"Tags": [
|
||||
"CleanUpHelper_ignore",
|
||||
"displacement_excluded"
|
||||
],
|
||||
"Tooltip": true,
|
||||
|
@ -40,6 +40,10 @@
|
||||
"Nickname": "Hand Helper",
|
||||
"Snap": true,
|
||||
"Sticky": true,
|
||||
"Tags": [
|
||||
"CleanUpHelper_ignore",
|
||||
"displacement_excluded"
|
||||
],
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": 37.613,
|
||||
|
@ -1,7 +1,7 @@
|
||||
MAT_GUIDS = { "8b081b", "bd0ff4", "383d8b", "0840d5" }
|
||||
local playmatAPI = require("playermat/PlaymatApi")
|
||||
|
||||
local BUTTON_PARAMETERS = {}
|
||||
BUTTON_PARAMETERS.function_owner = self
|
||||
local buttonParamaters = {}
|
||||
buttonParamaters.function_owner = self
|
||||
|
||||
-- saving "playerColor" and "des"
|
||||
function onSave() return JSON.encode({ playerColor, des}) end
|
||||
@ -13,41 +13,41 @@ function onLoad(saved_data)
|
||||
des = loaded_data[2] or false
|
||||
|
||||
-- index 0: button as hand size label
|
||||
BUTTON_PARAMETERS.hover_color = "White"
|
||||
BUTTON_PARAMETERS.click_function = "none"
|
||||
BUTTON_PARAMETERS.position = { 0, 0.1, -0.4 }
|
||||
BUTTON_PARAMETERS.height = 0
|
||||
BUTTON_PARAMETERS.width = 0
|
||||
BUTTON_PARAMETERS.font_size = 500
|
||||
BUTTON_PARAMETERS.font_color = "White"
|
||||
self.createButton(BUTTON_PARAMETERS)
|
||||
buttonParamaters.hover_color = "White"
|
||||
buttonParamaters.click_function = "none"
|
||||
buttonParamaters.position = { 0, 0.11, -0.4 }
|
||||
buttonParamaters.height = 0
|
||||
buttonParamaters.width = 0
|
||||
buttonParamaters.font_size = 500
|
||||
buttonParamaters.font_color = "White"
|
||||
self.createButton(buttonParamaters)
|
||||
|
||||
-- index 1: button to toggle "des"
|
||||
BUTTON_PARAMETERS.label = "DES: " .. (des and "✓" or "✗")
|
||||
BUTTON_PARAMETERS.click_function = "toggleDES"
|
||||
BUTTON_PARAMETERS.position = { 0.475, 0.1, 0.25 }
|
||||
BUTTON_PARAMETERS.height = 175
|
||||
BUTTON_PARAMETERS.width = 440
|
||||
BUTTON_PARAMETERS.font_size = 90
|
||||
BUTTON_PARAMETERS.font_color = "Black"
|
||||
self.createButton(BUTTON_PARAMETERS)
|
||||
buttonParamaters.label = "DES: " .. (des and "✓" or "✗")
|
||||
buttonParamaters.click_function = "toggleDES"
|
||||
buttonParamaters.position = { 0.475, 0.11, 0.25 }
|
||||
buttonParamaters.height = 175
|
||||
buttonParamaters.width = 440
|
||||
buttonParamaters.font_size = 90
|
||||
buttonParamaters.font_color = "Black"
|
||||
self.createButton(buttonParamaters)
|
||||
|
||||
-- index 2: button to discard a card
|
||||
BUTTON_PARAMETERS.label = "discard random card"
|
||||
BUTTON_PARAMETERS.click_function = "discardRandom"
|
||||
BUTTON_PARAMETERS.position = { 0, 0.1, 0.7 }
|
||||
BUTTON_PARAMETERS.width = 900
|
||||
self.createButton(BUTTON_PARAMETERS)
|
||||
buttonParamaters.label = "discard random card"
|
||||
buttonParamaters.click_function = "discardRandom"
|
||||
buttonParamaters.position = { 0, 0.11, 0.7 }
|
||||
buttonParamaters.width = 900
|
||||
self.createButton(buttonParamaters)
|
||||
|
||||
-- index 3: button to select color
|
||||
BUTTON_PARAMETERS.label = playerColor
|
||||
BUTTON_PARAMETERS.color = playerColor
|
||||
BUTTON_PARAMETERS.hover_color = playerColor
|
||||
BUTTON_PARAMETERS.click_function = "changeColor"
|
||||
BUTTON_PARAMETERS.tooltip = "change color"
|
||||
BUTTON_PARAMETERS.position = { -0.475, 0.1, 0.25 }
|
||||
BUTTON_PARAMETERS.width = 440
|
||||
self.createButton(BUTTON_PARAMETERS)
|
||||
buttonParamaters.label = playerColor
|
||||
buttonParamaters.color = playerColor
|
||||
buttonParamaters.hover_color = playerColor
|
||||
buttonParamaters.click_function = "changeColor"
|
||||
buttonParamaters.tooltip = "change color"
|
||||
buttonParamaters.position = { -0.475, 0.11, 0.25 }
|
||||
buttonParamaters.width = 440
|
||||
self.createButton(buttonParamaters)
|
||||
|
||||
-- start loop to update card count
|
||||
loopId = Wait.time(||updateValue(), 1, -1)
|
||||
@ -71,14 +71,6 @@ function onLoad(saved_data)
|
||||
end
|
||||
|
||||
function onObjectHover(hover_color, obj)
|
||||
-- error handling
|
||||
if obj == nil then return end
|
||||
|
||||
-- add context menu to "short supply"
|
||||
if obj.getName() == "Short Supply" then
|
||||
obj.addContextMenuItem("Discard 10 (" .. playerColor .. ")", shortSupply)
|
||||
end
|
||||
|
||||
-- only continue if correct player hovers over "self"
|
||||
if obj ~= self or hover_color ~= playerColor then return end
|
||||
|
||||
@ -151,11 +143,11 @@ function changeColor(_, _, isRightClick, color)
|
||||
end
|
||||
|
||||
-- update "change color" button (note: remove and create instantly updates hover_color)
|
||||
BUTTON_PARAMETERS.label = playerColor
|
||||
BUTTON_PARAMETERS.color = playerColor
|
||||
BUTTON_PARAMETERS.hover_color = playerColor
|
||||
buttonParamaters.label = playerColor
|
||||
buttonParamaters.color = playerColor
|
||||
buttonParamaters.hover_color = playerColor
|
||||
self.removeButton(3)
|
||||
self.createButton(BUTTON_PARAMETERS)
|
||||
self.createButton(buttonParamaters)
|
||||
end
|
||||
|
||||
---------------------------------------------------------
|
||||
@ -169,7 +161,8 @@ function discardRandom()
|
||||
if #hand == 0 then
|
||||
broadcastToAll("Cannot discard from empty hand!", "Red")
|
||||
else
|
||||
local mat = getPlayermat(playerColor)
|
||||
local searchPos = Player[playerColor].getHandTransform().position
|
||||
local mat = playmatAPI.getMatbyPosition(searchPos)
|
||||
if mat == nil then return end
|
||||
|
||||
local discardPos = mat.getTable("DISCARD_PILE_POSITION")
|
||||
@ -184,38 +177,6 @@ function discardRandom()
|
||||
end
|
||||
end
|
||||
|
||||
---------------------------------------------------------
|
||||
-- discards the top 10 cards of your deck
|
||||
---------------------------------------------------------
|
||||
function shortSupply(color)
|
||||
local mat = getPlayermat(playerColor)
|
||||
if mat == nil then return end
|
||||
|
||||
-- get draw deck and discard pile
|
||||
mat.call("getDrawDiscardDecks")
|
||||
drawDeck = mat.getVar("drawDeck")
|
||||
local discardPos = mat.getTable("DISCARD_PILE_POSITION")
|
||||
if discardPos == nil then
|
||||
broadcastToAll("Couldn't retrieve discard position from playermat!", "Red")
|
||||
return
|
||||
end
|
||||
|
||||
if drawDeck == nil then
|
||||
broadcastToColor("Deck not found!", color, "Yellow")
|
||||
return
|
||||
elseif drawDeck.tag ~= "Deck" then
|
||||
broadcastToColor("Deck only contains a single card!", color, "Yellow")
|
||||
return
|
||||
end
|
||||
|
||||
-- discard cards
|
||||
discardPos[2] = 0.5
|
||||
for i = 1, 10 do
|
||||
discardPos[2] = discardPos[2] + 0.05 * i
|
||||
drawDeck.takeObject({ flip = true; position = discardPos })
|
||||
end
|
||||
end
|
||||
|
||||
---------------------------------------------------------
|
||||
-- helper functions
|
||||
---------------------------------------------------------
|
||||
@ -232,27 +193,3 @@ function playerExists(color)
|
||||
local COLORS = Player.getAvailableColors()
|
||||
return indexOf(COLORS, color) and true or false
|
||||
end
|
||||
|
||||
-- helper to find playermat based on hand position
|
||||
function getPlayermat(color)
|
||||
local pos = Player[playerColor].getHandTransform().position
|
||||
if pos.x < -30 then
|
||||
if pos.z > 0 then
|
||||
playerNumber = 1
|
||||
else
|
||||
playerNumber = 2
|
||||
end
|
||||
else
|
||||
if pos.z > 0 then
|
||||
playerNumber = 3
|
||||
else
|
||||
playerNumber = 4
|
||||
end
|
||||
end
|
||||
|
||||
local mat = getObjectFromGUID(MAT_GUIDS[playerNumber])
|
||||
if mat == nil then
|
||||
broadcastToAll(playerColor .. " playermat could not be found!", "Yellow")
|
||||
end
|
||||
return mat
|
||||
end
|
||||
|
@ -32,7 +32,7 @@
|
||||
"Sticky": true,
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": -27.96,
|
||||
"posX": -30.5,
|
||||
"posY": 6,
|
||||
"posZ": 36.053,
|
||||
"rotX": 0,
|
||||
|
@ -32,9 +32,9 @@
|
||||
"Sticky": true,
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": -65.72,
|
||||
"posX": -65.7,
|
||||
"posY": 6,
|
||||
"posZ": -13.61,
|
||||
"posZ": -15.5,
|
||||
"rotX": 0,
|
||||
"rotY": 90,
|
||||
"rotZ": 0,
|
||||
|
@ -32,9 +32,9 @@
|
||||
"Sticky": true,
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": -65.581,
|
||||
"posX": -65.7,
|
||||
"posY": 6,
|
||||
"posZ": 13.55,
|
||||
"posZ": 15.5,
|
||||
"rotX": 0,
|
||||
"rotY": 90,
|
||||
"rotZ": 0,
|
||||
|
@ -32,7 +32,7 @@
|
||||
"Sticky": true,
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": -27.96,
|
||||
"posX": -30.5,
|
||||
"posY": 6,
|
||||
"posZ": -36.364,
|
||||
"rotX": 0,
|
||||
|
@ -42,11 +42,11 @@
|
||||
"Sticky": true,
|
||||
"Tooltip": false,
|
||||
"Transform": {
|
||||
"posX": -57.882,
|
||||
"posX": -57.887,
|
||||
"posY": 1.52,
|
||||
"posZ": -24.902,
|
||||
"posZ": -24.928,
|
||||
"rotX": 0,
|
||||
"rotY": 285,
|
||||
"rotY": 280,
|
||||
"rotZ": 0,
|
||||
"scaleX": 0.26,
|
||||
"scaleY": 1,
|
||||
|
@ -42,9 +42,9 @@
|
||||
"Sticky": true,
|
||||
"Tooltip": false,
|
||||
"Transform": {
|
||||
"posX": -57.837,
|
||||
"posX": -57.83,
|
||||
"posY": 1.52,
|
||||
"posZ": 7.19,
|
||||
"posZ": 7.229,
|
||||
"rotX": 0,
|
||||
"rotY": 280,
|
||||
"rotZ": 0,
|
||||
|
@ -42,9 +42,9 @@
|
||||
"Sticky": true,
|
||||
"Tooltip": false,
|
||||
"Transform": {
|
||||
"posX": -34.234,
|
||||
"posY": 1.52,
|
||||
"posZ": 29.394,
|
||||
"posX": -39.163,
|
||||
"posY": 1.519,
|
||||
"posZ": 29.487,
|
||||
"rotX": 0,
|
||||
"rotY": 10,
|
||||
"rotZ": 1,
|
||||
|
@ -42,11 +42,11 @@
|
||||
"Sticky": true,
|
||||
"Tooltip": false,
|
||||
"Transform": {
|
||||
"posX": -16.653,
|
||||
"posX": -21.469,
|
||||
"posY": 1.52,
|
||||
"posZ": -29.429,
|
||||
"posZ": -29.42,
|
||||
"rotX": 0,
|
||||
"rotY": 195,
|
||||
"rotY": 190,
|
||||
"rotZ": 0,
|
||||
"scaleX": 0.26,
|
||||
"scaleY": 1,
|
||||
|
@ -46,9 +46,9 @@
|
||||
"Sticky": true,
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": -42.227,
|
||||
"posY": 1.632,
|
||||
"posZ": -28.959,
|
||||
"posX": -45.4,
|
||||
"posY": 1.581,
|
||||
"posZ": -26,
|
||||
"rotX": 0,
|
||||
"rotY": 180,
|
||||
"rotZ": 0,
|
||||
|
@ -46,9 +46,9 @@
|
||||
"Sticky": true,
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": -44.101,
|
||||
"posY": 1.652,
|
||||
"posZ": 28.985,
|
||||
"posX": -45.4,
|
||||
"posY": 1.581,
|
||||
"posZ": 26,
|
||||
"rotX": 0,
|
||||
"rotY": 0,
|
||||
"rotZ": 0,
|
||||
|
@ -46,7 +46,7 @@
|
||||
],
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": -32.6,
|
||||
"posX": -37.35,
|
||||
"posY": 1.531,
|
||||
"posZ": 19.35,
|
||||
"rotX": 0,
|
||||
|
@ -46,7 +46,7 @@
|
||||
],
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": -47.76,
|
||||
"posX": -47.75,
|
||||
"posY": 1.531,
|
||||
"posZ": -23.1,
|
||||
"rotX": 0,
|
||||
|
@ -46,7 +46,7 @@
|
||||
],
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": -18.6,
|
||||
"posX": -23.35,
|
||||
"posY": 1.531,
|
||||
"posZ": -19.35,
|
||||
"rotX": 0,
|
||||
|
@ -1157,7 +1157,7 @@
|
||||
],
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": -19.17,
|
||||
"posX": -23.92,
|
||||
"posY": 1.55,
|
||||
"posZ": -24.845,
|
||||
"rotX": 0,
|
||||
|
@ -1157,7 +1157,7 @@
|
||||
],
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": -34.293,
|
||||
"posX": -39.043,
|
||||
"posY": 1.55,
|
||||
"posZ": 24.864,
|
||||
"rotX": 0,
|
||||
|
@ -1157,7 +1157,7 @@
|
||||
],
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": -18.025,
|
||||
"posX": -22.776,
|
||||
"posY": 1.55,
|
||||
"posZ": -24.845,
|
||||
"rotX": 0,
|
||||
|
@ -1157,9 +1157,9 @@
|
||||
],
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": -20.049,
|
||||
"posX": -24.91,
|
||||
"posY": 1.55,
|
||||
"posZ": -24.78,
|
||||
"posZ": -24.84,
|
||||
"rotX": 0,
|
||||
"rotY": 180,
|
||||
"rotZ": 0,
|
||||
|
@ -1157,7 +1157,7 @@
|
||||
],
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": -32.011,
|
||||
"posX": -36.761,
|
||||
"posY": 1.55,
|
||||
"posZ": 24.864,
|
||||
"rotX": 0,
|
||||
|
@ -1157,9 +1157,9 @@
|
||||
],
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": -30.997,
|
||||
"posX": -35.77,
|
||||
"posY": 1.55,
|
||||
"posZ": 24.81,
|
||||
"posZ": 24.86,
|
||||
"rotX": 0,
|
||||
"rotY": 0,
|
||||
"rotZ": 0,
|
||||
|
@ -1157,7 +1157,7 @@
|
||||
],
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": -16.887,
|
||||
"posX": -21.638,
|
||||
"posY": 1.55,
|
||||
"posZ": -24.845,
|
||||
"rotX": 0,
|
||||
|
@ -1157,7 +1157,7 @@
|
||||
],
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": -33.149,
|
||||
"posX": -37.899,
|
||||
"posY": 1.55,
|
||||
"posZ": 24.864,
|
||||
"rotX": 0,
|
||||
|
@ -1 +1 @@
|
||||
{"optionPanel":{"showAttachmentHelper":false,"showChaosBagManager":false,"showCleanUpHelper":false,"showCustomPlaymatImages":false,"showCYOA":false,"showDisplacementTool":false,"showDrawButton":false,"showHandHelper":[],"showNavigationOverlay":false,"showTokenArranger":false,"useClueClickers":false,"useSnapTags":true}}
|
||||
{"optionPanel":{"showAttachmentHelper":false,"showChaosBagManager":false,"showCleanUpHelper":false,"useClueClickers":false,"showCustomPlaymatImages":false,"showCYOA":false,"showDisplacementTool":false,"showDrawButton":false,"showHandHelper":[],"showNavigationOverlay":false,"useSnapTags":true,"showTitleSplash":true,"showTokenArranger":false}}
|
||||
|
57
objects/PlayerCards.2d30ee.json
Normal file
57
objects/PlayerCards.2d30ee.json
Normal file
@ -0,0 +1,57 @@
|
||||
{
|
||||
"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": "https://i.imgur.com/dISlnEk.jpg",
|
||||
"ImageURL": "https://i.imgur.com/dISlnEk.jpg",
|
||||
"WidthScale": 0
|
||||
},
|
||||
"Description": "",
|
||||
"DragSelectable": true,
|
||||
"GMNotes": "",
|
||||
"GUID": "2d30ee",
|
||||
"Grid": true,
|
||||
"GridProjection": false,
|
||||
"Hands": false,
|
||||
"HideWhenFaceDown": false,
|
||||
"IgnoreFoW": false,
|
||||
"LayoutGroupSortIndex": 0,
|
||||
"Locked": false,
|
||||
"LuaScript": "require(\"playercards/PlayerCardPanel\")",
|
||||
"LuaScriptState": "{\"spawnBagState\":{\"placed\":[],\"placedObjects\":[]}}",
|
||||
"MeasureMovement": false,
|
||||
"Name": "Custom_Tile",
|
||||
"Nickname": "Player Cards",
|
||||
"Snap": true,
|
||||
"Sticky": true,
|
||||
"Tooltip": false,
|
||||
"Transform": {
|
||||
"posX": -1.083,
|
||||
"posY": 1.255,
|
||||
"posZ": 69.985,
|
||||
"rotX": 0,
|
||||
"rotY": 270,
|
||||
"rotZ": 0,
|
||||
"scaleX": 9.39,
|
||||
"scaleY": 1,
|
||||
"scaleZ": 9.39
|
||||
},
|
||||
"Value": 0,
|
||||
"XmlUI": ""
|
||||
}
|
@ -145,30 +145,6 @@
|
||||
"Asset"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": 1.37,
|
||||
"y": 0.1,
|
||||
"z": -0.637
|
||||
},
|
||||
"Rotation": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": 0.914,
|
||||
"y": 0.1,
|
||||
"z": -0.637
|
||||
},
|
||||
"Rotation": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -1.817,
|
||||
@ -282,7 +258,7 @@
|
||||
"Sticky": true,
|
||||
"Tooltip": false,
|
||||
"Transform": {
|
||||
"posX": -25.6,
|
||||
"posX": -30.35,
|
||||
"posY": 1.45,
|
||||
"posZ": 26.6,
|
||||
"rotX": 0,
|
||||
|
@ -179,30 +179,6 @@
|
||||
"z": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": 0.911,
|
||||
"y": 0.1,
|
||||
"z": -0.641
|
||||
},
|
||||
"Rotation": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": 1.367,
|
||||
"y": 0.1,
|
||||
"z": -0.641
|
||||
},
|
||||
"Rotation": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"x": -0.982,
|
||||
@ -282,7 +258,7 @@
|
||||
"Sticky": true,
|
||||
"Tooltip": false,
|
||||
"Transform": {
|
||||
"posX": -25.6,
|
||||
"posX": -30.35,
|
||||
"posY": 1.45,
|
||||
"posZ": -26.6,
|
||||
"rotX": 0,
|
||||
|
@ -42,9 +42,9 @@
|
||||
"Sticky": true,
|
||||
"Tooltip": false,
|
||||
"Transform": {
|
||||
"posX": -59.774,
|
||||
"posX": -59.817,
|
||||
"posY": 1.52,
|
||||
"posZ": 7.535,
|
||||
"posZ": 7.617,
|
||||
"rotX": 0,
|
||||
"rotY": 280,
|
||||
"rotZ": 0,
|
||||
|
@ -42,11 +42,11 @@
|
||||
"Sticky": true,
|
||||
"Tooltip": false,
|
||||
"Transform": {
|
||||
"posX": -59.793,
|
||||
"posX": -59.798,
|
||||
"posY": 1.52,
|
||||
"posZ": -24.544,
|
||||
"posZ": -24.571,
|
||||
"rotX": 0,
|
||||
"rotY": 285,
|
||||
"rotY": 280,
|
||||
"rotZ": 0,
|
||||
"scaleX": 0.26,
|
||||
"scaleY": 1,
|
||||
|
@ -42,11 +42,11 @@
|
||||
"Sticky": true,
|
||||
"Tooltip": false,
|
||||
"Transform": {
|
||||
"posX": -17.037,
|
||||
"posX": -21.914,
|
||||
"posY": 1.52,
|
||||
"posZ": -31.384,
|
||||
"posZ": -31.433,
|
||||
"rotX": 0,
|
||||
"rotY": 195,
|
||||
"rotY": 190,
|
||||
"rotZ": 0,
|
||||
"scaleX": 0.26,
|
||||
"scaleY": 1,
|
||||
|
@ -42,9 +42,9 @@
|
||||
"Sticky": true,
|
||||
"Tooltip": false,
|
||||
"Transform": {
|
||||
"posX": -33.889,
|
||||
"posX": -38.812,
|
||||
"posY": 1.52,
|
||||
"posZ": 31.335,
|
||||
"posZ": 31.434,
|
||||
"rotX": 0,
|
||||
"rotY": 10,
|
||||
"rotZ": 0,
|
||||
|
@ -46,9 +46,9 @@
|
||||
"Sticky": true,
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": -44.105,
|
||||
"posY": 1.651,
|
||||
"posZ": 26.75,
|
||||
"posX": -45.4,
|
||||
"posY": 1.581,
|
||||
"posZ": 21.5,
|
||||
"rotX": 0,
|
||||
"rotY": 0,
|
||||
"rotZ": 0,
|
||||
|
@ -46,9 +46,9 @@
|
||||
"Sticky": true,
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": -42.223,
|
||||
"posY": 1.633,
|
||||
"posZ": -26.724,
|
||||
"posX": -45.4,
|
||||
"posY": 1.581,
|
||||
"posZ": -21.5,
|
||||
"rotX": 0,
|
||||
"rotY": 180,
|
||||
"rotZ": 0,
|
||||
|
@ -37,14 +37,14 @@
|
||||
"LuaScriptState": "",
|
||||
"MeasureMovement": false,
|
||||
"Name": "Custom_Tile",
|
||||
"Nickname": "",
|
||||
"Nickname": "Round Sequence / Action Description",
|
||||
"Snap": true,
|
||||
"Sticky": true,
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": -43.21,
|
||||
"posY": 1.55,
|
||||
"posZ": 22.5,
|
||||
"posX": -57,
|
||||
"posY": 1.255,
|
||||
"posZ": 48,
|
||||
"rotX": 0,
|
||||
"rotY": 270,
|
||||
"rotZ": 0,
|
@ -37,14 +37,14 @@
|
||||
"LuaScriptState": "",
|
||||
"MeasureMovement": false,
|
||||
"Name": "Custom_Tile",
|
||||
"Nickname": "",
|
||||
"Nickname": "Round Sequence / Action Description",
|
||||
"Snap": true,
|
||||
"Sticky": true,
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": -43.21,
|
||||
"posY": 1.55,
|
||||
"posZ": -22.5,
|
||||
"posX": -65,
|
||||
"posY": 1.355,
|
||||
"posZ": 48,
|
||||
"rotX": 0,
|
||||
"rotY": 270,
|
||||
"rotZ": 180,
|
@ -43,9 +43,9 @@
|
||||
"Sticky": true,
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": -60.748,
|
||||
"posY": 1.316,
|
||||
"posZ": 54.855,
|
||||
"posX": -61,
|
||||
"posY": 1.27,
|
||||
"posZ": 59,
|
||||
"rotX": 0,
|
||||
"rotY": 270,
|
||||
"rotZ": 0,
|
||||
|
@ -31,7 +31,7 @@
|
||||
"Sticky": true,
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": -14.05,
|
||||
"posX": -18.8,
|
||||
"posY": 1.481,
|
||||
"posZ": -28.6,
|
||||
"rotX": 0,
|
||||
|
@ -31,7 +31,7 @@
|
||||
"Sticky": true,
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": -27.977,
|
||||
"posX": -30.5,
|
||||
"posY": 4.076,
|
||||
"posZ": -37.889,
|
||||
"rotX": 0,
|
||||
|
@ -31,7 +31,7 @@
|
||||
"Sticky": true,
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": -28.046,
|
||||
"posX": -30.5,
|
||||
"posY": 4.065,
|
||||
"posZ": 37.669,
|
||||
"rotX": 0,
|
||||
|
@ -33,7 +33,7 @@
|
||||
"Transform": {
|
||||
"posX": -66.804,
|
||||
"posY": 4.135,
|
||||
"posZ": 13.565,
|
||||
"posZ": 15.5,
|
||||
"rotX": 0,
|
||||
"rotY": 90,
|
||||
"rotZ": 0,
|
||||
|
@ -33,7 +33,7 @@
|
||||
"Transform": {
|
||||
"posX": -66.963,
|
||||
"posY": 4.117,
|
||||
"posZ": -13.277,
|
||||
"posZ": -15.5,
|
||||
"rotX": 0,
|
||||
"rotY": 90,
|
||||
"rotZ": 0,
|
||||
|
@ -31,7 +31,7 @@
|
||||
"Sticky": true,
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": -37.15,
|
||||
"posX": -41.9,
|
||||
"posY": 1.468,
|
||||
"posZ": 28.6,
|
||||
"rotX": 0,
|
||||
|
@ -18,7 +18,7 @@
|
||||
"Damage.cd2a02",
|
||||
"Horror.36be72",
|
||||
"ClueDoom.a3fb6c",
|
||||
"Reesource.00d19a"
|
||||
"Resource.00d19a"
|
||||
],
|
||||
"ContainedObjects_path": "TokenSource.124381",
|
||||
"Description": "",
|
||||
|
@ -40,7 +40,7 @@
|
||||
"Nickname": "ClueDoom",
|
||||
"Snap": false,
|
||||
"Sticky": true,
|
||||
"Tooltip": false,
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": 78.661,
|
||||
"posY": 2.398,
|
||||
|
@ -40,7 +40,7 @@
|
||||
"Nickname": "ClueDoom",
|
||||
"Snap": false,
|
||||
"Sticky": true,
|
||||
"Tooltip": false,
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": 78.738,
|
||||
"posY": 2.287,
|
||||
|
@ -37,10 +37,10 @@
|
||||
"LuaScriptState": "",
|
||||
"MeasureMovement": false,
|
||||
"Name": "Custom_Token",
|
||||
"Nickname": "Reesource",
|
||||
"Nickname": "Resource",
|
||||
"Snap": false,
|
||||
"Sticky": true,
|
||||
"Tooltip": false,
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": 78.848,
|
||||
"posY": 2.273,
|
@ -46,7 +46,7 @@
|
||||
"Sticky": true,
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": -37.497,
|
||||
"posX": -42.25,
|
||||
"posY": 1.653,
|
||||
"posZ": -19.3,
|
||||
"rotX": 0,
|
||||
|
@ -46,7 +46,7 @@
|
||||
"Sticky": true,
|
||||
"Tooltip": true,
|
||||
"Transform": {
|
||||
"posX": -37.5,
|
||||
"posX": -42.25,
|
||||
"posY": 1.664,
|
||||
"posZ": 19.3,
|
||||
"rotX": 0,
|
||||
|
@ -134,15 +134,6 @@ do
|
||||
|
||||
internal.maybePrint(table.concat({ "Found decklist: ", deck.name }), playerColor)
|
||||
|
||||
log(table.concat({ "-", deck.name, "-" }))
|
||||
for k, v in pairs(deck) do
|
||||
if type(v) == "table" then
|
||||
log(table.concat { k, ": <table>" })
|
||||
else
|
||||
log(table.concat { k, ": ", tostring(v) })
|
||||
end
|
||||
end
|
||||
|
||||
-- Initialize deck slot table and perform common transformations. The order of these should not
|
||||
-- be changed, as later steps may act on cards added in each. For example, a random weakness or
|
||||
-- investigator may have bonded cards or taboo entries, and should be present
|
||||
|
@ -34,6 +34,7 @@ local chaosTokens = {}
|
||||
local chaosTokensLastMat = nil
|
||||
local IS_RESHUFFLING = false
|
||||
local bagSearchers = {}
|
||||
local hideTitleSplashWaitFunctionId = nil
|
||||
local playmatAPI = require("playermat/PlaymatApi")
|
||||
|
||||
---------------------------------------------------------
|
||||
@ -818,6 +819,10 @@ function applyOptionPanelChange(id, state)
|
||||
-- update master clue counter
|
||||
getObjectFromGUID("4a3aa4").setVar("useClickableCounters", state)
|
||||
|
||||
-- option: Show Title on placing scenarios
|
||||
elseif id == "showTitleSplash" then
|
||||
optionPanel[id] = state
|
||||
|
||||
-- option: Show token arranger
|
||||
elseif id == "showTokenArranger" then
|
||||
-- delete previously pulled out tokens
|
||||
@ -833,8 +838,8 @@ function applyOptionPanelChange(id, state)
|
||||
elseif id == "showHandHelper" then
|
||||
optionPanel[id][1] = spawnOrRemoveHelper(state, "Hand Helper", {-50.84, 1.6, 7.02}, {0, 270, 0}, "White")
|
||||
optionPanel[id][2] = spawnOrRemoveHelper(state, "Hand Helper", {-50.90, 1.6, -25.10}, {0, 270, 0}, "Orange")
|
||||
optionPanel[id][3] = spawnOrRemoveHelper(state, "Hand Helper", {-34.38, 1.6, 22.44}, {0, 000, 0}, "Green")
|
||||
optionPanel[id][4] = spawnOrRemoveHelper(state, "Hand Helper", {-16.69, 1.6, -22.42}, {0, 180, 0}, "Red")
|
||||
optionPanel[id][3] = spawnOrRemoveHelper(state, "Hand Helper", {-39.27, 1.6, 22.44}, {0, 000, 0}, "Green")
|
||||
optionPanel[id][4] = spawnOrRemoveHelper(state, "Hand Helper", {-21.51, 1.6, -22.44}, {0, 180, 0}, "Red")
|
||||
|
||||
-- option: Show chaos bag manager
|
||||
elseif id == "showChaosBagManager" then
|
||||
@ -951,7 +956,7 @@ function onClick_defaultSettings()
|
||||
for id, _ in pairs(optionPanel) do
|
||||
local state = false
|
||||
-- override for settings that are enabled by default
|
||||
if id == "useSnapTags" then
|
||||
if id == "useSnapTags" or id == "showTitleSplash" then
|
||||
state = true
|
||||
end
|
||||
applyOptionPanelChange(id, state)
|
||||
@ -962,6 +967,7 @@ function onClick_defaultSettings()
|
||||
useSnapTags = true,
|
||||
showDrawButton = false,
|
||||
useClueClickers = false,
|
||||
showTitleSplash = true,
|
||||
showTokenArranger = false,
|
||||
showCleanUpHelper = false,
|
||||
showHandHelper = {},
|
||||
@ -972,3 +978,25 @@ function onClick_defaultSettings()
|
||||
-- update UI
|
||||
updateOptionPanelState()
|
||||
end
|
||||
|
||||
-- splash scenario title on setup
|
||||
function titleSplash(scenarioName)
|
||||
if optionPanel['showTitleSplash'] then
|
||||
|
||||
-- if there's any ongoing title being displayed, hide it and cancel the waiting function
|
||||
if hideTitleSplashWaitFunctionId then
|
||||
Wait.stop(hideTitleSplashWaitFunctionId)
|
||||
hideTitleSplashWaitFunctionId = nil
|
||||
UI.setAttribute('title_splash', 'active', false)
|
||||
end
|
||||
|
||||
-- display scenario name and set a 4 seconds (2 seconds animation and 2 seconds on screen)
|
||||
-- wait timer to hide the scenario name
|
||||
UI.setValue('title_splash', scenarioName)
|
||||
UI.show('title_splash')
|
||||
hideTitleSplashWaitFunctionId = Wait.time(function()
|
||||
UI.hide('title_splash')
|
||||
hideTitleSplashWaitFunctionId = nil
|
||||
end, 4)
|
||||
end
|
||||
end
|
||||
|
@ -55,6 +55,7 @@ function resetTokensIfInDeckZone(container, object)
|
||||
end
|
||||
|
||||
function fireScenarioChangedEvent()
|
||||
Global.call('titleSplash', currentScenario)
|
||||
playArea.onScenarioChanged(currentScenario)
|
||||
end
|
||||
|
||||
|
@ -5,10 +5,24 @@ local tokenManager = require("core/token/TokenManager")
|
||||
---------------------------------------------------------
|
||||
|
||||
-- set true to enable debug logging
|
||||
DEBUG = false
|
||||
local DEBUG = false
|
||||
|
||||
-- Location connection directional options
|
||||
local BIDIRECTIONAL = 0
|
||||
local ONE_WAY = 1
|
||||
|
||||
-- Connector draw parameters
|
||||
local CONNECTION_THICKNESS = 0.015
|
||||
local CONNECTION_COLOR = { 0.4, 0.4, 0.4, 1 }
|
||||
local DIRECTIONAL_ARROW_DISTANCE = 3.5
|
||||
local ARROW_ARM_LENGTH = 0.9
|
||||
local ARROW_ANGLE = 25
|
||||
|
||||
-- Height to draw the connector lines, places them just above the table and always below cards
|
||||
local CONNECTION_LINE_Y = 1.529
|
||||
|
||||
-- we use this to turn off collision handling until onLoad() is complete
|
||||
COLLISION_ENABLED = false
|
||||
local collisionEnabled = false
|
||||
|
||||
local SHIFT_OFFSETS = {
|
||||
left = { x = 0.00, y = 0, z = 7.67 },
|
||||
@ -21,10 +35,23 @@ local SHIFT_EXCLUSION = {
|
||||
["f182ee"] = true,
|
||||
["721ba2"] = true
|
||||
}
|
||||
local LOC_LINK_EXCLUDE_SCENARIOS = {
|
||||
["Devil Reef"] = true,
|
||||
["The Witching Hour"] = true,
|
||||
}
|
||||
|
||||
local INVESTIGATOR_COUNTER_GUID = "f182ee"
|
||||
local PLAY_AREA_ZONE_GUID = "a2f932"
|
||||
|
||||
local clueData = {}
|
||||
local spawnedLocationGUIDs = {}
|
||||
|
||||
local locations = { }
|
||||
local locationConnections = { }
|
||||
local draggingGuids = { }
|
||||
|
||||
local locationData
|
||||
|
||||
local currentScenario
|
||||
|
||||
---------------------------------------------------------
|
||||
@ -33,17 +60,19 @@ local currentScenario
|
||||
|
||||
function onSave()
|
||||
return JSON.encode({
|
||||
currentScenario = currentScenario
|
||||
trackedLocations = locations,
|
||||
currentScenario = currentScenario,
|
||||
})
|
||||
end
|
||||
|
||||
function onLoad(saveState)
|
||||
-- records locations we have spawned clues for
|
||||
local saveData = JSON.decode(saveState) or {}
|
||||
currentScenario = saveData.currentScenario
|
||||
local save = JSON.decode(saveState) or { }
|
||||
locations = save.trackedLocations or { }
|
||||
currentScenario = save.currentScenario
|
||||
|
||||
self.interactable = DEBUG
|
||||
Wait.time(function() COLLISION_ENABLED = true end, 1)
|
||||
Wait.time(function() collisionEnabled = true end, 1)
|
||||
end
|
||||
|
||||
function log(message)
|
||||
@ -60,14 +89,15 @@ function updateLocations(args)
|
||||
end
|
||||
end
|
||||
|
||||
function onCollisionEnter(collision_info)
|
||||
if not COLLISION_ENABLED then return end
|
||||
|
||||
function onCollisionEnter(collisionInfo)
|
||||
if not collisionEnabled then return end
|
||||
-- check if we should spawn clues here and do so according to playercount
|
||||
local card = collision_info.collision_object
|
||||
local card = collisionInfo.collision_object
|
||||
if shouldSpawnTokens(card) then
|
||||
tokenManager.spawnForCard(card)
|
||||
end
|
||||
draggingGuids[card.getGUID()] = nil
|
||||
maybeTrackLocation(card)
|
||||
end
|
||||
|
||||
function shouldSpawnTokens(card)
|
||||
@ -81,6 +111,267 @@ function shouldSpawnTokens(card)
|
||||
or metadata.weakness
|
||||
end
|
||||
|
||||
function onCollisionExit(collisionInfo)
|
||||
maybeUntrackLocation(collisionInfo.collision_object)
|
||||
end
|
||||
|
||||
-- Destroyed objects don't trigger onCollisionExit(), so check on destruction to untrack as well
|
||||
function onObjectDestroy(object)
|
||||
maybeUntrackLocation(object)
|
||||
end
|
||||
|
||||
function onObjectPickUp(player, object)
|
||||
-- onCollisionExit fires first, so we have to check the card to see if it's a location we should
|
||||
-- be tracking
|
||||
if showLocationLinks() and isInPlayArea(object) and object.getGMNotes() ~= nil and object.getGMNotes() ~= "" then
|
||||
local pickedUpGuid = object.getGUID()
|
||||
local metadata = JSON.decode(object.getGMNotes())
|
||||
if (metadata.type == "Location") then
|
||||
draggingGuids[pickedUpGuid] = metadata
|
||||
rebuildConnectionList()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function onUpdate()
|
||||
-- Due to the frequence of onUpdate calls, ensure that we only process any changes to the
|
||||
-- connection list once, and only redraw once
|
||||
local needsConnectionRebuild = false
|
||||
local needsConnectionDraw = false
|
||||
for guid, _ in pairs(draggingGuids) do
|
||||
local obj = getObjectFromGUID(guid)
|
||||
if obj == nil or not isInPlayArea(obj) then
|
||||
draggingGuids[guid] = nil
|
||||
needsConnectionRebuild = true
|
||||
end
|
||||
-- Even if the last location left the play area, need one last draw to clear the lines
|
||||
needsConnectionDraw = true
|
||||
end
|
||||
if (needsConnectionRebuild) then
|
||||
rebuildConnectionList()
|
||||
end
|
||||
if needsConnectionDraw then
|
||||
drawConnections()
|
||||
end
|
||||
end
|
||||
|
||||
-- Checks the given card and adds it to the list of locations tracked for connection purposes.
|
||||
-- A card will be added to the tracking if it is a location in the play area (based on centerpoint).
|
||||
-- @param A card object, possibly a location.
|
||||
function maybeTrackLocation(card)
|
||||
-- Collision checks for any part of the card overlap, but our other tracking is centerpoint
|
||||
-- Ignore any collision where the centerpoint isn't in the area
|
||||
if showLocationLinks() and isInPlayArea(card) then
|
||||
local metadata = JSON.decode(card.getGMNotes()) or { }
|
||||
if metadata.type == "Location" then
|
||||
locations[card.getGUID()] = metadata
|
||||
rebuildConnectionList()
|
||||
drawConnections()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Stop tracking a location for connection drawing. This should be called for both collision exit
|
||||
-- and destruction, as a destroyed object does not trigger collision exit. An object can also be
|
||||
-- deleted mid-drag, but the ordering for drag events means we can't clear those here and those will
|
||||
-- be cleared in the next onUpdate() cycle.
|
||||
-- @param card 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.
|
||||
if locations[card.getGUID()] ~= nil and not card.locked then
|
||||
locations[card.getGUID()] = nil
|
||||
rebuildConnectionList()
|
||||
drawConnections()
|
||||
end
|
||||
end
|
||||
|
||||
-- Builds a list of GUID to GUID connection information based on the currently tracked locations.
|
||||
-- This will update the connection information and store it in the locationConnections data member,
|
||||
-- but does not draw those connections. This should often be followed by a call to
|
||||
-- drawConnections()
|
||||
function rebuildConnectionList()
|
||||
if not showLocationLinks() then
|
||||
locationConnections = { }
|
||||
return
|
||||
end
|
||||
|
||||
local iconCardList = { }
|
||||
|
||||
-- Build a list of cards with each icon as their location ID
|
||||
for cardId, metadata in pairs(draggingGuids) do
|
||||
buildLocListByIcon(cardId, iconCardList)
|
||||
end
|
||||
for cardId, metadata in pairs(locations) do
|
||||
buildLocListByIcon(cardId, iconCardList)
|
||||
end
|
||||
|
||||
-- Pair up all the icons
|
||||
locationConnections = { }
|
||||
for cardId, metadata in pairs(draggingGuids) do
|
||||
buildConnection(cardId, iconCardList)
|
||||
end
|
||||
for cardId, metadata in pairs(locations) do
|
||||
if draggingGuids[cardId] == nil then
|
||||
buildConnection(cardId, iconCardList)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Extracts the card's icon string into a list of individual location icons
|
||||
-- @param cardID GUID of the card to pull the icon data from
|
||||
-- @param iconCardList A table of icon->GUID list. Mutable, will be updated by this method
|
||||
function buildLocListByIcon(cardId, iconCardList)
|
||||
local card = getObjectFromGUID(cardId)
|
||||
local locData = getLocationData(card)
|
||||
if locData ~= nil and locData.icons ~= nil then
|
||||
for icon in string.gmatch(locData.icons, "%a+") do
|
||||
if iconCardList[icon] == nil then
|
||||
iconCardList[icon] = { }
|
||||
end
|
||||
table.insert(iconCardList[icon], card.getGUID())
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Builds the connections for the given cardID by finding matching icons and adding them to the
|
||||
-- Playarea's locationConnections table.
|
||||
-- @param cardId GUID of the card to build the connections for
|
||||
-- @param iconCardList A table of icon->GUID List. Used to find matching icons for connections.
|
||||
function buildConnection(cardId, iconCardList)
|
||||
local card = getObjectFromGUID(cardId)
|
||||
local locData = getLocationData(card)
|
||||
if locData ~= nil and locData.connections ~= nil then
|
||||
locationConnections[card.getGUID()] = { }
|
||||
for icon in string.gmatch(locData.connections, "%a+") do
|
||||
if iconCardList[icon] ~= nil then
|
||||
for _, connectedGuid in ipairs(iconCardList[icon]) do
|
||||
-- If the reciprocal exists, convert it to BiDi, otherwise add as a one-way
|
||||
if locationConnections[connectedGuid] ~= nil
|
||||
and locationConnections[connectedGuid][card.getGUID()] ~= nil then
|
||||
locationConnections[connectedGuid][card.getGUID()] = BIDIRECTIONAL
|
||||
else
|
||||
locationConnections[card.getGUID()][connectedGuid] = ONE_WAY
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Helper method to extract the location metadata from a card based on whether it's front or back
|
||||
-- is showing.
|
||||
-- @param card Card object to extract data from
|
||||
-- @return Table with either the locationFront or locationBack metadata structure, or nil if the
|
||||
-- metadata doesn't exist
|
||||
function getLocationData(card)
|
||||
if card == nil then
|
||||
return nil
|
||||
end
|
||||
if card.is_face_down then
|
||||
return JSON.decode(card.getGMNotes()).locationBack
|
||||
else
|
||||
return JSON.decode(card.getGMNotes()).locationFront
|
||||
end
|
||||
end
|
||||
|
||||
-- Draws the lines for connections currently in locationConnections.
|
||||
function drawConnections()
|
||||
if not showLocationLinks() then
|
||||
locationConnections = { }
|
||||
return
|
||||
end
|
||||
local cardConnectionLines = { }
|
||||
|
||||
for originGuid, targetGuids in pairs(locationConnections) do
|
||||
-- Objects should reliably exist at this point, but since this can be called during onUpdate the
|
||||
-- object checks are conservative just to make sure.
|
||||
local origin = getObjectFromGUID(originGuid)
|
||||
if origin != nil then
|
||||
for targetGuid, direction in pairs(targetGuids) do
|
||||
local target = getObjectFromGUID(targetGuid)
|
||||
if target != nil then
|
||||
if direction == BIDIRECTIONAL then
|
||||
addBidirectionalVector(origin, target, cardConnectionLines)
|
||||
elseif direction == ONE_WAY then
|
||||
addOneWayVector(origin, target, cardConnectionLines)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
self.setVectorLines(cardConnectionLines)
|
||||
end
|
||||
|
||||
-- Draws a bidirectional location connection between the two cards, adding the lines to do so to the
|
||||
-- given lines list.
|
||||
-- @param card1 One of the card objects to connect
|
||||
-- @param card2 The other card object to connect
|
||||
-- @param lines List of vector line elements. Mutable, will be updated to add this connector
|
||||
function addBidirectionalVector(card1, card2, lines)
|
||||
local cardPos1 = card1.getPosition()
|
||||
local cardPos2 = card2.getPosition()
|
||||
cardPos1.y = CONNECTION_LINE_Y
|
||||
cardPos2.y = CONNECTION_LINE_Y
|
||||
local pos1 = self.positionToLocal(cardPos1)
|
||||
local pos2 = self.positionToLocal(cardPos2)
|
||||
table.insert(lines, {
|
||||
points = { pos1, pos2 },
|
||||
color = CONNECTION_COLOR,
|
||||
thickness = CONNECTION_THICKNESS,
|
||||
})
|
||||
end
|
||||
|
||||
-- Draws a one-way location connection between the two cards, adding the lines to do so to the
|
||||
-- given lines list. Arrows will point towards the target card.
|
||||
-- @param origin Origin card in the connection
|
||||
-- @param target Target card object to connect
|
||||
-- @param lines List of vector line elements. Mutable, will be updated to add this connector
|
||||
function addOneWayVector(origin, target, lines)
|
||||
-- Start with the BiDi then add the arrow lines to it
|
||||
addBidirectionalVector(origin, target, lines)
|
||||
local originPos = origin.getPosition()
|
||||
local targetPos = target.getPosition()
|
||||
originPos.y = CONNECTION_LINE_Y
|
||||
targetPos.y = CONNECTION_LINE_Y
|
||||
|
||||
-- Calculate card distance to be closer for horizontal positions than vertical, since cards are
|
||||
-- taller than they are wide
|
||||
local heading = Vector(originPos):sub(targetPos):heading("y")
|
||||
local distanceFromCard = DIRECTIONAL_ARROW_DISTANCE * 0.7 + DIRECTIONAL_ARROW_DISTANCE * 0.3 * math.abs(math.sin(math.rad(heading)))
|
||||
|
||||
-- Calculate the three possible arrow positions. These are offset by half the arrow length to
|
||||
-- make them visually balanced by keeping the arrows centered, not tracking the point
|
||||
local midpoint = Vector(originPos):add(targetPos):scale(Vector(0.5, 0.5, 0.5)):moveTowards(targetPos, ARROW_ARM_LENGTH / 2)
|
||||
local closeToOrigin = Vector(originPos):moveTowards(targetPos, distanceFromCard + ARROW_ARM_LENGTH / 2)
|
||||
local closeToTarget = Vector(targetPos):moveTowards(originPos, distanceFromCard - ARROW_ARM_LENGTH / 2)
|
||||
|
||||
if (originPos:distance(closeToOrigin) > originPos:distance(closeToTarget)) then
|
||||
addArrowLines(midpoint, originPos, lines)
|
||||
else
|
||||
addArrowLines(closeToOrigin, originPos, lines)
|
||||
addArrowLines(closeToTarget, originPos, lines)
|
||||
end
|
||||
end
|
||||
|
||||
-- Draws an arrowhead at the given position.
|
||||
-- @param arrowheadPosition Centerpoint of the arrowhead to draw (NOT the tip of the arrow)
|
||||
-- @param originPos Origin point of the connection, used to position the arrow arms
|
||||
-- @param lines List of vector line elements. Mutable, will be updated to add this arrow
|
||||
function addArrowLines(arrowheadPos, originPos, 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)
|
||||
|
||||
local head = self.positionToLocal(arrowheadPos)
|
||||
local arm1 = self.positionToLocal(arrowArm1)
|
||||
local arm2 = self.positionToLocal(arrowArm2)
|
||||
table.insert(lines, {
|
||||
points = { arm1, head, arm2},
|
||||
color = CONNECTION_COLOR,
|
||||
thickness = CONNECTION_THICKNESS
|
||||
})
|
||||
end
|
||||
|
||||
-- Move all contents on the play area (cards, tokens, etc) one slot in the given direction. Certain
|
||||
-- fixed objects will be ignored, as will anything the player has tagged with
|
||||
-- 'displacement_excluded'
|
||||
@ -123,6 +414,20 @@ function getInvestigatorCount()
|
||||
return investigatorCounter.getVar("val")
|
||||
end
|
||||
|
||||
-- Check to see if the given object is within the bounds of the play area, based solely on the X and
|
||||
-- Z coordinates, ignoring height
|
||||
-- @param object Object to check
|
||||
-- @return True if the object is inside the play area
|
||||
function isInPlayArea(object)
|
||||
local bounds = self.getBounds()
|
||||
local position = object.getPosition()
|
||||
-- Corners are arbitrary since it's all global - c1 goes down both axes, c2 goes up
|
||||
local c1 = { x = bounds.center.x - bounds.size.x / 2, z = bounds.center.z - bounds.size.z / 2}
|
||||
local c2 = { x = bounds.center.x + bounds.size.x / 2, z = bounds.center.z + bounds.size.z / 2}
|
||||
|
||||
return position.x > c1.x and position.x < c2.x and position.z > c1.z and position.z < c2.z
|
||||
end
|
||||
|
||||
-- Reset the play area's tracking of which cards have had tokens spawned.
|
||||
function resetSpawnedCards()
|
||||
spawnedLocationGUIDs = {}
|
||||
@ -130,4 +435,11 @@ end
|
||||
|
||||
function onScenarioChanged(scenarioName)
|
||||
currentScenario = scenarioName
|
||||
if not showLocationLinks() then
|
||||
broadcastToAll("Automatic location connections not available for this scenario")
|
||||
end
|
||||
end
|
||||
|
||||
function showLocationLinks()
|
||||
return not LOC_LINK_EXCLUDE_SCENARIOS[currentScenario]
|
||||
end
|
||||
|
@ -248,6 +248,8 @@ do
|
||||
else
|
||||
rot.y = 270
|
||||
end
|
||||
|
||||
tokenTemplate.Nickname = ""
|
||||
return spawnObjectData({
|
||||
data = tokenTemplate,
|
||||
position = position,
|
||||
|
@ -6,8 +6,8 @@ tourCardTemplate = {
|
||||
tag = "Panel",
|
||||
attributes = {
|
||||
id = "tourCard",
|
||||
height = 195,
|
||||
width = 300,
|
||||
height = 215,
|
||||
width = 330,
|
||||
rotation = "0 0 0",
|
||||
position = "0 300 30",
|
||||
showAnimation = "FadeIn",
|
||||
@ -19,10 +19,10 @@ tourCardTemplate = {
|
||||
tag = "Image",
|
||||
attributes = {
|
||||
id = "tourNarratorImageLeft",
|
||||
height=75,
|
||||
width=50,
|
||||
height=120,
|
||||
width=80,
|
||||
rectAlignment="UpperLeft",
|
||||
offsetXY = "-50 0",
|
||||
offsetXY = "-80 0",
|
||||
-- Image will be set when the card is updated
|
||||
}
|
||||
},
|
||||
@ -31,10 +31,10 @@ tourCardTemplate = {
|
||||
attributes = {
|
||||
id = "tourNarratorImageRight",
|
||||
active = false,
|
||||
height=75,
|
||||
width=50,
|
||||
height=125,
|
||||
width=80,
|
||||
rectAlignment="UpperRight",
|
||||
offsetXY = "50 0"
|
||||
offsetXY = "80 0"
|
||||
-- Image will be set when the card is updated
|
||||
}
|
||||
},
|
||||
@ -43,8 +43,8 @@ tourCardTemplate = {
|
||||
attributes = {
|
||||
id = "tourSpeechBubble",
|
||||
color = "#F5F5DC",
|
||||
height = 195,
|
||||
width = 300,
|
||||
height = 215,
|
||||
width = 330,
|
||||
rectAlignment = "MiddleCenter",
|
||||
image = "SpeechBubble",
|
||||
},
|
||||
@ -53,35 +53,37 @@ tourCardTemplate = {
|
||||
tag = "Text",
|
||||
attributes = {
|
||||
id = "tourText",
|
||||
height = 165,
|
||||
width = 230,
|
||||
-- Everything on this is double-sized and scaled down to keep the text sharps
|
||||
height = 370,
|
||||
width = 520,
|
||||
scale = "0.5 0.5 1",
|
||||
rectAlignment = "UpperCenter",
|
||||
offsetXY = "15 -15",
|
||||
resizeTextForBestFit = true,
|
||||
resizeTextMinSize = 10,
|
||||
resizeTextMaxSize = 16,
|
||||
resizeTextMinSize = 20,
|
||||
resizeTextMaxSize = 32,
|
||||
color = "#050505",
|
||||
alignment = "UpperLeft",
|
||||
horizontalOverflow = "wrap",
|
||||
}
|
||||
},
|
||||
{
|
||||
tag = "Button",
|
||||
tag = "Image",
|
||||
attributes = {
|
||||
id = "tourNext",
|
||||
height = 40,
|
||||
width = 40,
|
||||
height = 45,
|
||||
width = 45,
|
||||
rectAlignment = "LowerRight",
|
||||
offsetXY = "-5 -45",
|
||||
image = "NextArrow"
|
||||
},
|
||||
},
|
||||
{
|
||||
tag = "Button",
|
||||
tag = "Image",
|
||||
attributes = {
|
||||
id = "tourStop",
|
||||
height = 40,
|
||||
width = 40,
|
||||
height = 45,
|
||||
width = 45,
|
||||
rectAlignment = "LowerLeft",
|
||||
offsetXY = "35 -45",
|
||||
image = "Exit"
|
||||
|
@ -36,10 +36,14 @@ do
|
||||
east = "600 0 0",
|
||||
west = "-600 0 0",
|
||||
south = "0 -300 0",
|
||||
northwest = "-600 300 0",
|
||||
-- Northwest is only used by the Mandy card, move it a little right than standard so it's
|
||||
-- closer to the importer
|
||||
northwest = "-500 300 0",
|
||||
northeast = "600 300 0",
|
||||
southwest = "-600 -300 0",
|
||||
southeast = "600 -300 0"
|
||||
-- Used by the Diana and Wini cards referencing the bottom-right global controls, moved a little
|
||||
-- closer to them
|
||||
southeast = "730 -365 0"
|
||||
}
|
||||
|
||||
-- Tracks the current state of the tours. Keyed by player color to keep each player's tour
|
||||
@ -264,7 +268,6 @@ do
|
||||
---@param playerColor String. String color of the player to make this visible for
|
||||
internal.setDeepVisibility = function(xmlUi, playerColor)
|
||||
xmlUi.attributes.visibility = "" .. playerColor
|
||||
log(xmlUi.attributes.id)
|
||||
if xmlUi.children ~= nil then
|
||||
for _, child in ipairs(xmlUi.children) do
|
||||
internal.setDeepVisibility(child, playerColor)
|
||||
|
@ -8,7 +8,7 @@ TOUR_SCRIPT = {
|
||||
},
|
||||
{
|
||||
narrator = "Darrell",
|
||||
text = "Cameras can be tricky things. Best you leave handling it to the professionals during the tour. Don't try to move the camera until the tour is complete.\n\nOnce we're done, remmeber you can use the 'p' key to switch back to third-person mode, and the spacebar to reset the position.",
|
||||
text = "Cameras can be tricky things. Best you leave handling it to the professionals during the tour. Don't try to move the camera until the tour is complete.\n\nOnce we're done, remember you can use the 'p' key to switch back to third-person mode, and the spacebar to reset the position.",
|
||||
position = "center",
|
||||
speakerSide = "right",
|
||||
},
|
||||
@ -25,7 +25,7 @@ TOUR_SCRIPT = {
|
||||
text = "To survive what's coming you'll need a deck. If it's safely hidden away on ArkhamDB you can load it here, and even find the newest version after an upgrade without changing the ID.\n\nNo need to publish all your decks, use 'Private' and you can see it. Just make sure to select 'Make your decks public' in ArkhamDB.",
|
||||
showObj = "a28140",
|
||||
distanceFromObj = -10,
|
||||
position = "west",
|
||||
position = "northwest",
|
||||
},
|
||||
{
|
||||
narrator = "Daniela",
|
||||
@ -83,7 +83,7 @@ TOUR_SCRIPT = {
|
||||
},
|
||||
{
|
||||
narrator = "Preston",
|
||||
text = "I can afford to buy what I need, but for those less well-off we've provided an endless pool of tokens to track your game. Simply drag one out of the pools here.\n\nResources are my favorite, of course, but damage and horror are as inevitable as taxes, though I leave those to my bookkeeper. Those tokens can work like counters, use the number keys to change the value.",
|
||||
text = "I can afford to buy what I need, but for those less well-off we've provided an endless pool of tokens to track your game. Simply drag one out of the pools here.\n\nResources are my favorite of course, but damage and horror are as inevitable as taxes. I leave those to my bookkeeper though. Those tokens can work like counters, use the number keys to change the value.",
|
||||
showObj = "9fadf9",
|
||||
position = "north",
|
||||
skipCentering = true,
|
||||
|
@ -26,7 +26,6 @@ function onLoad()
|
||||
end
|
||||
|
||||
function startTour(_, playerColor, _)
|
||||
broadcastToColor("Starting the tour, please wait", playerColor)
|
||||
tourManager.startTour(playerColor)
|
||||
end
|
||||
|
||||
|
@ -7,6 +7,8 @@ local WEAKNESS_CHECK_Z = 37
|
||||
local cardIdIndex = { }
|
||||
local classAndLevelIndex = { }
|
||||
local basicWeaknessList = { }
|
||||
local uniqueWeaknessList = { }
|
||||
local cycleIndex = { }
|
||||
|
||||
local indexingDone = false
|
||||
local allowRemoval = false
|
||||
@ -45,7 +47,9 @@ function clearIndexes()
|
||||
classAndLevelIndex["Survivor-level0"] = { }
|
||||
classAndLevelIndex["Rogue-level0"] = { }
|
||||
classAndLevelIndex["Neutral-level0"] = { }
|
||||
cycleIndex = { }
|
||||
basicWeaknessList = { }
|
||||
uniqueWeaknessList = { }
|
||||
end
|
||||
|
||||
-- Clears the bag indexes and starts the coroutine to rebuild the indexes
|
||||
@ -121,27 +125,27 @@ function buildSupplementalIndexes()
|
||||
local cardMetadata = card.metadata
|
||||
-- If the ID key and the metadata ID don't match this is a duplicate card created by an
|
||||
-- alternate_id, and we should skip it
|
||||
if (cardId == cardMetadata.id) then
|
||||
if cardId == cardMetadata.id then
|
||||
-- Add card to the basic weakness list, if appropriate. Some weaknesses have
|
||||
-- multiple copies, and are added multiple times
|
||||
if (cardMetadata.weakness and cardMetadata.basicWeaknessCount ~= nil) then
|
||||
if cardMetadata.weakness and cardMetadata.basicWeaknessCount ~= nil then
|
||||
table.insert(uniqueWeaknessList, cardMetadata.id)
|
||||
for i = 1, cardMetadata.basicWeaknessCount do
|
||||
table.insert(basicWeaknessList, cardMetadata.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
table.sort(basicWeaknessList, cardComparator)
|
||||
|
||||
-- Add the card to the appropriate class and level indexes
|
||||
local isGuardian = false
|
||||
local isSeeker = false
|
||||
local isMystic = false
|
||||
local isRogue = false
|
||||
local isSurvivor = false
|
||||
local isNeutral = false
|
||||
local upgradeKey
|
||||
-- Excludes signature cards (which have no class or level) and alternate
|
||||
-- ID entries
|
||||
if (cardMetadata.class ~= nil and cardMetadata.level ~= nil) then
|
||||
-- Add the card to the appropriate class and level indexes
|
||||
local isGuardian = false
|
||||
local isSeeker = false
|
||||
local isMystic = false
|
||||
local isRogue = false
|
||||
local isSurvivor = false
|
||||
local isNeutral = false
|
||||
local upgradeKey
|
||||
-- Excludes signature cards (which have no class or level) and alternate
|
||||
-- ID entries
|
||||
if (cardMetadata.class ~= nil and cardMetadata.level ~= nil) then
|
||||
isGuardian = string.match(cardMetadata.class, "Guardian")
|
||||
isSeeker = string.match(cardMetadata.class, "Seeker")
|
||||
isMystic = string.match(cardMetadata.class, "Mystic")
|
||||
@ -171,12 +175,32 @@ function buildSupplementalIndexes()
|
||||
if (isNeutral) then
|
||||
table.insert(classAndLevelIndex["Neutral"..upgradeKey], cardMetadata.id)
|
||||
end
|
||||
|
||||
local cycleName = cardMetadata.cycle
|
||||
if cycleName ~= nil then
|
||||
cycleName = string.lower(cycleName)
|
||||
if string.match(cycleName, "return") then
|
||||
cycleName = string.sub(cycleName, 11)
|
||||
end
|
||||
if cycleName == "the night of the zealot" then
|
||||
cycleName = "core"
|
||||
end
|
||||
if cycleIndex[cycleName] == nil then
|
||||
cycleIndex[cycleName] = { }
|
||||
end
|
||||
table.insert(cycleIndex[cycleName], cardMetadata.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
for _, indexTable in pairs(classAndLevelIndex) do
|
||||
table.sort(indexTable, cardComparator)
|
||||
end
|
||||
for _, indexTable in pairs(cycleIndex) do
|
||||
table.sort(indexTable)
|
||||
end
|
||||
table.sort(basicWeaknessList, cardComparator)
|
||||
table.sort(uniqueWeaknessList, cardComparator)
|
||||
end
|
||||
|
||||
-- Comparison function used to sort the class card bag indexes. Sorts by card
|
||||
@ -235,6 +259,14 @@ function getCardsByClassAndLevel(params)
|
||||
return classAndLevelIndex[params.class..upgradeKey];
|
||||
end
|
||||
|
||||
function getCardsByCycle(cycleName)
|
||||
if (not indexingDone) then
|
||||
broadcastToAll("Still loading player cards, please try again in a few seconds", {0.9, 0.2, 0.2})
|
||||
return { }
|
||||
end
|
||||
return cycleIndex[string.lower(cycleName)]
|
||||
end
|
||||
|
||||
-- Searches the bag for cards which match the given name and returns a list. Note that this is
|
||||
-- an O(n) search without index support. It may be slow.
|
||||
-- Parameter array must contain these fields to define the search:
|
||||
@ -303,6 +335,10 @@ function getBasicWeaknesses()
|
||||
return basicWeaknessList
|
||||
end
|
||||
|
||||
function getUniqueWeaknesses()
|
||||
return uniqueWeaknessList
|
||||
end
|
||||
|
||||
-- Helper function that adds one to the table entry for the number of weaknesses in play
|
||||
function incrementWeaknessCount(table, cardMetadata)
|
||||
if (isBasicWeakness(cardMetadata)) then
|
||||
@ -322,6 +358,7 @@ function isInPlayArea(object)
|
||||
return position.x < WEAKNESS_CHECK_X
|
||||
and position.z < WEAKNESS_CHECK_Z
|
||||
end
|
||||
|
||||
function isBasicWeakness(cardMetadata)
|
||||
return cardMetadata ~= nil
|
||||
and cardMetadata.weakness
|
||||
|
@ -2,24 +2,49 @@ require("playercards/PlayerCardPanelData")
|
||||
local spawnBag = require("playercards/spawnbag/SpawnBag")
|
||||
local arkhamDb = require("arkhamdb/ArkhamDb")
|
||||
|
||||
-- TODO: Update when the real UI image is in place
|
||||
local BUTTON_WIDTH = 150
|
||||
local BUTTON_HEIGHT = 550
|
||||
-- Size and position information for the three rows of class buttons
|
||||
local CIRCLE_BUTTON_SIZE = 250
|
||||
local CLASS_BUTTONS_X_OFFSET = 0.1325
|
||||
local INVESTIGATOR_ROW_START = Vector(0.125, 0.1, -0.447)
|
||||
local LEVEL_ZERO_ROW_START = Vector(0.125, 0.1, -0.007)
|
||||
local UPGRADED_ROW_START = Vector(0.125, 0.1, 0.333)
|
||||
|
||||
-- Size and position information for the two blocks of other buttons
|
||||
local MISC_BUTTONS_X_OFFSET = 0.155
|
||||
local WEAKNESS_ROW_START = Vector(0.157, 0.1, 0.666)
|
||||
local OTHER_ROW_START = Vector(0.605, 0.1, 0.666)
|
||||
|
||||
-- Size and position information for the Cycle (box) buttons
|
||||
local CYCLE_BUTTON_SIZE = 468
|
||||
local CYCLE_BUTTON_START = Vector(-0.716, 0.1, -0.39)
|
||||
local CYCLE_COLUMN_COUNT = 3
|
||||
local CYCLE_BUTTONS_X_OFFSET = 0.267
|
||||
local CYCLE_BUTTONS_Z_OFFSET = 0.2665
|
||||
|
||||
local ALL_CARDS_BAG_GUID = "15bb07"
|
||||
|
||||
local STARTER_DECK_MODE_SELECTED_COLOR = { 0.2, 0.2, 0.2, 0.8 }
|
||||
local TRANSPARENT = { 0, 0, 0, 0 }
|
||||
local STARTER_DECK_MODE_STARTERS = "starters"
|
||||
local STARTER_DECK_MODE_CARDS_ONLY = "cards"
|
||||
|
||||
local FACE_UP_ROTATION = { x = 0, y = 270, z = 0}
|
||||
local FACE_DOWN_ROTATION = { x = 0, y = 270, z = 180}
|
||||
|
||||
-- Coordinates to begin laying out cards to match the reserved areas of the
|
||||
-- table. Cards will lay out horizontally, then create additional rows
|
||||
-- Coordinates to begin laying out cards. These vary based on the cards that are being placed
|
||||
local START_POSITIONS = {
|
||||
skill = Vector(58.384, 1.36, 92.4),
|
||||
event = Vector(53.229, 1.36, 92.4),
|
||||
asset = Vector(40.960, 1.36, 92.4),
|
||||
investigator = Vector(60, 1.36, 80)
|
||||
classCards = Vector(58.384, 1.36, 92.4),
|
||||
investigator = Vector(60, 1.36, 86),
|
||||
cycle = Vector(48, 1.36, 92.4),
|
||||
other = Vector(56, 1.36, 86),
|
||||
summonedServitor = Vector(55.5, 1.36, 60.2),
|
||||
randomWeakness = Vector(55, 1.36, 75)
|
||||
}
|
||||
|
||||
-- Shifts to move rows of cards, and groups of rows, as different groupings are laid out
|
||||
local CARD_ROW_OFFSET = 3.7
|
||||
local CARD_GROUP_OFFSET = 2
|
||||
|
||||
-- Position offsets for investigator decks in investigator mode, defines the spacing for how the
|
||||
-- rows and columns are laid out
|
||||
local INVESTIGATOR_POSITION_SHIFT_ROW = Vector(-11, 0, 0)
|
||||
@ -31,7 +56,21 @@ local INVESTIGATOR_MAX_COLS = 6
|
||||
local INVESTIGATOR_CARD_OFFSET = Vector(-2.55, 0, 0)
|
||||
local INVESTIGATOR_SIGNATURE_OFFSET = Vector(-5.75, 0, 0)
|
||||
|
||||
local spawnStarterDecks = false
|
||||
local CLASS_LIST = { "Guardian", "Seeker", "Rogue", "Mystic", "Survivor", "Neutral" }
|
||||
local CYCLE_LIST = {
|
||||
"Core",
|
||||
"The Dunwich Legacy",
|
||||
"The Path to Carcosa",
|
||||
"The Forgotten Age",
|
||||
"The Circle Undone",
|
||||
"The Dream-Eaters",
|
||||
"The Innsmouth Conspiracy",
|
||||
"Edge of the Earth",
|
||||
"The Scarlet Keys",
|
||||
"Investigator Packs"
|
||||
}
|
||||
|
||||
local starterDeckMode = STARTER_DECK_MODE_CARDS_ONLY
|
||||
|
||||
function onSave()
|
||||
local saveState = {
|
||||
@ -48,232 +87,223 @@ function onLoad(savedData)
|
||||
spawnBag.loadFromSave(saveState.spawnBagState)
|
||||
end
|
||||
end
|
||||
createButtons()
|
||||
end
|
||||
|
||||
self.createButton({
|
||||
label="Guardian", click_function="spawnInvestigatorsGuardian", function_owner=self,
|
||||
position={-0.3,0.2,-0.5}, rotation={0,0,0}, height=BUTTON_WIDTH, width=BUTTON_HEIGHT,
|
||||
font_size=64, color={0,0,0}, font_color={1,1,1}, scale={0.25, 0.25, 0.25}
|
||||
})
|
||||
self.createButton({
|
||||
label="Seeker", click_function="spawnInvestigatorsSeeker", function_owner=self,
|
||||
position={0,0.2,-0.5}, rotation={0,0,0}, height=BUTTON_WIDTH, width=BUTTON_HEIGHT,
|
||||
font_size=64, color={0,0,0}, font_color={1,1,1}, scale={0.25, 0.25, 0.25}
|
||||
})
|
||||
self.createButton({
|
||||
label="Mystic", click_function="spawnInvestigatorsMystic", function_owner=self,
|
||||
position={0.3,0.2,-0.5}, rotation={0,0,0}, height=BUTTON_WIDTH, width=BUTTON_HEIGHT,
|
||||
font_size=64, color={0,0,0}, font_color={1,1,1}, scale={0.25, 0.25, 0.25}
|
||||
})
|
||||
self.createButton({
|
||||
label="Rogue", click_function="spawnInvestigatorsRogue", function_owner=self,
|
||||
position={-0.3,0.2,-0.4}, rotation={0,0,0}, height=BUTTON_WIDTH, width=BUTTON_HEIGHT,
|
||||
font_size=64, color={0,0,0}, font_color={1,1,1}, scale={0.25, 0.25, 0.25}
|
||||
})
|
||||
self.createButton({
|
||||
label="Survivor", click_function="spawnSurvivor", function_owner=self,
|
||||
position={0,0.2,-0.4}, rotation={0,0,0}, height=BUTTON_WIDTH, width=BUTTON_HEIGHT,
|
||||
font_size=64, color={0,0,0}, font_color={1,1,1}, scale={0.25, 0.25, 0.25}
|
||||
})
|
||||
self.createButton({
|
||||
label="Neutral", click_function="spawnNeutral", function_owner=self,
|
||||
position={0.3,0.2,-0.4}, rotation={0,0,0}, height=BUTTON_WIDTH, width=BUTTON_HEIGHT,
|
||||
font_size=64, color={0,0,0}, font_color={1,1,1}, scale={0.25, 0.25, 0.25}
|
||||
})
|
||||
function createButtons()
|
||||
createInvestigatorButtons()
|
||||
createLevelZeroButtons()
|
||||
createUpgradedButtons()
|
||||
createWeaknessButtons()
|
||||
createOtherButtons()
|
||||
createCycleButtons()
|
||||
createClearButton()
|
||||
-- Create investigator mode buttons last so the indexes are set when we need to update them
|
||||
createInvestigatorModeButtons()
|
||||
end
|
||||
|
||||
self.createButton({
|
||||
label="Core", click_function="spawnCore", function_owner=self,
|
||||
position={-0.3,0.2,-0.2}, rotation={0,0,0}, height=BUTTON_WIDTH, width=BUTTON_HEIGHT,
|
||||
font_size=64, color={0,0,0}, font_color={1,1,1}, scale={0.25, 0.25, 0.25}
|
||||
})
|
||||
self.createButton({
|
||||
label="Dunwich", click_function="spawnDunwich", function_owner=self,
|
||||
position={0,0.2,-0.2}, rotation={0,0,0}, height=BUTTON_WIDTH, width=BUTTON_HEIGHT,
|
||||
font_size=64, color={0,0,0}, font_color={1,1,1}, scale={0.25, 0.25, 0.25}
|
||||
})
|
||||
self.createButton({
|
||||
label="Carcosa", click_function="spawnCarcosa", function_owner=self,
|
||||
position={0.3,0.2,-0.2}, rotation={0,0,0}, height=BUTTON_WIDTH, width=BUTTON_HEIGHT,
|
||||
font_size=64, color={0,0,0}, font_color={1,1,1}, scale={0.25, 0.25, 0.25}
|
||||
})
|
||||
self.createButton({
|
||||
label="Forgotten Age", click_function="spawnForgottenAge", function_owner=self,
|
||||
position={-0.3,0.2,-0.1}, rotation={0,0,0}, height=BUTTON_WIDTH, width=BUTTON_HEIGHT,
|
||||
font_size=64, color={0,0,0}, font_color={1,1,1}, scale={0.25, 0.25, 0.25}
|
||||
})
|
||||
self.createButton({
|
||||
label="Circle Undone", click_function="spawnCircleUndone", function_owner=self,
|
||||
position={0,0.2,-0.1}, rotation={0,0,0}, height=BUTTON_WIDTH, width=BUTTON_HEIGHT,
|
||||
font_size=64, color={0,0,0}, font_color={1,1,1}, scale={0.25, 0.25, 0.25}
|
||||
})
|
||||
self.createButton({
|
||||
label="Dream Eaters", click_function="spawnDreamEaters", function_owner=self,
|
||||
position={0.3,0.2,-0.1}, rotation={0,0,0}, height=BUTTON_WIDTH, width=BUTTON_HEIGHT,
|
||||
font_size=64, color={0,0,0}, font_color={1,1,1}, scale={0.25, 0.25, 0.25}
|
||||
})
|
||||
self.createButton({
|
||||
label="Innsmouth", click_function="spawnInnsmouth", function_owner=self,
|
||||
position={-0.3,0.2,0}, rotation={0,0,0}, height=BUTTON_WIDTH, width=BUTTON_HEIGHT,
|
||||
font_size=64, color={0,0,0}, font_color={1,1,1}, scale={0.25, 0.25, 0.25}
|
||||
})
|
||||
self.createButton({
|
||||
label="EotE", click_function="spawnEotE", function_owner=self,
|
||||
position={0,0.2,0}, rotation={0,0,0}, height=BUTTON_WIDTH, width=BUTTON_HEIGHT,
|
||||
font_size=64, color={0,0,0}, font_color={1,1,1}, scale={0.25, 0.25, 0.25}
|
||||
})
|
||||
self.createButton({
|
||||
label="Scarlet Keys", click_function="spawnScarletKeys", function_owner=self,
|
||||
position={0.3,0.2,0}, rotation={0,0,0}, height=BUTTON_WIDTH, width=BUTTON_HEIGHT,
|
||||
font_size=64, color={0,0,0}, font_color={1,1,1}, scale={0.25, 0.25, 0.25}
|
||||
})
|
||||
self.createButton({
|
||||
label="InvPacks", click_function="spawnInvestigatorDecks", function_owner=self,
|
||||
position={-0.3,0.2,0.1}, rotation={0,0,0}, height=BUTTON_WIDTH, width=BUTTON_HEIGHT,
|
||||
font_size=64, color={0,0,0}, font_color={1,1,1}, scale={0.25, 0.25, 0.25}
|
||||
})
|
||||
self.createButton({
|
||||
label="Investigators", click_function="setInvestigators", function_owner=self,
|
||||
position={-0.15,0.2,-0.6}, rotation={0,0,0}, height=BUTTON_WIDTH, width=BUTTON_HEIGHT,
|
||||
font_size=64, color={0,0,0}, font_color={1,1,1}, scale={0.25, 0.25, 0.25}
|
||||
})
|
||||
self.createButton({
|
||||
label="Starters", click_function="setStarters", function_owner=self,
|
||||
position={0.15,0.2,-0.6}, rotation={0,0,0}, height=BUTTON_WIDTH, width=BUTTON_HEIGHT,
|
||||
font_size=64, color={0,0,0}, font_color={1,1,1}, scale={0.25, 0.25, 0.25}
|
||||
})
|
||||
|
||||
self.createButton({
|
||||
label="L0 Guardian", click_function="spawnBasicGuardian", function_owner=self,
|
||||
position={-0.15,0.2,0.3}, rotation={0,0,0}, height=BUTTON_WIDTH, width=BUTTON_HEIGHT,
|
||||
font_size=64, color={0,0,0}, font_color={1,1,1}, scale={0.25, 0.25, 0.25}
|
||||
})
|
||||
self.createButton({
|
||||
label="L1-5 Guardian", click_function="spawnUpgradedGuardian", function_owner=self,
|
||||
position={0.15,0.2,0.3}, rotation={0,0,0}, height=BUTTON_WIDTH, width=BUTTON_HEIGHT,
|
||||
font_size=64, color={0,0,0}, font_color={1,1,1}, scale={0.25, 0.25, 0.25}
|
||||
})
|
||||
self.createButton({
|
||||
label="L0 Seeker", click_function="spawnBasicSeeker", function_owner=self,
|
||||
position={-0.15,0.2,0.4}, rotation={0,0,0}, height=BUTTON_WIDTH, width=BUTTON_HEIGHT,
|
||||
font_size=64, color={0,0,0}, font_color={1,1,1}, scale={0.25, 0.25, 0.25}
|
||||
})
|
||||
self.createButton({
|
||||
label="L1-5 Seeker", click_function="spawnUpgradedSeeker", function_owner=self,
|
||||
position={0.15,0.2,0.4}, rotation={0,0,0}, height=BUTTON_WIDTH, width=BUTTON_HEIGHT,
|
||||
font_size=64, color={0,0,0}, font_color={1,1,1}, scale={0.25, 0.25, 0.25}
|
||||
})
|
||||
self.createButton({
|
||||
label="L0 Mystic", click_function="spawnBasicMystic", function_owner=self,
|
||||
position={-0.15,0.2,0.5}, rotation={0,0,0}, height=BUTTON_WIDTH, width=BUTTON_HEIGHT,
|
||||
font_size=64, color={0,0,0}, font_color={1,1,1}, scale={0.25, 0.25, 0.25}
|
||||
})
|
||||
self.createButton({
|
||||
label="L1-5 Mystic", click_function="spawnUpgradedGuardian", function_owner=self,
|
||||
position={0.15,0.2,0.5}, rotation={0,0,0}, height=BUTTON_WIDTH, width=BUTTON_HEIGHT,
|
||||
font_size=64, color={0,0,0}, font_color={1,1,1}, scale={0.25, 0.25, 0.25}
|
||||
})
|
||||
self.createButton({
|
||||
label="L0 Rogue", click_function="spawnBasicRogue", function_owner=self,
|
||||
position={-0.15,0.2,0.6}, rotation={0,0,0}, height=BUTTON_WIDTH, width=BUTTON_HEIGHT,
|
||||
font_size=64, color={0,0,0}, font_color={1,1,1}, scale={0.25, 0.25, 0.25}
|
||||
})
|
||||
self.createButton({
|
||||
label="L1-5 Rogue", click_function="spawnUpgradedRogue", function_owner=self,
|
||||
position={0.15,0.2,0.6}, rotation={0,0,0}, height=BUTTON_WIDTH, width=BUTTON_HEIGHT,
|
||||
font_size=64, color={0,0,0}, font_color={1,1,1}, scale={0.25, 0.25, 0.25}
|
||||
})
|
||||
self.createButton({
|
||||
label="L0 Survivor", click_function="spawnBasicSurvivor", function_owner=self,
|
||||
position={-0.15,0.2,0.7}, rotation={0,0,0}, height=BUTTON_WIDTH, width=BUTTON_HEIGHT,
|
||||
font_size=64, color={0,0,0}, font_color={1,1,1}, scale={0.25, 0.25, 0.25}
|
||||
})
|
||||
self.createButton({
|
||||
label="L1-5 Survivor", click_function="spawnUpgradedSurvivor", function_owner=self,
|
||||
position={0.15,0.2,0.7}, rotation={0,0,0}, height=BUTTON_WIDTH, width=BUTTON_HEIGHT,
|
||||
font_size=64, color={0,0,0}, font_color={1,1,1}, scale={0.25, 0.25, 0.25}
|
||||
})
|
||||
self.createButton({
|
||||
label="L0 Neutral", click_function="spawnBasicNeutral", function_owner=self,
|
||||
position={-0.15,0.2,0.8}, rotation={0,0,0}, height=BUTTON_WIDTH, width=BUTTON_HEIGHT,
|
||||
font_size=64, color={0,0,0}, font_color={1,1,1}, scale={0.25, 0.25, 0.25}
|
||||
})
|
||||
self.createButton({
|
||||
label="L1-5 Neutral", click_function="spawnUpgradedNeutral", function_owner=self,
|
||||
position={0.15,0.2,0.8}, rotation={0,0,0}, height=BUTTON_WIDTH, width=BUTTON_HEIGHT,
|
||||
font_size=64, color={0,0,0}, font_color={1,1,1}, scale={0.25, 0.25, 0.25}
|
||||
})
|
||||
self.createButton({
|
||||
label="Clear", click_function="deleteAll", function_owner=self,
|
||||
position={0.5,0.2,0.9}, rotation={0,0,0}, height=BUTTON_WIDTH, width=BUTTON_HEIGHT,
|
||||
font_size=64, color={0,0,0}, font_color={1,1,1}, scale={0.25, 0.25, 0.25}
|
||||
})
|
||||
self.createButton({
|
||||
label="Weaknesses", click_function="spawnWeaknesses", function_owner=self,
|
||||
position={-0.5,0.2,0.9}, rotation={0,0,0}, height=BUTTON_WIDTH, width=BUTTON_HEIGHT,
|
||||
font_size=64, color={0,0,0}, font_color={1,1,1}, scale={0.25, 0.25, 0.25}
|
||||
})
|
||||
local classList = { "Guardian", "Seeker", "Mystic", "Rogue", "Survivor", "Neutral" }
|
||||
for _, className in ipairs(classList) do
|
||||
local funcName = "spawnInvestigators"..className
|
||||
self.setVar(funcName, function(_, _, _) spawnGroup(className) end)
|
||||
funcName = "spawnBasic"..className
|
||||
self.setVar(funcName, function(_, _, _) spawnClassCards(className, false) end)
|
||||
funcName = "spawnUpgraded"..className
|
||||
self.setVar(funcName, function(_, _, _) spawnClassCards(className, true) end)
|
||||
function createInvestigatorButtons()
|
||||
local invButtonParams = {
|
||||
function_owner = self,
|
||||
rotation = Vector(0, 0, 0),
|
||||
height = CIRCLE_BUTTON_SIZE,
|
||||
width = CIRCLE_BUTTON_SIZE,
|
||||
scale = Vector(0.25, 1, 0.25),
|
||||
color = TRANSPARENT,
|
||||
}
|
||||
local buttonPos = INVESTIGATOR_ROW_START:copy()
|
||||
for _, class in ipairs(CLASS_LIST) do
|
||||
invButtonParams.click_function = "spawnInvestigators" .. class
|
||||
invButtonParams.position = buttonPos
|
||||
self.createButton(invButtonParams)
|
||||
buttonPos.x = buttonPos.x + CLASS_BUTTONS_X_OFFSET
|
||||
self.setVar(invButtonParams.click_function, function(_, _, _) spawnInvestigatorGroup(class) end)
|
||||
end
|
||||
end
|
||||
|
||||
-- TODO: Replace these with something less manual once the full data in in place so we know what
|
||||
-- keys to use
|
||||
function placeCore()
|
||||
spawnGroup("Core")
|
||||
function createLevelZeroButtons()
|
||||
local l0ButtonParams = {
|
||||
function_owner = self,
|
||||
rotation = Vector(0, 0, 0),
|
||||
height = CIRCLE_BUTTON_SIZE,
|
||||
width = CIRCLE_BUTTON_SIZE,
|
||||
scale = Vector(0.25, 1, 0.25),
|
||||
color = TRANSPARENT,
|
||||
}
|
||||
local buttonPos = LEVEL_ZERO_ROW_START:copy()
|
||||
for _, class in ipairs(CLASS_LIST) do
|
||||
l0ButtonParams.click_function = "spawnBasic" .. class
|
||||
l0ButtonParams.position = buttonPos
|
||||
self.createButton(l0ButtonParams)
|
||||
buttonPos.x = buttonPos.x + CLASS_BUTTONS_X_OFFSET
|
||||
self.setVar(l0ButtonParams.click_function, function(_, _, _) spawnClassCards(class, false) end)
|
||||
end
|
||||
end
|
||||
|
||||
function placeDunwich()
|
||||
spawnGroup("Dunwich")
|
||||
function createUpgradedButtons()
|
||||
local upgradedButtonParams = {
|
||||
function_owner = self,
|
||||
rotation = Vector(0, 0, 0),
|
||||
height = CIRCLE_BUTTON_SIZE,
|
||||
width = CIRCLE_BUTTON_SIZE,
|
||||
scale = Vector(0.25, 1, 0.25),
|
||||
color = TRANSPARENT,
|
||||
}
|
||||
local buttonPos = UPGRADED_ROW_START:copy()
|
||||
for _, class in ipairs(CLASS_LIST) do
|
||||
upgradedButtonParams.click_function = "spawnUpgraded" .. class
|
||||
upgradedButtonParams.position = buttonPos
|
||||
self.createButton(upgradedButtonParams)
|
||||
buttonPos.x = buttonPos.x + CLASS_BUTTONS_X_OFFSET
|
||||
self.setVar(upgradedButtonParams.click_function, function(_, _, _) spawnClassCards(class, true) end)
|
||||
end
|
||||
end
|
||||
|
||||
function placeCarcosa()
|
||||
spawnGroup("Carcosa")
|
||||
function createWeaknessButtons()
|
||||
local weaknessButtonParams = {
|
||||
function_owner = self,
|
||||
rotation = Vector(0, 0, 0),
|
||||
height = CIRCLE_BUTTON_SIZE,
|
||||
width = CIRCLE_BUTTON_SIZE,
|
||||
scale = Vector(0.25, 1, 0.25),
|
||||
color = TRANSPARENT,
|
||||
}
|
||||
local buttonPos = WEAKNESS_ROW_START:copy()
|
||||
weaknessButtonParams.click_function = "spawnWeaknesses"
|
||||
weaknessButtonParams.tooltip = "Basic Weaknesses"
|
||||
weaknessButtonParams.position = buttonPos
|
||||
self.createButton(weaknessButtonParams)
|
||||
buttonPos.x = buttonPos.x + MISC_BUTTONS_X_OFFSET
|
||||
weaknessButtonParams.click_function = "spawnRandomWeakness"
|
||||
weaknessButtonParams.tooltip = "Random Weakness"
|
||||
weaknessButtonParams.position = buttonPos
|
||||
self.createButton(weaknessButtonParams)
|
||||
end
|
||||
|
||||
function placeForgottenAge()
|
||||
spawnGroup("ForgottenAge")
|
||||
function createOtherButtons()
|
||||
local otherButtonParams = {
|
||||
function_owner = self,
|
||||
rotation = Vector(0, 0, 0),
|
||||
height = CIRCLE_BUTTON_SIZE,
|
||||
width = CIRCLE_BUTTON_SIZE,
|
||||
scale = Vector(0.25, 1, 0.25),
|
||||
color = TRANSPARENT,
|
||||
}
|
||||
local buttonPos = OTHER_ROW_START:copy()
|
||||
otherButtonParams.click_function = "spawnBonded"
|
||||
otherButtonParams.tooltip = "Bonded Cards"
|
||||
otherButtonParams.position = buttonPos
|
||||
self.createButton(otherButtonParams)
|
||||
buttonPos.x = buttonPos.x + MISC_BUTTONS_X_OFFSET
|
||||
otherButtonParams.click_function = "spawnUpgradeSheets"
|
||||
otherButtonParams.tooltip = "Customization Upgrade Sheets"
|
||||
otherButtonParams.position = buttonPos
|
||||
self.createButton(otherButtonParams)
|
||||
end
|
||||
|
||||
function placeCircleUndone()
|
||||
spawnGroup("CircleUndone")
|
||||
function createCycleButtons()
|
||||
local cycleButtonParams = {
|
||||
function_owner = self,
|
||||
rotation = Vector(0, 0, 0),
|
||||
height = CYCLE_BUTTON_SIZE,
|
||||
width = CYCLE_BUTTON_SIZE,
|
||||
scale = Vector(0.25, 1, 0.25),
|
||||
color = TRANSPARENT,
|
||||
}
|
||||
local buttonPos = CYCLE_BUTTON_START:copy()
|
||||
local rowCount = 0
|
||||
local colCount = 0
|
||||
for _, cycle in ipairs(CYCLE_LIST) do
|
||||
cycleButtonParams.click_function = "spawnCycle" .. cycle
|
||||
cycleButtonParams.position = buttonPos
|
||||
cycleButtonParams.tooltip = cycle
|
||||
self.createButton(cycleButtonParams)
|
||||
self.setVar(cycleButtonParams.click_function, function(_, _, _) spawnCycle(cycle) end)
|
||||
colCount = colCount + 1
|
||||
-- If we've reached the end of a row, shift down and back to the first column
|
||||
if colCount >= CYCLE_COLUMN_COUNT then
|
||||
buttonPos = CYCLE_BUTTON_START:copy()
|
||||
rowCount = rowCount + 1
|
||||
colCount = 0
|
||||
buttonPos.z = buttonPos.z + CYCLE_BUTTONS_Z_OFFSET * rowCount
|
||||
if rowCount == 3 then
|
||||
-- Account for centered button on the final row
|
||||
buttonPos.x = buttonPos.x + CYCLE_BUTTONS_X_OFFSET
|
||||
end
|
||||
else
|
||||
buttonPos.x = buttonPos.x + CYCLE_BUTTONS_X_OFFSET
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function placeDreamEaters()
|
||||
spawnGroup("DreamEaters")
|
||||
function createClearButton()
|
||||
self.createButton({
|
||||
function_owner = self,
|
||||
click_function = "deleteAll",
|
||||
position = Vector(0, 0.1, 0.852),
|
||||
rotation = Vector(0, 0, 0),
|
||||
height = 170,
|
||||
width = 750,
|
||||
scale = Vector(0.25, 1, 0.25),
|
||||
color = TRANSPARENT,
|
||||
})
|
||||
end
|
||||
|
||||
function placeInnsmouth()
|
||||
spawnGroup("Innsmouth")
|
||||
function createInvestigatorModeButtons()
|
||||
local starterMode = starterDeckMode == STARTER_DECK_MODE_STARTERS
|
||||
|
||||
self.createButton({
|
||||
function_owner = self,
|
||||
click_function = "setCardsOnlyMode",
|
||||
position = Vector(0.251, 0.1, -0.322),
|
||||
rotation = Vector(0, 0, 0),
|
||||
height = 170,
|
||||
width = 760,
|
||||
scale = Vector(0.25, 1, 0.25),
|
||||
color = starterMode and TRANSPARENT or STARTER_DECK_MODE_SELECTED_COLOR
|
||||
})
|
||||
self.createButton({
|
||||
function_owner = self,
|
||||
click_function = "setStarterDeckMode",
|
||||
position = Vector(0.66, 0.1, -0.322),
|
||||
rotation = Vector(0, 0, 0),
|
||||
height = 170,
|
||||
width = 760,
|
||||
scale = Vector(0.25, 1, 0.25),
|
||||
color = starterMode and STARTER_DECK_MODE_SELECTED_COLOR or TRANSPARENT
|
||||
})
|
||||
local checkX = starterMode and 0.52 or 0.11
|
||||
self.createButton({
|
||||
function_owner = self,
|
||||
label = "✓",
|
||||
click_function = "doNothing",
|
||||
position = Vector(checkX, 0.11, -0.317),
|
||||
rotation = Vector(0, 0, 0),
|
||||
height = 0,
|
||||
width = 0,
|
||||
scale = Vector(0.3, 1, 0.3),
|
||||
font_color = { 0, 0, 0 },
|
||||
color = { 1, 1, 1 }
|
||||
})
|
||||
end
|
||||
|
||||
function placeEotE()
|
||||
spawnGroup("EotE")
|
||||
function setStarterDeckMode()
|
||||
starterDeckMode = STARTER_DECK_MODE_STARTERS
|
||||
updateStarterModeButtons()
|
||||
end
|
||||
|
||||
function placeScarletKeys()
|
||||
spawnGroup("ScarletKeys")
|
||||
function setCardsOnlyMode()
|
||||
starterDeckMode = STARTER_DECK_MODE_CARDS_ONLY
|
||||
updateStarterModeButtons()
|
||||
end
|
||||
|
||||
function placeInvestigatorDecks()
|
||||
spawnGroup("InvestigatorDecks")
|
||||
end
|
||||
|
||||
-- UI handler to put the investigator spawn in investigator mode.
|
||||
function setInvestigators()
|
||||
spawnStarterDecks = false
|
||||
printToAll("Spawning investigator piles")
|
||||
end
|
||||
|
||||
-- UI handler to put the investigator spawn in starter deck mode.
|
||||
function setStarters()
|
||||
spawnStarterDecks = true
|
||||
printToAll("Spawning starter decks")
|
||||
function updateStarterModeButtons()
|
||||
local buttonCount = #self.getButtons()
|
||||
-- Buttons are 0-indexed, so the last three are -1, -2, and -3 from the size
|
||||
self.removeButton(buttonCount - 1)
|
||||
self.removeButton(buttonCount - 2)
|
||||
self.removeButton(buttonCount - 3)
|
||||
createInvestigatorModeButtons()
|
||||
end
|
||||
|
||||
-- Deletes all cards currently placed on the table
|
||||
@ -284,10 +314,11 @@ end
|
||||
-- Spawn an investigator group, based on the current UI setting for either investigators or starter
|
||||
-- decks.
|
||||
---@param groupName String. Name of the group to spawn, matching a key in InvestigatorPanelData
|
||||
function spawnGroup(groupName)
|
||||
function spawnInvestigatorGroup(groupName)
|
||||
local starterMode = starterDeckMode == STARTER_DECK_MODE_STARTERS
|
||||
spawnBag.recall(true)
|
||||
Wait.frames(function()
|
||||
if spawnStarterDecks then
|
||||
if starterMode then
|
||||
spawnStarters(groupName)
|
||||
else
|
||||
spawnInvestigators(groupName)
|
||||
@ -359,13 +390,13 @@ function buildCommonSpawnSpec(investigatorName, investigatorData, position, oneC
|
||||
return {
|
||||
{
|
||||
name = investigatorName.."minicards",
|
||||
cards = oneCardOnly and investigatorData.minicards[1] or investigatorData.minicards,
|
||||
cards = oneCardOnly and { investigatorData.minicards[1] } or investigatorData.minicards,
|
||||
globalPos = position,
|
||||
rotation = FACE_UP_ROTATION,
|
||||
},
|
||||
{
|
||||
name = investigatorName.."cards",
|
||||
cards = oneCardOnly and investigatorData.cards[1] or investigatorData.cards,
|
||||
cards = oneCardOnly and { investigatorData.cards[1] } or investigatorData.cards,
|
||||
globalPos = cardPos,
|
||||
rotation = FACE_UP_ROTATION,
|
||||
},
|
||||
@ -452,31 +483,34 @@ function placeClassCards(cardClass, isUpgraded)
|
||||
table.insert(assetList, cardId)
|
||||
end
|
||||
end
|
||||
local groupPos = Vector(START_POSITIONS.classCards)
|
||||
if #skillList > 0 then
|
||||
spawnBag.spawn({
|
||||
name = cardClass .. (isUpgraded and "upgraded" or "basic"),
|
||||
cards = skillList,
|
||||
globalPos = START_POSITIONS.skill,
|
||||
globalPos = groupPos,
|
||||
rotation = FACE_UP_ROTATION,
|
||||
spread = true,
|
||||
spreadCols = 20
|
||||
})
|
||||
groupPos.x = groupPos.x - math.ceil(#skillList / 20) * CARD_ROW_OFFSET - CARD_GROUP_OFFSET
|
||||
end
|
||||
if #eventList > 0 then
|
||||
spawnBag.spawn({
|
||||
name = cardClass .. "event" .. (isUpgraded and "upgraded" or "basic"),
|
||||
cards = eventList,
|
||||
globalPos = START_POSITIONS.event,
|
||||
globalPos = groupPos,
|
||||
rotation = FACE_UP_ROTATION,
|
||||
spread = true,
|
||||
spreadCols = 20
|
||||
})
|
||||
groupPos.x = groupPos.x - math.ceil(#eventList / 20) * CARD_ROW_OFFSET - CARD_GROUP_OFFSET
|
||||
end
|
||||
if #assetList > 0 then
|
||||
spawnBag.spawn({
|
||||
name = cardClass .. "asset" .. (isUpgraded and "upgraded" or "basic"),
|
||||
cards = assetList,
|
||||
globalPos = START_POSITIONS.asset,
|
||||
globalPos = groupPos,
|
||||
rotation = FACE_UP_ROTATION,
|
||||
spread = true,
|
||||
spreadCols = 20
|
||||
@ -484,26 +518,108 @@ function placeClassCards(cardClass, isUpgraded)
|
||||
end
|
||||
end
|
||||
|
||||
-- Clears the current cards, and places all basic weaknesses on the table.
|
||||
function spawnWeaknesses()
|
||||
spawnBag.recall(fast)
|
||||
-- Spawns the investigator sets and all cards for the given cycle
|
||||
---@param cycle String Name of a cycle, should match the standard used in card metadata
|
||||
function spawnCycle(cycle)
|
||||
spawnBag.recall(true)
|
||||
spawnInvestigators(cycle)
|
||||
local allCardsBag = getObjectFromGUID(ALL_CARDS_BAG_GUID)
|
||||
local indexReady = allCardsBag.call("isIndexReady")
|
||||
if (not indexReady) then
|
||||
broadcastToAll("Still loading player cards, please try again in a few seconds", {0.9, 0.2, 0.2})
|
||||
return
|
||||
end
|
||||
local weaknessIdList = allCardsBag.call("getBasicWeaknesses")
|
||||
local cycleCardList = allCardsBag.call("getCardsByCycle", cycle)
|
||||
local copiedList = { }
|
||||
for i, id in ipairs(weaknessIdList) do
|
||||
for i, id in ipairs(cycleCardList) do
|
||||
copiedList[i] = id
|
||||
end
|
||||
spawnBag.spawn({
|
||||
name = "weaknesses",
|
||||
name = "cycle"..cycle,
|
||||
cards = copiedList,
|
||||
globalPos = START_POSITIONS.asset,
|
||||
globalPos = START_POSITIONS.cycle,
|
||||
rotation = FACE_UP_ROTATION,
|
||||
spread = true,
|
||||
spreadCols = 20
|
||||
})
|
||||
end
|
||||
|
||||
function spawnBonded()
|
||||
spawnBag.recall(true)
|
||||
spawnBag.spawn({
|
||||
name = "bonded",
|
||||
cards = BONDED_CARD_LIST,
|
||||
globalPos = START_POSITIONS.classCards,
|
||||
rotation = FACE_UP_ROTATION,
|
||||
spread = true,
|
||||
spreadCols = 20
|
||||
})
|
||||
end
|
||||
|
||||
function spawnUpgradeSheets()
|
||||
spawnBag.recall(true)
|
||||
spawnBag.spawn({
|
||||
name = "upgradeSheets",
|
||||
cards = UPGRADE_SHEET_LIST,
|
||||
globalPos = START_POSITIONS.classCards,
|
||||
rotation = FACE_UP_ROTATION,
|
||||
spread = true,
|
||||
spreadCols = 20
|
||||
})
|
||||
spawnBag.spawn({
|
||||
name = "servitor",
|
||||
cards = { "09080-m" },
|
||||
globalPos = START_POSITIONS.summonedServitor,
|
||||
rotation = FACE_UP_ROTATION,
|
||||
})
|
||||
end
|
||||
|
||||
-- Clears the current cards, and places all basic weaknesses on the table.
|
||||
function spawnWeaknesses()
|
||||
spawnBag.recall(true)
|
||||
local allCardsBag = getObjectFromGUID(ALL_CARDS_BAG_GUID)
|
||||
local indexReady = allCardsBag.call("isIndexReady")
|
||||
if (not indexReady) then
|
||||
broadcastToAll("Still loading player cards, please try again in a few seconds", {0.9, 0.2, 0.2})
|
||||
return
|
||||
end
|
||||
local weaknessIdList = allCardsBag.call("getUniqueWeaknesses")
|
||||
local copiedList = { }
|
||||
for i, id in ipairs(weaknessIdList) do
|
||||
copiedList[i] = id
|
||||
end
|
||||
local groupPos = Vector(START_POSITIONS.classCards)
|
||||
spawnBag.spawn({
|
||||
name = "weaknesses",
|
||||
cards = copiedList,
|
||||
globalPos = groupPos,
|
||||
rotation = FACE_UP_ROTATION,
|
||||
spread = true,
|
||||
spreadCols = 20
|
||||
})
|
||||
groupPos.x = groupPos.x - math.ceil(#copiedList / 20) * CARD_ROW_OFFSET - CARD_GROUP_OFFSET
|
||||
spawnBag.spawn({
|
||||
name = "evolvedWeaknesses",
|
||||
cards = EVOLVED_WEAKNESSES,
|
||||
globalPos = groupPos,
|
||||
rotation = FACE_UP_ROTATION,
|
||||
spread = true,
|
||||
spreadCols = 20
|
||||
})
|
||||
end
|
||||
|
||||
function spawnRandomWeakness()
|
||||
spawnBag.recall(true)
|
||||
local allCardsBag = getObjectFromGUID(ALL_CARDS_BAG_GUID)
|
||||
local weaknessId = allCardsBag.call("getRandomWeaknessId")
|
||||
if (weaknessId == nil) then
|
||||
broadcastToAll("All basic weaknesses are in play!", {0.9, 0.2, 0.2})
|
||||
return
|
||||
end
|
||||
spawnBag.spawn({
|
||||
name = "randomWeakness",
|
||||
cards = { weaknessId },
|
||||
globalPos = START_POSITIONS.randomWeakness,
|
||||
rotation = FACE_UP_ROTATION,
|
||||
})
|
||||
end
|
||||
|
@ -1,3 +1,45 @@
|
||||
BONDED_CARD_LIST = {
|
||||
"05314", -- Soothing Melody
|
||||
"06277", -- Wish Eater
|
||||
"06019", -- Bloodlust
|
||||
"06022", -- Pendant of the Queen
|
||||
"05317", -- Blood-rite
|
||||
"06113", -- Essence of the Dream
|
||||
"06028", -- Stars Are Right
|
||||
"06025", -- Guardian of the Crystallizer
|
||||
"06283", -- Unbound Beast
|
||||
"06032", -- Zeal
|
||||
"06031", -- Hope
|
||||
"06033", -- Augur
|
||||
"06331", -- Dream Parasite
|
||||
"06015a", -- Dream-Gate
|
||||
}
|
||||
|
||||
UPGRADE_SHEET_LIST = {
|
||||
"09040-c", -- Alchemical Distillation
|
||||
"09023-c", -- Custom Modifications
|
||||
"09059-c", -- Damning Testimony
|
||||
"09041-c", -- Emperical Hypothesis
|
||||
"09060-c", -- Friends in Low Places
|
||||
"09101-c", -- Grizzled
|
||||
"09061-c", -- Honed Instinct
|
||||
"09021-c", -- Hunter's Armor
|
||||
"09119-c", -- Hyperphysical Shotcaster
|
||||
"09079-c", -- Living Ink
|
||||
"09100-c", -- Makeshift Trap
|
||||
"09099-c", -- Pocket Multi Tool
|
||||
"09081-c", -- Power Word
|
||||
"09022-c", -- Runic Axe
|
||||
"09080-c", -- Summoned Servitor
|
||||
"09042-c", -- Raven's Quill
|
||||
}
|
||||
|
||||
EVOLVED_WEAKNESSES = {
|
||||
"04039",
|
||||
"04041",
|
||||
"04042",
|
||||
}
|
||||
|
||||
------------------ START INVESTIGATOR DATA DEFINITION ------------------
|
||||
INVESTIGATOR_GROUPS = {
|
||||
Guardian = {
|
||||
@ -13,10 +55,6 @@ INVESTIGATOR_GROUPS = {
|
||||
"D2",
|
||||
"R3",
|
||||
"D3",
|
||||
"R4",
|
||||
"D4",
|
||||
"R5",
|
||||
"D5",
|
||||
},
|
||||
}
|
||||
|
||||
@ -25,13 +63,13 @@ INVESTIGATORS["Roland Banks"] = {
|
||||
cards = { "01001", "01001-promo", "01001-p", "01001-pf", "01001-pb", },
|
||||
minicards = { "01001-m", "01001-promo-m", },
|
||||
signatures = { "01006", "01007", "90030", "90031", },
|
||||
starterDeck = "1462",
|
||||
starterDeck = "2624931",
|
||||
}
|
||||
INVESTIGATORS["Daisy Walker"] = {
|
||||
cards = { "01002", "01002-p", "01002-pf", "01002-pb", },
|
||||
minicards = { "01002-m", },
|
||||
signatures = { "01008", "01009", "90002", "90003" },
|
||||
starterDeck = "42652",
|
||||
starterDeck = "2624938",
|
||||
}
|
||||
------------------ END INVESTIGATOR DATA DEFINITION ------------------
|
||||
INVESTIGATORS["R2"] = INVESTIGATORS["Roland Banks"]
|
||||
|
@ -663,7 +663,7 @@ function clickableClues(showCounter)
|
||||
local pos = self.positionToWorld({x = -1.12, y = 0.05, z = 0.7})
|
||||
for i = 1, clueCount do
|
||||
pos.y = pos.y + 0.045 * i
|
||||
TokenManager.spawnToken(pos, "clue", PLAY_ZONE_ROTATION)
|
||||
tokenManager.spawnToken(pos, "clue", PLAY_ZONE_ROTATION)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -3,26 +3,59 @@ do
|
||||
local internal = { }
|
||||
|
||||
local MAT_IDS = {
|
||||
White = "8b081b",
|
||||
White = "8b081b",
|
||||
Orange = "bd0ff4",
|
||||
Green = "383d8b",
|
||||
Red = "0840d5"
|
||||
Green = "383d8b",
|
||||
Red = "0840d5"
|
||||
}
|
||||
|
||||
local CLUE_COUNTER_GUIDS = {
|
||||
White = "37be78",
|
||||
White = "37be78",
|
||||
Orange = "1769ed",
|
||||
Green = "032300",
|
||||
Red = "d86b7c"
|
||||
Green = "032300",
|
||||
Red = "d86b7c"
|
||||
}
|
||||
|
||||
local CLUE_CLICKER_GUIDS = {
|
||||
White = "db85d6",
|
||||
White = "db85d6",
|
||||
Orange = "3f22e5",
|
||||
Green = "891403",
|
||||
Red = "4111de"
|
||||
Green = "891403",
|
||||
Red = "4111de"
|
||||
}
|
||||
|
||||
-- Returns the color of the by position requested playermat as string
|
||||
---@param startPos Table Position of the search, table get's roughly cut into 4 quarters to assign a playermat
|
||||
PlaymatApi.getMatColorByPosition = function(startPos)
|
||||
if startPos.x < -42 then
|
||||
if startPos.z > 0 then
|
||||
return "White"
|
||||
else
|
||||
return "Orange"
|
||||
end
|
||||
else
|
||||
if startPos.z > 0 then
|
||||
return "Green"
|
||||
else
|
||||
return "Red"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Returns the draw deck of the requested playmat
|
||||
---@param matColor String Color of the playermat
|
||||
PlaymatApi.getDrawDeck = function(matColor)
|
||||
local mat = getObjectFromGUID(MAT_IDS[matColor])
|
||||
mat.call("getDrawDiscardDecks")
|
||||
return mat.getVar("drawDeck")
|
||||
end
|
||||
|
||||
-- Returns the position of the discard pile of the requested playmat
|
||||
---@param matColor String Color of the playermat
|
||||
PlaymatApi.getDiscardPosition = function(matColor)
|
||||
local mat = getObjectFromGUID(MAT_IDS[matColor])
|
||||
return mat.getTable("DISCARD_PILE_POSITION")
|
||||
end
|
||||
|
||||
-- Sets the requested playermat'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
|
||||
@ -79,7 +112,7 @@ do
|
||||
-- Convenience function to look up a mat's object by color, or get all mats.
|
||||
---@param matColor String for one of the active player colors - White, Orange, Green, Red. Also
|
||||
-- accepts "All" as a special value which will return all four mats.
|
||||
---@return Array of playermat objects. If a single mat is requested, will return a single-element
|
||||
---@return: Array of playermat objects. If a single mat is requested, will return a single-element
|
||||
-- array to simplify processing by consumers.
|
||||
internal.getMatForColor = function(matColor)
|
||||
local targetMatGuid = MAT_IDS[matColor]
|
||||
|
@ -104,4 +104,17 @@
|
||||
</Panel>
|
||||
</VerticalLayout>
|
||||
|
||||
<!-- Title Splash when starting a scenario -->
|
||||
<Text id="title_splash"
|
||||
fontSize="150"
|
||||
font="font_teutonic-arkham"
|
||||
outline="black"
|
||||
outlineSize="3 -3"
|
||||
showAnimation="FadeIn"
|
||||
hideAnimation="FadeOut"
|
||||
active="false"
|
||||
animationDuration="2"
|
||||
horizontalOverflow="Wrap">
|
||||
</Text>
|
||||
|
||||
<Include src="OptionPanel.xml"/>
|
||||
|
@ -142,6 +142,20 @@
|
||||
</Cell>
|
||||
</Row>
|
||||
|
||||
<!-- Option: splash scenario name on setup -->
|
||||
<Row class="option-text">
|
||||
<Cell class="option-text">
|
||||
<VerticalLayout class="text-column">
|
||||
<Text class="option-header">Show Scenario Title on Setup</Text>
|
||||
<Text class="description">Fade in the name of the scenario for 2 seconds when placing down a scenario.</Text>
|
||||
</VerticalLayout>
|
||||
</Cell>
|
||||
<Cell class="option-button">
|
||||
<Toggle id="showTitleSplash"
|
||||
onValueChanged="onClick_toggleOption(showTitleSplash)"/>
|
||||
</Cell>
|
||||
</Row>
|
||||
|
||||
<!-- Group: fan-made accessories -->
|
||||
<Row class="group-header">
|
||||
<Cell class="group-header">
|
||||
|
Loading…
Reference in New Issue
Block a user