Merge branch 'main' into extraToken

This commit is contained in:
Chr1Z93 2024-06-08 23:03:55 +02:00
commit b8a0b38e55
11 changed files with 347 additions and 295 deletions

View File

@ -9,9 +9,29 @@
"Order": 0
},
"ColorDiffuse": {
"b": 0,
"g": 0.36652,
"r": 0.70588
"b": 1,
"g": 1,
"r": 1
},
"CustomMesh": {
"CastShadows": true,
"ColliderURL": "https://raw.githubusercontent.com/RobMayer/TTSLibrary/master/advboxes/core_h_COL.obj",
"Convex": true,
"CustomShader": {
"FresnelStrength": 0,
"SpecularColor": {
"b": 1,
"g": 1,
"r": 1
},
"SpecularIntensity": 0,
"SpecularSharpness": 2
},
"DiffuseURL": "http://cloud-3.steamusercontent.com/ugc/2450601198422160026/E21C455A90B78E48E0D03FCA4AF52A9C33C31534/",
"MaterialIndex": 3,
"MeshURL": "https://raw.githubusercontent.com/RobMayer/TTSLibrary/master/advboxes/core_h_MSH.obj",
"NormalURL": "",
"TypeIndex": 6
},
"Description": "Put any cards in here to add them to the indices for the player card panel and deck importer.\n\nSelect the 'update index' entry in the context menu of this bag once you've added all cards.\n\nThis can be used for custom cards too.",
"DragSelectable": true,
@ -29,7 +49,7 @@
"MaterialIndex": -1,
"MeasureMovement": false,
"MeshIndex": -1,
"Name": "Bag",
"Name": "Custom_Model",
"Nickname": "Additional Player Cards",
"Number": 0,
"Snap": true,
@ -40,14 +60,14 @@
"Tooltip": true,
"Transform": {
"posX": 60,
"posY": 1.204,
"posY": 1.486,
"posZ": 48,
"rotX": 0,
"rotY": 0,
"rotY": 270,
"rotZ": 0,
"scaleX": 1.5,
"scaleY": 1.5,
"scaleZ": 1.5
"scaleX": 1,
"scaleY": 0.14,
"scaleZ": 1
},
"Value": 0,
"XmlUI": ""

View File

@ -22,7 +22,7 @@
"ImageURL": "http://cloud-3.steamusercontent.com/ugc/1704036721123215146/E44A3B99EACF310E49E94977151A03C9A3DC7F17/",
"WidthScale": 0
},
"Description": "Displays the hand size (total or by title for \"Dream Enhancing Serum\"), hover over it to briefly toggle counting method.\n\nAllows you to randomly discard a card from your hand.",
"Description": "Displays the hand size (total or by title for \"Dream Enhancing Serum\" - hover over it to see the regular count).\n\nAllows you to randomly discard a card from your hand.",
"DragSelectable": true,
"GMNotes": "",
"GUID": "450688",

View File

