diff --git a/objects/PlayArea.721ba2.json b/objects/PlayArea.721ba2.json
index 08bac973..7a4e0967 100644
--- a/objects/PlayArea.721ba2.json
+++ b/objects/PlayArea.721ba2.json
@@ -959,6 +959,13 @@
"ImageURL": "https://steamusercontent-a.akamaihd.net/ugc/998015670465071049/FFAE162920D67CF38045EFBD3B85AD0F916147B2/",
"WidthScale": 0
},
+ "CustomUIAssets": [
+ {
+ "Name": "font_teutonic-arkham",
+ "Type": 1,
+ "URL": "https://steamusercontent-a.akamaihd.net/ugc/2027213118467703445/89328E273B4C5180BF491516CE998DE3C604E162/"
+ }
+ ],
"Description": "",
"DragSelectable": true,
"GMNotes": "",
@@ -995,5 +1002,5 @@
"scaleZ": 10
},
"Value": 0,
- "XmlUI": ""
+ "XmlUI": "\u003cInclude src=\"PlayArea.xml\"/\u003e"
}
diff --git a/src/core/DoomCounter.ttslua b/src/core/DoomCounter.ttslua
index 2057389b..3bc07839 100644
--- a/src/core/DoomCounter.ttslua
+++ b/src/core/DoomCounter.ttslua
@@ -61,7 +61,7 @@ function updateVal(number)
if number then
broadcastDoom(val)
else
- broadcastToAll("0 doom on the agenda", "White")
+ broadcastToAll("0 doom on the agenda")
end
end
@@ -72,9 +72,9 @@ function broadcastDoom(val)
local doomThreshold = getDoomThreshold()
if doomThreshold then
- broadcastToAll(val .. " doom on the agenda (" .. doomInPlay .. "/" .. doomThreshold .. " in play)", "White")
+ broadcastToAll(val .. " doom on the agenda (" .. doomInPlay .. "/" .. doomThreshold .. " in play)")
else
- broadcastToAll(val .. " doom on the agenda (" .. doomInPlay .. " in play)", "White")
+ broadcastToAll(val .. " doom on the agenda (" .. doomInPlay .. " in play)")
end
end
diff --git a/src/core/GameKeyHandler.ttslua b/src/core/GameKeyHandler.ttslua
index 7d79bd0d..dcc08363 100644
--- a/src/core/GameKeyHandler.ttslua
+++ b/src/core/GameKeyHandler.ttslua
@@ -54,6 +54,9 @@ function triggerUpkeepMultihanded(playerColor)
playermatApi.doUpkeepFromHotkey(matColor, playerColor)
end
end
+
+ -- also trigger the PlayArea's "Ready Cards" function
+ playAreaApi.readyCards()
end
-- adds 1 doom to the agenda
diff --git a/src/core/PlayArea.ttslua b/src/core/PlayArea.ttslua
index dd0836b1..d6551ff7 100644
--- a/src/core/PlayArea.ttslua
+++ b/src/core/PlayArea.ttslua
@@ -21,7 +21,8 @@ local CONNECTION_LINE_Y = 1.529
-- used for recreating the link to a custom data helper after image change
customDataHelper = nil
-local DEFAULT_URL = "https://steamusercontent-a.akamaihd.net/ugc/998015670465071049/FFAE162920D67CF38045EFBD3B85AD0F916147B2/"
+local DEFAULT_URL =
+"https://steamusercontent-a.akamaihd.net/ugc/998015670465071049/FFAE162920D67CF38045EFBD3B85AD0F916147B2/"
local SHIFT_OFFSETS = {
left = { x = 0.00, y = 0, z = 7.67 },
@@ -69,7 +70,7 @@ function onLoad(savedData)
end
-- this needs to be here since the playarea will be reloaded when the image changes
- self.interactable = false
+ self.interactable = false
Wait.time(function() collisionEnabled = true end, 0.1)
end
@@ -308,7 +309,7 @@ function buildConnection(cardId, iconCardList, locData)
-- If the reciprocal exists, convert it to BiDi, otherwise add as a one-way
if locationConnections[connectedGuid] ~= nil
and (locationConnections[connectedGuid][cardId] == ONE_WAY
- or locationConnections[connectedGuid][cardId] == BIDIRECTIONAL) then
+ or locationConnections[connectedGuid][cardId] == BIDIRECTIONAL) then
locationConnections[connectedGuid][cardId] = BIDIRECTIONAL
locationConnections[cardId][connectedGuid] = nil
else
@@ -426,7 +427,8 @@ function addOneWayVector(origin, target, vectorOwner, lines)
-- Calculate distance to be closer for horizontal positions than vertical, since cards are taller than 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)))
+ 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
@@ -449,8 +451,10 @@ end
--- positioning and scaling, as well as highlighting connections during a drag operation
---@param lines table List of vector line elements. Mutable, will be updated to add this arrow
function addArrowLines(arrowheadPos, originPos, vectorOwner, lines)
- local arrowArm1 = Vector(arrowheadPos):moveTowards(originPos, ARROW_ARM_LENGTH):sub(arrowheadPos):rotateOver("y", -1 * ARROW_ANGLE):add(arrowheadPos)
- local arrowArm2 = Vector(arrowheadPos):moveTowards(originPos, ARROW_ARM_LENGTH):sub(arrowheadPos):rotateOver("y", ARROW_ANGLE):add(arrowheadPos)
+ 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 = vectorOwner.positionToLocal(arrowheadPos)
local arm1 = vectorOwner.positionToLocal(arrowArm1)
@@ -512,6 +516,55 @@ function highlightMissingData(state)
end
end
+-- Readies all cards in the main playarea (both player cards, treacheries and enemies)
+function readyCards(player, clickType)
+ local playerColor = player.color
+
+ -- when right-clicked
+ if clickType == "-2" then
+ printToColor("This will ready (rotate 90° closer to 0°) all cards in the main play area." ..
+ " Make sure to handle enemy engagement manually. To exclude a card from this (e.g. Handcuffs)," ..
+ " right-click it, select 'Tags' and add the tag 'DoNotReady' to it.", playerColor)
+ return
+ end
+
+ local zone = guidReferenceApi.getObjectByOwnerAndType("Mythos", "PlayAreaZone")
+ if not zone then
+ broadcastToColor("Scripting zone couldn't be found.", playerColor, "Red")
+ return
+ end
+
+ broadcastToAll("Readied cards in Play Area")
+
+ local rot = self.getRotation()
+ for _, obj in ipairs(zone.getObjects()) do
+ if obj.type == "Card" and obj.locked == false and not (obj.getVar("do_not_ready") or obj.hasTag("DoNotReady")) then
+ local cardRotation = obj.getRotation()
+ local roundedRotY = round(cardRotation.y, 0)
+ local yRotDiff = roundedRotY - rot.y
+
+ if yRotDiff < 0 then
+ yRotDiff = yRotDiff + 360
+ end
+
+ -- rotate cards to the next multiple of 90° towards 0°
+ local cardRotY = rot.y
+ if yRotDiff > 90 and yRotDiff <= 180 then
+ cardRotY = rot.y + 90
+ elseif yRotDiff > 180 and yRotDiff < 270 then
+ cardRotY = rot.y + 270
+ end
+
+ -- highlighting for readied cards
+ if cardRotY == rot.y and roundedRotY ~= rot.y then
+ obj.highlightOn({ r = 0.8, g = 1, b = 0.05 }, 2)
+ end
+
+ obj.setRotation(cardRotation:setAt("y", cardRotY))
+ end
+ end
+end
+
---------------------------------------------------------
-- functions for outside calls
---------------------------------------------------------
diff --git a/src/core/PlayAreaApi.ttslua b/src/core/PlayAreaApi.ttslua
index 47bba879..e7721106 100644
--- a/src/core/PlayAreaApi.ttslua
+++ b/src/core/PlayAreaApi.ttslua
@@ -105,7 +105,12 @@ do
-- Updates the surface of the play area
PlayAreaApi.updateSurface = function(url)
- return getPlayArea().call("updateSurface", url)
+ getPlayArea().call("updateSurface", url)
+ end
+
+ -- Readies cards in the PlayArea
+ PlayAreaApi.readyCards = function()
+ getPlayArea().call("readyCards")
end
-- Returns a deep copy of the currently tracked locations
diff --git a/src/playermat/Playermat.ttslua b/src/playermat/Playermat.ttslua
index 94f8cf60..86ccdb11 100644
--- a/src/playermat/Playermat.ttslua
+++ b/src/playermat/Playermat.ttslua
@@ -350,23 +350,22 @@ function doUpkeep(_, clickedByColor, isRightClick)
elseif obj.type == "Card" and not inArea(self.positionToLocal(obj.getPosition()), INVESTIGATOR_AREA) then
local cardMetadata = JSON.decode(obj.getGMNotes()) or {}
if not (obj.getVar("do_not_ready") or obj.hasTag("DoNotReady")) then
- local cardRotation = round(obj.getRotation().y, 0) - rot.y
- local yRotDiff = 0
+ local cardRotation = obj.getRotation()
+ local yRotDiff = round(cardRotation.y, 0) - rot.y
- if cardRotation < 0 then
- cardRotation = cardRotation + 360
+ if yRotDiff < 0 then
+ yRotDiff = yRotDiff + 360
end
-- rotate cards to the next multiple of 90° towards 0°
- if cardRotation > 90 and cardRotation <= 180 then
- yRotDiff = 90
- elseif cardRotation < 270 and cardRotation > 180 then
- yRotDiff = 270
+ local cardRotY = rot.y
+ if yRotDiff > 90 and yRotDiff <= 180 then
+ cardRotY = rot.y + 90
+ elseif yRotDiff > 180 and yRotDiff < 270 then
+ cardRotY = rot.y + 270
end
- -- set correct rotation for face-down cards
- rot.z = obj.is_face_down and 180 or 0
- obj.setRotation({ rot.x, rot.y + yRotDiff, rot.z })
+ obj.setRotation(cardRotation:setAt("y", cardRotY))
end
-- detect Forced Learning to handle card drawing accordingly
diff --git a/xml/MythosArea.xml b/xml/MythosArea.xml
index 356838c1..15ac038a 100644
--- a/xml/MythosArea.xml
+++ b/xml/MythosArea.xml
@@ -1,4 +1,4 @@
-
@@ -7,5 +7,6 @@
textColors="#ffffff|#88e3cf|#4f8478"
font="font_teutonic-arkham"
fontSize="62"
+ textAlignment="MiddleCenter"
onClick="reshuffleEncounterDeck">Reshuffle ➡
diff --git a/xml/PlayArea.xml b/xml/PlayArea.xml
new file mode 100644
index 00000000..6fd686f0
--- /dev/null
+++ b/xml/PlayArea.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
\ No newline at end of file