@ -44,7 +44,7 @@
"Transform": {
"posX": 60,
"posY": 1.481,
"posZ": 56,
"posZ": 57,
"rotX": 0,
"rotY": 270,
"rotZ": 0,

View File

@ -1,7 +1,7 @@
local playmatApi = require("playermat/PlaymatApi")
-- forward declaration of variables that are used across functions
local matColor, handColor, loopId, hovering
local matColor, handColor, hovering
function onLoad()
local buttonParamaters = {}
@ -10,7 +10,7 @@ function onLoad()
-- index 0: button as hand size label
buttonParamaters.hover_color = "White"
buttonParamaters.click_function = "none"
buttonParamaters.position = { 0, 0.11, -0.4 }
buttonParamaters.position = Vector(0, 0.11, -0.4)
buttonParamaters.height = 0
buttonParamaters.width = 0
buttonParamaters.font_size = 500
@ -19,17 +19,14 @@ function onLoad()
-- index 1: button to toggle "des"
buttonParamaters.label = "DES: ✗"
buttonParamaters.click_function = "none"
buttonParamaters.position = { 0, 0.11, 0.25 }
buttonParamaters.height = 0
buttonParamaters.width = 0
buttonParamaters.position.z = 0.25
buttonParamaters.font_size = 120
self.createButton(buttonParamaters)
-- index 2: button to discard a card
buttonParamaters.label = "discard random card"
buttonParamaters.label = "Discard Random Card"
buttonParamaters.click_function = "discardRandom"
buttonParamaters.position = { 0, 0.11, 0.7 }
buttonParamaters.position.z = 0.7
buttonParamaters.height = 175
buttonParamaters.width = 900
buttonParamaters.font_size = 90
@ -39,27 +36,24 @@ function onLoad()
updateColors()
-- start loop to update card count
loopId = Wait.time(updateValue, 1, -1)
playmatApi.checkForDES(matColor)
Wait.time(updateValue, 1, -1)
end
-- updates colors when object is dropped somewhere
function onDrop() updateColors() end
-- toggles counting method briefly
function onObjectHover(hover_color, obj)
-- only continue if correct player hovers over "self"
if obj ~= self or hover_color ~= handColor or hovering then return end
-- disables DES counting while hovered
function onObjectHover(hoverColor, object)
if hoverColor ~= handColor then return end
-- toggle this flag so this doesn't get executed multiple times during the delay
hovering = true
-- stop loop, toggle "des" and displayed value briefly, then start new loop after 2s
Wait.stop(loopId)
updateValue(true)
Wait.time(function()
loopId = Wait.time(updateValue, 1, -1)
if object == self then
hovering = true
playmatApi.checkForDES(matColor)
updateValue()
else
hovering = false
end, 1)
end
end
-- updates the matcolor and handcolor variable
@ -70,7 +64,7 @@ function updateColors()
end
-- count cards in hand (by name for DES)
function updateValue(toggle)
function updateValue()
-- update colors if handColor doesn't own a handzone
if Player[handColor].getHandCount() == 0 then
updateColors()
@ -79,19 +73,24 @@ function updateValue(toggle)
-- if there is still no handzone, then end here
if Player[handColor].getHandCount() == 0 then return end
-- get state of "Dream-Enhancing Serum" from playermat and update button label
local des = playmatApi.isDES(matColor)
if toggle then des = not des end
self.editButton({ index = 1, label = "DES: " .. (des and "✓" or "✗") })
-- get state of "Dream-Enhancing Serum" from playermat
local hasDES = playmatApi.hasDES(matColor)
-- default to regular count if hovered
if hovering then
hasDES = false
end
self.editButton({ index = 1, label = "DES: " .. (hasDES and "✓" or "✗") })
-- count cards in hand
local hand = Player[handColor].getHandObjects()
local size = 0
if des then
if hasDES then
local cardHash = {}
for _, obj in pairs(hand) do
if obj.tag == "Card" then
if obj.type == "Card" then
local name = obj.getName()
local title = string.match(name, '(.+)(%s%(%d+%))') or name
cardHash[title] = true
@ -102,12 +101,14 @@ function updateValue(toggle)
end
else
for _, obj in pairs(hand) do
if obj.tag == "Card" then size = size + 1 end
if obj.type == "Card" then
size = size + 1
end
end
end
-- update button label and color
self.editButton({ index = 0, font_color = des and "Green" or "White", label = size })
self.editButton({ index = 0, font_color = hasDES and "Green" or "White", label = size })
end
-- discards a random non-hidden card from hand

View File

@ -163,12 +163,11 @@ function endSearch(_, _, isRightClick)
-- draw set aside cards (from the ground!)
for _, obj in ipairs(searchLib.atPosition(setAsidePosition, "isCardOrDeck")) do
local count = 1
if obj.type == "Deck" then
Wait.time(function() obj.deal(#obj.getObjects(), handColor) end, 1)
elseif obj.type == "Card" then
obj.setPosition(Player[handColor].getHandTransform().position)
obj.flip()
count = #obj.getObjects()
end
Wait.time(function() obj.deal(count, handColor) end, 1)
end
normalView()
@ -180,11 +179,11 @@ function endSearch(_, _, isRightClick)
if deckAreaObjects.draw then
deckAreaObjects.draw.shuffle()
end
end, (#handCards + 2.5) * 0.2)
end, #handCards * 0.3 + 0.5)
end
-- Norman Withers handling
if topCardDetected then
Wait.time(function() playmatApi.flipTopCardFromDeck(matColor) end, #handCards * 0.2)
Wait.time(function() playmatApi.flipTopCardFromDeck(matColor) end, #handCards * 0.3 + 0.75)
end
end

View File

@ -71,45 +71,42 @@ function takeCardIntoThreatArea(playerColor, hoveredObject)
local matColor = playmatApi.getMatColor(playerColor)
local mat = guidReferenceApi.getObjectByOwnerAndType(matColor, "Playermat")
-- do not continue if the threat area is already full
if playmatApi.getEncounterCardDrawPosition(matColor, false) == playmatApi.getEncounterCardDrawPosition(matColor, true) then
broadcastToColor("Threat area is full.", playerColor,"Yellow")
return
if playmatApi.getEncounterCardDrawPosition(matColor, false) == playmatApi.getEncounterCardDrawPosition(matColor, true) then
broadcastToColor("Threat area is full.", playerColor, "Yellow")
return
end
-- initialize list of objects to move
local moveTheseObjects = {}
for _, obj in ipairs(searchLib.onObject(hoveredObject, "isTileOrToken")) do
table.insert(moveTheseObjects, obj)
end
-- find out if the original card is on the green or red playmats
local originalMatColor = guidReferenceApi.getOwnerOfObject(hoveredObject)
-- determine modifiers for the playmats
local modifierY
local modifierY = 0
if originalMatColor == "Red" then
modifierY = 90
elseif originalMatColor == "Green" then
modifierY = -90
else
modifierY = 0
end
-- store local positions of objects
local localPositions = {}
for i, obj in ipairs(moveTheseObjects) do
local localPos = hoveredObject.positionToLocal(obj.getPosition())
localPositions[i] = localPos
end
-- move the main card
local pos = playmatApi.getEncounterCardDrawPosition(matColor, false)
hoveredObject.setPosition(pos)
hoveredObject.setRotation(hoveredObject.getRotation() - Vector(0, 270-mat.getRotation().y-modifierY, 0))
hoveredObject.setRotation(hoveredObject.getRotation() - Vector(0, 270 - mat.getRotation().y - modifierY, 0))
local cardName = hoveredObject.getName()
if cardName == nil or cardName == "" then
cardName = "card(s)"
@ -120,7 +117,7 @@ function takeCardIntoThreatArea(playerColor, hoveredObject)
if not obj.locked then
local globalPos = hoveredObject.positionToWorld(localPositions[i])
obj.setPosition(globalPos)
obj.setRotation(obj.getRotation() - Vector(0, 270-mat.getRotation().y-modifierY, 0))
obj.setRotation(obj.getRotation() - Vector(0, 270 - mat.getRotation().y - modifierY, 0))
end
end
end
@ -136,15 +133,17 @@ function discardObject(playerColor, hoveredObject)
end
-- These should probably not be discarded normally. Ask player for confirmation.
if (hoveredObject.type == "Deck") or hoveredObject.hasTag("Location") then
if hoveredObject.type == "Deck" or hoveredObject.hasTag("Location") then
local suspect = (hoveredObject.type == "Deck") and "Deck" or "Location"
Player[playerColor].showConfirmDialog("Discard " .. suspect .. "?", function () performDiscard(playerColor, hoveredObject) end)
Player[playerColor].showConfirmDialog("Discard " .. suspect .. "?",
function() performDiscard(playerColor, hoveredObject) end)
return
end
performDiscard(playerColor, hoveredObject)
end
-- actually performs the discarding of the object and tokens / tiles on it
function performDiscard(playerColor, hoveredObject)
-- initialize list of objects to discard
local discardTheseObjects = { hoveredObject }
@ -169,13 +168,14 @@ function discardTopDeck(playerColor, hoveredObject)
broadcastToColor("Hover a deck/card and try again.", playerColor, "Yellow")
return
end
-- take top card from deck (unless it is already a single card)
local takenCard = hoveredObject
if hoveredObject.type == "Deck" then
takenCard = hoveredObject.takeObject({index = 0})
else
takenCard = hoveredObject
takenCard = hoveredObject.takeObject({ index = 0 })
end
Wait.frames(function() performDiscard(playerColor, takenCard) end, 1)
end
end
-- helper function to get the player to trigger the discard function for
function getColorToDiscardFor(hoveredObject, playerColor)
@ -194,15 +194,21 @@ function getColorToDiscardFor(hoveredObject, playerColor)
areaNearPlaymat.minZ = bounds.center.z - bounds.size.z / 2 - bufferAroundPlaymat
areaNearPlaymat.maxZ = bounds.center.z + bounds.size.z / 2 + bufferAroundPlaymat
-- discard to closest mat if near it, use triggering playmat if not
local discardForMatColor
-- discard to closest mat if near it
if inArea(pos, areaNearPlaymat) then
return closestMatColor
elseif pos.y > (Player[playerColor].getHandTransform().position.y - (Player[playerColor].getHandTransform().scale.y / 2)) then -- discard to closest mat if card is in a hand
return closestMatColor
else
return playmatApi.getMatColor(playerColor)
end
-- discard to closest mat if card is in a hand
local handZone = guidReferenceApi.getObjectByOwnerAndType(closestMatColor, "HandZone")
for _, zone in ipairs(hoveredObject.getZones()) do
if zone == handZone then
return closestMatColor
end
end
-- discard to triggering mat if previous conditions weren't met
return playmatApi.getMatColor(playerColor)
end
-- moves the hovered card to the victory display
@ -408,17 +414,17 @@ function takeClueFromLocation(playerColor, hoveredObject)
end
if clickableClues then
pos = {x = 0.49, y = 2.66, z = 0.00}
pos = { x = 0.49, y = 2.66, z = 0.00 }
playmatApi.updateCounter(matColor, "ClickableClueCounter", _, 1)
else
pos = playmatApi.transformLocalPosition({x = -1.12, y = 0.05, z = 0.7}, matColor)
pos = playmatApi.transformLocalPosition({ x = -1.12, y = 0.05, z = 0.7 }, matColor)
end
local rot = playmatApi.returnRotation(matColor)
-- check if found clue is a stack or single token
if clue.getQuantity() > 1 then
clue.takeObject({position = pos, rotation = rot})
clue.takeObject({ position = pos, rotation = rot })
else
clue.setPositionSmooth(pos)
clue.setRotation(rot)
@ -448,9 +454,9 @@ end
---@param bounds table Defined area to see if the point is within
function inArea(point, bounds)
return (point.x > bounds.minX
and point.x < bounds.maxX
and point.z > bounds.minZ
and point.z < bounds.maxZ)
and point.x < bounds.maxX
and point.z > bounds.minZ
and point.z < bounds.maxZ)
end
-- capitalizes the first letter

View File

@ -1445,7 +1445,7 @@ function applyOptionPanelChange(id, state)
local counter = guidReferenceApi.getObjectByOwnerAndType("Mythos", "MasterClueCounter")
counter.setVar("useClickableCounters", state)
-- option: Play area snap tags
-- option: Play area connection drawing
elseif id == "playAreaConnections" then
playAreaApi.setConnectionDrawState(state)

View File

@ -65,7 +65,7 @@ function onLoad(savedData)
locations = loadedData.trackedLocations or {}
currentScenario = loadedData.currentScenario
connectionColor = loadedData.connectionColor or { 0.4, 0.4, 0.4, 1 }
connectionsEnabled = loadedData.connectionsEnabled or true
connectionsEnabled = loadedData.connectionsEnabled
end
-- this needs to be here since the playarea will be reloaded when the image changes

View File

@ -1,53 +1,53 @@
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
"10006", -- Aetheric Current (Yuggoth)
"10007", -- Aetheric Current (Yoth)
"10036", -- Blade of Yoth
"10039", -- Evanescent Ascension
"10045", -- Uncanny Growth
"10063", -- Bianca
"10086", -- Rot
"10087", -- Rot
"10088", -- Rot
"10089", -- Rot
"10090", -- Rot
"10106", -- Keeper of the Key
"10107", -- Servant of Brass
"10134", -- Twilight Diadem
"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
"10006", -- Aetheric Current (Yuggoth)
"10007", -- Aetheric Current (Yoth)
"10036", -- Blade of Yoth
"10039", -- Evanescent Ascension
"10045", -- Uncanny Growth
"10063", -- Bianca
"10086", -- Rot
"10087", -- Rot
"10088", -- Rot
"10089", -- Rot
"10090", -- Rot
"10106", -- Keeper of the Key
"10107", -- Servant of Brass
"10134", -- Twilight Diadem
}
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
"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
"09081-t-c", -- Power Word (Taboo)
"09022-c", -- Runic Axe
"09022-c", -- Runic Axe
"09022-t-c", -- Runic Axe (Taboo)
"09080-c", -- Summoned Servitor
"09042-c", -- Raven's Quill
"09080-c", -- Summoned Servitor
"09042-c", -- Raven's Quill
}
EVOLVED_WEAKNESSES = {
@ -60,152 +60,152 @@ EVOLVED_WEAKNESSES = {
------------------ START INVESTIGATOR DATA DEFINITION ------------------
INVESTIGATOR_GROUPS = {
["Guardian"] = {
"Roland Banks",
"Zoey Samaras",
"Mark Harrigan",
"Leo Anderson",
"Carolyn Fern",
"Tommy Muldoon",
"Nathaniel Cho",
"Sister Mary",
"Daniela Reyes",
"Carson Sinclair",
["Guardian"] = {
"Roland Banks",
"Zoey Samaras",
"Mark Harrigan",
"Leo Anderson",
"Carolyn Fern",
"Tommy Muldoon",
"Nathaniel Cho",
"Sister Mary",
"Daniela Reyes",
"Carson Sinclair",
"Wilson Richards"
},
["Seeker"] = {
"Daisy Walker",
"Rex Murphy",
"Minh Thi Phan",
"Ursula Downs",
"Joe Diamond",
"Mandy Thompson",
"Harvey Walters",
"Amanda Sharpe",
"Norman Withers",
"Vincent Lee",
},
["Seeker"] = {
"Daisy Walker",
"Rex Murphy",
"Minh Thi Phan",
"Ursula Downs",
"Joe Diamond",
"Mandy Thompson",
"Harvey Walters",
"Amanda Sharpe",
"Norman Withers",
"Vincent Lee",
"Kate Winthrop"
},
["Rogue"] = {
"\"Skids\" O'Toole",
"Jenny Barnes",
"Sefina Rousseau",
"Finn Edwards",
"Preston Fairmont",
"Tony Morgan",
"Winifred Habbamock",
"Trish Scarborough",
"Monterey Jack",
"Kymani Jones",
},
["Rogue"] = {
"\"Skids\" O'Toole",
"Jenny Barnes",
"Sefina Rousseau",
"Finn Edwards",
"Preston Fairmont",
"Tony Morgan",
"Winifred Habbamock",
"Trish Scarborough",
"Monterey Jack",
"Kymani Jones",
"Alessandra Zorzi"
},
["Mystic"] = {
"Agnes Baker",
"Jim Culver",
"Akachi Onyele",
"Father Mateo",
"Diana Stanley",
"Marie Lambeau",
"Luke Robinson",
"Jacqueline Fine",
"Dexter Drake",
"Lily Chen",
"Amina Zidane",
"Gloria Goldberg",
},
["Mystic"] = {
"Agnes Baker",
"Jim Culver",
"Akachi Onyele",
"Father Mateo",
"Diana Stanley",
"Marie Lambeau",
"Luke Robinson",
"Jacqueline Fine",
"Dexter Drake",
"Lily Chen",
"Amina Zidane",
"Gloria Goldberg",
"Kōhaku Narukami"
},
["Survivor"] = {
"Wendy Adams",
"\"Ashcan\" Pete",
"William Yorick",
"Calvin Wright",
"Rita Young",
"Patrice Hathaway",
"Stella Clark",
"Silas Marsh",
"Bob Jenkins",
"Darrell Simmons",
},
["Survivor"] = {
"Wendy Adams",
"\"Ashcan\" Pete",
"William Yorick",
"Calvin Wright",
"Rita Young",
"Patrice Hathaway",
"Stella Clark",
"Silas Marsh",
"Bob Jenkins",
"Darrell Simmons",
"Hank Samson"
},
["Neutral"] = {
"Lola Hayes",
"Charlie Kane",
"Subject 5U-21"
},
["Core"] = {
"Roland Banks",
"Daisy Walker",
"\"Skids\" O'Toole",
"Agnes Baker",
"Wendy Adams"
},
["The Dunwich Legacy"] = {
"Zoey Samaras",
"Rex Murphy",
"Jenny Barnes",
"Jim Culver",
"\"Ashcan\" Pete"
},
["The Path to Carcosa"] = {
"Mark Harrigan",
"Minh Thi Phan",
"Sefina Rousseau",
"Akachi Onyele",
"William Yorick",
"Lola Hayes"
},
["The Forgotten Age"] = {
"Leo Anderson",
"Ursula Downs",
"Finn Edwards",
"Father Mateo",
"Calvin Wright"
},
["The Circle Undone"] = {
"Carolyn Fern",
"Joe Diamond",
"Preston Fairmont",
"Diana Stanley",
"Rita Young",
"Marie Lambeau"
},
["The Dream-Eaters"] = {
"Tommy Muldoon",
"Mandy Thompson",
"Tony Morgan",
"Luke Robinson",
"Patrice Hathaway"
},
["Investigator Packs"] = {
"Nathaniel Cho",
"Harvey Walters",
"Winifred Habbamock",
"Jacqueline Fine",
"Stella Clark",
"Gloria Goldberg"
},
["The Innsmouth Conspiracy"] = {
"Sister Mary",
"Amanda Sharpe",
"Trish Scarborough",
"Dexter Drake",
"Silas Marsh"
},
["Edge of the Earth"] = {
"Daniela Reyes",
"Norman Withers",
"Monterey Jack",
"Lily Chen",
"Bob Jenkins"
},
["The Scarlet Keys"] = {
"Carson Sinclair",
"Vincent Lee",
"Kymani Jones",
"Amina Zidane",
"Darrell Simmons",
"Charlie Kane"
},
},
["Neutral"] = {
"Lola Hayes",
"Charlie Kane",
"Subject 5U-21"
},
["Core"] = {
"Roland Banks",
"Daisy Walker",
"\"Skids\" O'Toole",
"Agnes Baker",
"Wendy Adams"
},
["The Dunwich Legacy"] = {
"Zoey Samaras",
"Rex Murphy",
"Jenny Barnes",
"Jim Culver",
"\"Ashcan\" Pete"
},
["The Path to Carcosa"] = {
"Mark Harrigan",
"Minh Thi Phan",
"Sefina Rousseau",
"Akachi Onyele",
"William Yorick",
"Lola Hayes"
},
["The Forgotten Age"] = {
"Leo Anderson",
"Ursula Downs",
"Finn Edwards",
"Father Mateo",
"Calvin Wright"
},
["The Circle Undone"] = {
"Carolyn Fern",
"Joe Diamond",
"Preston Fairmont",
"Diana Stanley",
"Rita Young",
"Marie Lambeau"
},
["The Dream-Eaters"] = {
"Tommy Muldoon",
"Mandy Thompson",
"Tony Morgan",
"Luke Robinson",
"Patrice Hathaway"
},
["Investigator Packs"] = {
"Nathaniel Cho",
"Harvey Walters",
"Winifred Habbamock",
"Jacqueline Fine",
"Stella Clark",
"Gloria Goldberg"
},
["The Innsmouth Conspiracy"] = {
"Sister Mary",
"Amanda Sharpe",
"Trish Scarborough",
"Dexter Drake",
"Silas Marsh"
},
["Edge of the Earth"] = {
"Daniela Reyes",
"Norman Withers",
"Monterey Jack",
"Lily Chen",
"Bob Jenkins"
},
["The Scarlet Keys"] = {
"Carson Sinclair",
"Vincent Lee",
"Kymani Jones",
"Amina Zidane",
"Darrell Simmons",
"Charlie Kane"
},
["The Feast of Hemlock Vale"] = {
"Wilson Richards",
"Kate Winthrop",
@ -549,38 +549,38 @@ INVESTIGATORS["Wilson Richards"] = {
cards = { "10001" },
minicards = { "10001-m" },
signatures = { "10002", "10003" },
starterDeck = "2634667" --carson deck as placeholder
starterDeck = "3893753"
}
INVESTIGATORS["Kate Winthrop"] = {
cards = { "10004" },
minicards = { "10004-m" },
signatures = { "10005", "10006", "10007", "10008" },
starterDeck = "2643928" --harvey deck as placeholder
starterDeck = "3893779"
}
INVESTIGATORS["Alessandra Zorzi"] = {
cards = { "10009" },
minicards = { "10009-m" },
signatures = { "10010", "10010", "10010", "10011" },
starterDeck = "2643931" --winifred deck as placeholder
starterDeck = "3893775"
}
INVESTIGATORS["Kōhaku Narukami"] = {
cards = { "10012" },
minicards = { "10012-m" },
signatures = { "10013", "10014" },
starterDeck = "2636199" --gloria deck as placeholder
starterDeck = "3893763"
}
INVESTIGATORS["Hank Samson"] = {
cards = { "10015", "10015-b1", "10015-b2" },
minicards = { "10015-m" },
signatures = { "10017", "10018"},
starterDeck = "2643934" --stella deck as placeholder
signatures = { "10017", "10018" },
starterDeck = "3893788"
}
-- PnP content
INVESTIGATORS["Subject 5U-21"] = {
cards = { "89001" },
minicards = { "89001-m" },
signatures = { "89002", "89003", "89003", "89003", "89004", "89004", "89004", "89005" },
starterDeck = "2624990" -- Lola's deck id until Suzi is on ArkhamDB
starterDeck = "3893795"
}
-- Promo content
INVESTIGATORS["Gloria Goldberg"] = {

View File

@ -16,6 +16,7 @@ local DISCARD_BUTTON_X_START = -1.365
local DISCARD_BUTTON_X_OFFSET = 0.455
local SEARCH_AROUND_SELF_X_BUFFER = 8
local SEARCH_AROUND_SELF_Z_BUFFER = 1.75
-- defined areas for object searching
local MAIN_PLAY_AREA = {
@ -89,7 +90,7 @@ activeInvestigatorId = "00000"
local isDrawButtonVisible = false
-- global variable to report "Dream-Enhancing Serum" status
isDES = false
hasDES = false
-- table of type-object reference pairs of all owned objects
local ownedObjects = {}
@ -170,17 +171,23 @@ end
-- finds all objects on the playmat and associated set aside zone.
function searchAroundSelf(filter)
local scale = self.getScale()
local bounds = self.getBoundsNormalized()
-- Increase the width to cover the set aside zone
bounds.size.x = bounds.size.x + SEARCH_AROUND_SELF_X_BUFFER
bounds.size.y = 1
-- Since the cast is centered on the position, shift left or right to keep the non-set aside edge
-- of the cast at the edge of the playmat
-- setAsideDirection accounts for the set aside zone being on the left or right, depending on the
-- table position of the playmat
bounds.size.z = bounds.size.z + SEARCH_AROUND_SELF_Z_BUFFER
-- 'setAsideDirection' accounts for the set aside zone being on the left or right,
-- depending on the table position of the playmat
local setAsideDirection = bounds.center.z > 0 and 1 or -1
-- Since the cast is centered on the position, shift left or right to keep
-- the non-set aside edge of the cast at the edge of the playmat
local localCenter = self.positionToLocal(bounds.center)
localCenter.x = localCenter.x + setAsideDirection * SEARCH_AROUND_SELF_X_BUFFER / 2 / self.getScale().x
localCenter.x = localCenter.x + setAsideDirection * SEARCH_AROUND_SELF_X_BUFFER / 2 / scale.x
localCenter.z = localCenter.z - SEARCH_AROUND_SELF_Z_BUFFER / 2 / scale.z
return searchArea(self.positionToWorld(localCenter), bounds.size, filter)
end
@ -291,7 +298,8 @@ function doUpkeep(_, clickedByColor, isRightClick)
updateMessageColor(clickedByColor)
-- unexhaust cards in play zone, flip action tokens and find forcedLearning
-- unexhaust cards in play zone, flip action tokens and find Forced Learning / Dream-Enhancing Serum
checkForDES()
local forcedLearning = false
local rot = self.getRotation()
for _, obj in ipairs(searchAroundSelf()) do
@ -319,7 +327,7 @@ function doUpkeep(_, clickedByColor, isRightClick)
obj.setRotation({ rot.x, rot.y + yRotDiff, rot.z })
end
-- detect forced learning to handle card drawing accordingly
-- detect Forced Learning to handle card drawing accordingly
if cardMetadata.id == "08031" then
forcedLearning = true
end
@ -535,6 +543,23 @@ function doDiscardOne()
end
end
-- checks if DES is present
function checkForDES()
hasDES = false
for _, obj in ipairs(searchAroundSelf()) do
if obj.type == "Card" then
local cardMetadata = JSON.decode(obj.getGMNotes()) or {}
-- position is used to exclude deck / discard
local cardPos = self.positionToLocal(obj.getPosition())
if cardMetadata.id == "06159" and cardPos.x > -1 then
hasDES = true
break
end
end
end
end
---------------------------------------------------------
-- slot symbol displaying
---------------------------------------------------------
@ -754,9 +779,6 @@ function onCollisionEnter(collisionInfo)
-- only continue for cards
if object.type ~= "Card" then return end
-- detect if "Dream-Enhancing Serum" is placed
if object.getName() == "Dream-Enhancing Serum" then isDES = true end
maybeUpdateActiveInvestigator(object)
syncCustomizableMetadata(object)
@ -769,11 +791,6 @@ function onCollisionEnter(collisionInfo)
end
end
-- detect if "Dream-Enhancing Serum" is removed
function onCollisionExit(collisionInfo)
if collisionInfo.collision_object.getName() == "Dream-Enhancing Serum" then isDES = false end
end
-- checks if tokens should be spawned for the provided card
function shouldSpawnTokens(card)
if card.is_face_down then

View File

@ -47,11 +47,20 @@ do
end
end
-- Instructs a playmat to check for DES
---@param matColor string Color of the playmat - White, Orange, Green, Red or All
PlaymatApi.checkForDES = function(matColor)
for _, mat in pairs(getMatForColor(matColor)) do
mat.call("checkForDES")
end
end
-- Returns if there is the card "Dream-Enhancing Serum" on the requested playmat
---@param matColor string Color of the playmat - White, Orange, Green or Red (does not support "All")
PlaymatApi.isDES = function(matColor)
---@return boolean: whether DES is present on the playmat
PlaymatApi.hasDES = function(matColor)
for _, mat in pairs(getMatForColor(matColor)) do
return mat.getVar("isDES")
return mat.getVar("hasDES")
end
end