Merge branch 'argonui:main' into token-stack

This commit is contained in:
dscarpac 2024-07-06 01:28:18 -05:00 committed by GitHub
commit 07fdfface2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 3761 additions and 243 deletions

View File

@ -3,7 +3,6 @@
"ComponentTags_path": "ComponentTags.json", "ComponentTags_path": "ComponentTags.json",
"CustomUIAssets_path": "CustomUIAssets.json", "CustomUIAssets_path": "CustomUIAssets.json",
"DecalPallet_path": "DecalPallet.json", "DecalPallet_path": "DecalPallet.json",
"Decals": [],
"GameComplexity": "", "GameComplexity": "",
"GameMode": "Arkham Horror LCG - Super Complete Edition", "GameMode": "Arkham Horror LCG - Super Complete Edition",
"GameType": "", "GameType": "",
@ -84,6 +83,7 @@
"Trash.5f896a", "Trash.5f896a",
"Trash.147e80", "Trash.147e80",
"Trash.f7b6c8", "Trash.f7b6c8",
"PatchNotes.f47225",
"RulesReference.d99993", "RulesReference.d99993",
"LatestFAQ.faqfaq", "LatestFAQ.faqfaq",
"Doomtokens.16724b", "Doomtokens.16724b",
@ -207,7 +207,6 @@
"Tokencache_Curse.16a9a7", "Tokencache_Curse.16a9a7",
"Tokencache_Frost.b2b7be", "Tokencache_Frost.b2b7be",
"PhysicsDetector.b300d8", "PhysicsDetector.b300d8",
"ArkhamSCE390-06302024-Page1.bd6b3e",
"Neutral.834ad5", "Neutral.834ad5",
"Neutral.a84ae4", "Neutral.a84ae4",
"Neutral.762df8", "Neutral.762df8",

View File

@ -1,137 +0,0 @@
{
"AltLookAngle": {
"x": 0,
"y": 0,
"z": 0
},
"Autoraise": true,
"ColorDiffuse": {
"b": 1,
"g": 1,
"r": 1
},
"Description": "Thanks for downloading Arkham SCE 3.9.0!\n\n- Added confirmation dialog for discard hotkey (e.g. for locations)\r\n- Added new action / ability tokens\r\n- Added automated discarding for Patrice\r\n- Added new option to enable all card helpers\r\n- Added new option to load class-specific playermats\r",
"DragSelectable": true,
"GMNotes": "",
"GUID": "bd6b3e",
"Grid": true,
"GridProjection": false,
"Hands": false,
"HideWhenFaceDown": false,
"IgnoreFoW": false,
"LayoutGroupSortIndex": 0,
"Locked": false,
"LuaScript": "",
"LuaScriptState": "",
"MeasureMovement": false,
"Name": "Notecard",
"Nickname": "Arkham SCE 3.9.0 - 06/30/2024 - Page 1",
"Snap": true,
"States": {
"2": {
"AltLookAngle": {
"x": 0,
"y": 0,
"z": 0
},
"Autoraise": true,
"ColorDiffuse": {
"b": 1,
"g": 1,
"r": 1
},
"Description": "\n- Performed a small clean up of the bottom corners of the table\r\n- Updated 'Additional Cards Bag' / 'Player Card Panel' with better handling for fan-made cards\r\n- Updated Clean Up Helper, Drawing Tool, Hand Helper and Search Assistant\r\n- Updated Token Arranger",
"DragSelectable": true,
"GMNotes": "",
"GUID": "522604",
"Grid": true,
"GridProjection": false,
"Hands": false,
"HideWhenFaceDown": false,
"IgnoreFoW": false,
"LayoutGroupSortIndex": 0,
"Locked": false,
"LuaScript": "",
"LuaScriptState": "",
"MeasureMovement": false,
"Name": "Notecard",
"Nickname": "Arkham SCE 3.9.0 - 06/30/2024 - Page 2",
"Snap": true,
"Sticky": true,
"Tooltip": true,
"Transform": {
"posX": -27,
"posY": 1.551,
"posZ": -56.165,
"rotX": 0,
"rotY": 90,
"rotZ": 0,
"scaleX": 3,
"scaleY": 1,
"scaleZ": 3
},
"Value": 0,
"XmlUI": ""
},
"3": {
"AltLookAngle": {
"x": 0,
"y": 0,
"z": 0
},
"Autoraise": true,
"ColorDiffuse": {
"b": 1,
"g": 1,
"r": 1
},
"Description": "\n- Implemented menu to redraw tokens for specific cards like Heavy Furs and Wendy Adams\r\n- Bugfix for attempting to draw an encounter card while there is no deck\r\n- Bugfix for Navigation Overlay: now checks if playmat is occupied\r\n- Bugfix for Phase Tracker broadcasting\r\n- Performance improvements",
"DragSelectable": true,
"GMNotes": "",
"GUID": "522877",
"Grid": true,
"GridProjection": false,
"Hands": false,
"HideWhenFaceDown": false,
"IgnoreFoW": false,
"LayoutGroupSortIndex": 0,
"Locked": false,
"LuaScript": "",
"LuaScriptState": "",
"MeasureMovement": false,
"Name": "Notecard",
"Nickname": "Arkham SCE 3.9.0 - 06/30/2024 - Page 3",
"Snap": true,
"Sticky": true,
"Tooltip": true,
"Transform": {
"posX": -27,
"posY": 1.551,
"posZ": -56.165,
"rotX": 0,
"rotY": 90,
"rotZ": 0,
"scaleX": 3,
"scaleY": 1,
"scaleZ": 3
},
"Value": 0,
"XmlUI": ""
}
},
"Sticky": true,
"Tooltip": true,
"Transform": {
"posX": -27,
"posY": 1.551,
"posZ": -56.165,
"rotX": 0,
"rotY": 90,
"rotZ": 0,
"scaleX": 3,
"scaleY": 1,
"scaleZ": 3
},
"Value": 0,
"XmlUI": ""
}

View File

@ -0,0 +1,113 @@
{
"AltLookAngle": {
"x": 0,
"y": 0,
"z": 0
},
"AttachedDecals": [
{
"CustomDecal": {
"ImageURL": "http://cloud-3.steamusercontent.com/ugc/2501268517218943111/803E57A7B3E9765DF342050EE6C71D69473A7388/",
"Name": "Image #1",
"Size": 1
},
"Transform": {
"posX": -0.93,
"posY": 0.105,
"posZ": 0.66,
"rotX": 90,
"rotY": 180,
"rotZ": 0,
"scaleX": 0.6,
"scaleY": 0.6,
"scaleZ": 1
}
},
{
"CustomDecal": {
"ImageURL": "http://cloud-3.steamusercontent.com/ugc/2037357792052848566/5DA900C430E97D3DFF2C9B8A3DB1CB2271791FC7/",
"Name": "Image #2",
"Size": 1
},
"Transform": {
"posX": -1.05,
"posY": 0.105,
"posZ": -0.567,
"rotX": 90,
"rotY": 205,
"rotZ": 0,
"scaleX": 0.3,
"scaleY": 0.3,
"scaleZ": 1
}
},
{
"CustomDecal": {
"ImageURL": "http://cloud-3.steamusercontent.com/ugc/2501268517219098388/0936FEE03B410319658B5E05DB5D486CEDDE98F5/",
"Name": "Image #3",
"Size": 1
},
"Transform": {
"posX": 0,
"posY": 0.105,
"posZ": -0.81,
"rotX": 90,
"rotY": 180,
"rotZ": 0,
"scaleX": 2.4,
"scaleY": 0.009,
"scaleZ": 1
}
}
],
"Autoraise": true,
"ColorDiffuse": {
"b": 1,
"g": 1,
"r": 1
},
"CustomImage": {
"CustomTile": {
"Stackable": false,
"Stretch": true,
"Thickness": 0.1,
"Type": 0
},
"ImageScalar": 1,
"ImageSecondaryURL": "http://sfwallpaper.com/images/parchment-paper-wallpaper-10.jpg",
"ImageURL": "http://sfwallpaper.com/images/parchment-paper-wallpaper-10.jpg",
"WidthScale": 0
},
"Description": "Thanks for downloading! We're happy to present you a rather big update this time :-)\n\nNew things\n- automated discarding for Patrice\n- confirmation dialog for discard hotkey (e.g. for locations)\n- helpers for cards that redraw tokens and Kohaku\n- displaying of token count for cards that seal tokens\r\n- new action / ability tokens (replacing the old ones)\r\n- option to enable all card helpers (e.g. Heavy Furs)\r\n- option to load class-colored playermat backgrounds\n- coloring for player names in broadcasts\n- right-click option for RBW button on Player Card Panel to specify trait(s)\n\nUpdates\r\n- performed a small clean up of the bottom corners of the table\n- \"Numpad 9\" to rearranges present tokens (on top of adding a resource)\n- Scroll of Secrets context menu helper now displays player names instead of colors\r\n- Player Card Panel can display fan-made cards with a new \"custom\" cycle button)\n- \"Discard object\" gamekey works for selected objects\r\n- updated a bunch of tools like Clean Up Helper, Drawing Tool,\nHand Helper, Token Arranger and Search Assistant\n\nFixes\r\r\n- Bugfix for attempting to draw an encounter card while there is no deck\r\n- Bugfix for Navigation Overlay: now checks if playmat is occupied\r\n- Bugfix for Phase Tracker broadcasting\r\n- Performance and file size improvements (e.g. by adding download\nfunctions for CYOA campaign guides and Arkham Fantasy standees)",
"DragSelectable": true,
"GMNotes": "",
"GUID": "f47225",
"Grid": true,
"GridProjection": false,
"Hands": false,
"HideWhenFaceDown": false,
"IgnoreFoW": false,
"LayoutGroupSortIndex": 0,
"Locked": false,
"LuaScriptState_path": "PatchNotes.f47225.luascriptstate",
"LuaScript_path": "PatchNotes.f47225.ttslua",
"MeasureMovement": false,
"Name": "Custom_Tile",
"Nickname": "Patch Notes",
"Snap": true,
"Sticky": true,
"Tooltip": true,
"Transform": {
"posX": -27,
"posY": 1.481,
"posZ": -56.165,
"rotX": 0,
"rotY": 270,
"rotZ": 0,
"scaleX": 7.5,
"scaleY": 1,
"scaleZ": 7.5
},
"Value": 0,
"XmlUI": ""
}

View File

@ -0,0 +1 @@
{"checks":[],"decals":[{"locked":false,"name":"Arkham SCE logo","pos":{"x":3.1,"y":2.2},"rotation":0,"scale":{"x":"2","y":"2"},"tooltip":"None","url":"http://cloud-3.steamusercontent.com/ugc/2501268517218943111/803E57A7B3E9765DF342050EE6C71D69473A7388/"},{"locked":false,"name":"Bootlegger Finn","pos":{"x":3.5,"y":-1.89},"rotation":"25","scale":{"x":"1","y":"1"},"tooltip":"None","url":"http://cloud-3.steamusercontent.com/ugc/2037357792052848566/5DA900C430E97D3DFF2C9B8A3DB1CB2271791FC7/"},{"locked":false,"name":"black bar","pos":{"x":0,"y":-2.7},"rotation":0,"scale":{"x":"8","y":"0.03"},"tooltip":"None","url":"http://cloud-3.steamusercontent.com/ugc/2501268517219098388/0936FEE03B410319658B5E05DB5D486CEDDE98F5/"}],"fields":[{"align":3,"array":{"x":"1","y":"1"},"counter":"False","distance":{"x":"1","y":"1"},"fieldColor":{"a":0,"b":1,"g":1,"r":1},"font":"200","locked":false,"name":"Patch Notes","pos":{"x":"0","y":-2.9},"role":"Normal Field","size":{"x":"3750","y":"250"},"textColor":{"a":1,"b":0,"g":0,"r":0},"tooltip":"None","value":["Arkham Horror LCG SCE 3.9.0 - 07/05/2024"]},{"align":2,"array":{"x":"1","y":1},"distance":{"x":"1","y":"1"},"fieldColor":{"a":0,"b":1,"g":1,"r":1},"font":"90","locked":false,"name":"Details","pos":{"x":"0","y":0.4},"role":"Set object's description","size":{"x":"3750","y":"2750"},"textColor":{"a":1,"b":0,"g":0,"r":0},"tooltip":"None","value":["Thanks for downloading! We're happy to present you a rather big update this time :-)\n\nNew things\n- automated discarding for Patrice\n- confirmation dialog for discard hotkey (e.g. for locations)\n- helpers for cards that redraw tokens and Kohaku\n- displaying of token count for cards that seal tokens\r\n- new action / ability tokens (replacing the old ones)\r\n- option to enable all card helpers (e.g. Heavy Furs)\r\n- option to load class-colored playermat backgrounds\n- coloring for player names in broadcasts\n- right-click option for RBW button on Player Card Panel to specify trait(s)\n\nUpdates\r\n- performed a small clean up of the bottom corners of the table\n- \"Numpad 9\" to rearranges present tokens (on top of adding a resource)\n- Scroll of Secrets context menu helper now displays player names instead of colors\r\n- Player Card Panel can display fan-made cards with a new \"custom\" cycle button)\n- \"Discard object\" gamekey works for selected objects\r\n- updated a bunch of tools like Clean Up Helper, Drawing Tool,\nHand Helper, Token Arranger and Search Assistant\n\nFixes\r\r\n- Bugfix for attempting to draw an encounter card while there is no deck\r\n- Bugfix for Navigation Overlay: now checks if playmat is occupied\r\n- Bugfix for Phase Tracker broadcasting\r\n- Performance and file size improvements (e.g. by adding download\nfunctions for CYOA campaign guides and Arkham Fantasy standees)"]}],"flip":"False","height":"0.1","locks":{"checks":false,"decals":false,"fields":false},"nudgeDistance":0.01,"scale":{"x":"0.3","y":"0.3"},"sheetLocked":true}

File diff suppressed because it is too large Load Diff

View File

@ -284,7 +284,6 @@ end
-- maybe ignore cards / decks on the tekelili helper -- maybe ignore cards / decks on the tekelili helper
function maybeIgnoreTekeliliCards() function maybeIgnoreTekeliliCards()
local tekeliliHelper = getTekeliliHelper() local tekeliliHelper = getTekeliliHelper()
if tekeliliHelper then if tekeliliHelper then
removeIgnoreLater = searchLib.onObject(tekeliliHelper, "isCardOrDeck") removeIgnoreLater = searchLib.onObject(tekeliliHelper, "isCardOrDeck")
for _, obj in ipairs(removeIgnoreLater) do for _, obj in ipairs(removeIgnoreLater) do
@ -295,10 +294,7 @@ end
-- clean up for play area -- clean up for play area
function tidyPlayareaCoroutine() function tidyPlayareaCoroutine()
-- small wait to allow other operations to finish coWaitFrames(10)
for k = 1, 10 do
coroutine.yield(0)
end
local trash = guidReferenceApi.getObjectByOwnerAndType("Mythos", "Trash") local trash = guidReferenceApi.getObjectByOwnerAndType("Mythos", "Trash")
local playAreaZone = guidReferenceApi.getObjectByOwnerAndType("Mythos", "PlayAreaZone") local playAreaZone = guidReferenceApi.getObjectByOwnerAndType("Mythos", "PlayAreaZone")
@ -333,43 +329,46 @@ function tidyPlayerMatCoroutine()
if getOptionValue() then if getOptionValue() then
for _, color in ipairs(COLORS) do for _, color in ipairs(COLORS) do
-- delay for animation purpose
for k = 1, 20 do
coroutine.yield(0)
end
-- get respective trash
local trash = guidReferenceApi.getObjectByOwnerAndType(color, "Trash") local trash = guidReferenceApi.getObjectByOwnerAndType(color, "Trash")
if trash == nil then if trash == nil then
printToAll("Trashcan for " .. color .. " playermat could not be found! Skipping this playermat.", "Yellow") printToAll("Trashcan for " .. color .. " playermat could not be found! Skipping this playermat.", "Yellow")
goto continue else
end coWaitFrames(20)
-- maybe store tekelili cards -- maybe store tekelili cards
if tekeliliHelper then if tekeliliHelper then
tekeliliHelper.call("storeTekelili", color) tekeliliHelper.call("storeTekelili", color)
end end
-- remove objects (with exceptions) -- parse playermat objects
for _, obj in ipairs(playermatApi.searchAroundPlayermat(color)) do for _, obj in ipairs(playermatApi.searchAroundPlayermat(color)) do
maybeTrashObject(obj, trash) -- reset action tokens
end if obj.hasTag("UniversalToken") and obj.is_face_down then
obj.flip()
end
-- reset "activeInvestigatorId" and "...class" -- get rid of temporary tokens
local mat = guidReferenceApi.getObjectByOwnerAndType(color, "Playermat") if obj.hasTag("Temporary") then
mat.setVar("activeInvestigatorId", "00000") trash.putObject(obj)
mat.setVar("activeInvestigatorClass", "Neutral") end
mat.call("updateTexture")
for k = 1, 5 do -- remove objects (with exceptions)
coroutine.yield(0) maybeTrashObject(obj, trash)
end end
-- maybe respawn tekelili cards -- reset "activeInvestigatorId" and "...class"
if tekeliliHelper then local mat = guidReferenceApi.getObjectByOwnerAndType(color, "Playermat")
tekeliliHelper.call("spawnStoredTekelili", color) mat.setVar("activeInvestigatorId", "00000")
mat.setVar("activeInvestigatorClass", "Neutral")
mat.call("updateTexture")
coWaitFrames(5)
-- maybe respawn tekelili cards
if tekeliliHelper then
tekeliliHelper.call("spawnStoredTekelili", color)
end
end end
::continue::
end end
end end
@ -431,3 +430,10 @@ function getOptionValue()
return options["tidyPlayermats"] return options["tidyPlayermats"]
end end
end end
-- pauses the current coroutine for 'frameCount' frames
function coWaitFrames(frameCount)
for k = 1, frameCount do
coroutine.yield(0)
end
end

View File

@ -176,6 +176,17 @@ function getOwnerOfObject(object)
end end
end end
-- check if the object is in a handzone
for owner, subtable in pairs(GuidReferences) do
for type, guid in pairs(subtable) do
for _, zone in ipairs(object.getZones()) do
if guid == zone.getGUID() then
return owner
end
end
end
end
-- check if it is on an owned object -- check if it is on an owned object
local result = searchLib.belowPosition(object.getPosition()) local result = searchLib.belowPosition(object.getPosition())

View File

@ -1,11 +1,11 @@
local blessCurseManagerApi = require("chaosbag/BlessCurseManagerApi") local blessCurseManagerApi = require("chaosbag/BlessCurseManagerApi")
local guidReferenceApi = require("core/GUIDReferenceApi") local guidReferenceApi = require("core/GUIDReferenceApi")
local mythosAreaApi = require("core/MythosAreaApi") local mythosAreaApi = require("core/MythosAreaApi")
local navigationOverlayApi = require("core/NavigationOverlayApi") local navigationOverlayApi = require("core/NavigationOverlayApi")
local optionPanelApi = require("core/OptionPanelApi") local optionPanelApi = require("core/OptionPanelApi")
local playermatApi = require("playermat/PlayermatApi") local playermatApi = require("playermat/PlayermatApi")
local searchLib = require("util/SearchLib") local searchLib = require("util/SearchLib")
local victoryDisplayApi = require("core/VictoryDisplayApi") local victoryDisplayApi = require("core/VictoryDisplayApi")
function onLoad() function onLoad()
addHotkey("Add doom to agenda", addDoomToAgenda) addHotkey("Add doom to agenda", addDoomToAgenda)
@ -75,15 +75,19 @@ function takeCardIntoThreatArea(playerColor, hoveredObject)
local mat = guidReferenceApi.getObjectByOwnerAndType(matColor, "Playermat") local mat = guidReferenceApi.getObjectByOwnerAndType(matColor, "Playermat")
-- do not continue if the threat area is already full -- do not continue if the threat area is already full
if playermatApi.getEncounterCardDrawPosition(matColor, false) == playermatApi.getEncounterCardDrawPosition(matColor, true) then local threatAreaPos = playermatApi.getEncounterCardDrawPosition(matColor, false)
if threatAreaPos == playermatApi.getEncounterCardDrawPosition(matColor, true) then
broadcastToColor("Threat area is full.", playerColor, "Yellow") broadcastToColor("Threat area is full.", playerColor, "Yellow")
return return
end end
-- initialize list of objects to move -- initialize list of objects to move (and store local positions)
local moveTheseObjects = {} local additionalObjects = {}
for _, obj in ipairs(searchLib.onObject(hoveredObject, "isTileOrToken")) do for _, obj in ipairs(searchLib.onObject(hoveredObject, "isTileOrToken")) do
table.insert(moveTheseObjects, obj) local data = {}
data.object = obj
data.localPos = hoveredObject.positionToLocal(obj.getPosition())
table.insert(additionalObjects, data)
end end
-- find out if the original card is on the green or red playermats -- find out if the original card is on the green or red playermats
@ -97,29 +101,25 @@ function takeCardIntoThreatArea(playerColor, hoveredObject)
modifierY = -90 modifierY = -90
end 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 = playermatApi.getEncounterCardDrawPosition(matColor, false)
hoveredObject.setPosition(pos)
hoveredObject.setRotation(hoveredObject.getRotation() - Vector(0, 270 - mat.getRotation().y - modifierY, 0))
local cardName = hoveredObject.getName() local cardName = hoveredObject.getName()
if cardName == nil or cardName == "" then if cardName == "" then cardName = "card" end
cardName = "card(s)" broadcastToAll("Moved " .. cardName .. " to " .. getColoredName(playerColor) .. "'s threat area.", "White")
end
broadcastToAll("Placed " .. cardName .. " into threat area.", "White")
for i, obj in ipairs(moveTheseObjects) do -- get new rotation (rounded)
if not obj.locked then local cardRot = hoveredObject.getRotation()
local globalPos = hoveredObject.positionToWorld(localPositions[i]) local roundedRotY = roundToMultiple(cardRot.y, 45)
obj.setPosition(globalPos) local deltaRotY = 270 - mat.getRotation().y - modifierY
obj.setRotation(obj.getRotation() - Vector(0, 270 - mat.getRotation().y - modifierY, 0)) local newCardRot = cardRot:setAt("y", roundedRotY - deltaRotY)
-- move the main card to threat area
hoveredObject.setRotation(newCardRot)
hoveredObject.setPosition(threatAreaPos)
-- move tokens/tiles (to new global position)
for _, data in ipairs(additionalObjects) do
if not data.object.locked then
data.object.setPosition(hoveredObject.positionToWorld(data.localPos))
data.object.setRotation(data.object.getRotation() - Vector(0, deltaRotY, 0))
end end
end end
end end
@ -131,7 +131,7 @@ function discardObject(playerColor, hoveredObject)
if #selectedObjects > 0 then if #selectedObjects > 0 then
discardGroup(playerColor, selectedObjects) discardGroup(playerColor, selectedObjects)
return return
-- only continue if an unlocked card, deck or tile was hovered -- only continue if an unlocked card, deck or tile was hovered
elseif hoveredObject == nil elseif hoveredObject == nil
or (hoveredObject.type ~= "Card" and hoveredObject.type ~= "Deck" and hoveredObject.type ~= "Tile") or (hoveredObject.type ~= "Card" and hoveredObject.type ~= "Deck" and hoveredObject.type ~= "Tile")
or hoveredObject.locked then or hoveredObject.locked then
@ -174,11 +174,11 @@ function discardGroup(playerColor, selectedObjects)
local count = #selectedObjects local count = #selectedObjects
-- discarding one at a time avoids an error with cards in the discard pile losing the 'hands' toggle and uses multiple mats -- discarding one at a time avoids an error with cards in the discard pile losing the 'hands' toggle and uses multiple mats
for i = count, 1, -1 do for i = count, 1, -1 do
Wait.time(function() Wait.time(function()
if (selectedObjects[i].type == "Card" or selectedObjects[i].type ~= "Deck" or selectedObjects[i].type == "Tile") then if (selectedObjects[i].type == "Card" or selectedObjects[i].type ~= "Deck" or selectedObjects[i].type == "Tile") then
performDiscard(playerColor, selectedObjects[i]) performDiscard(playerColor, selectedObjects[i])
end end
end, (count - i + 1) * 0.1) end, (count - i + 1) * 0.1)
end end
end end
@ -503,3 +503,7 @@ function getColoredName(playerColor)
-- add bb-code -- add bb-code
return "[" .. Color.fromString(playerColor):toHex() .. "]" .. displayName .. "[-]" return "[" .. Color.fromString(playerColor):toHex() .. "]" .. displayName .. "[-]"
end end
function roundToMultiple(num, mult)
return math.floor((num + mult / 2) / mult) * mult
end

View File

@ -212,10 +212,14 @@ end
-- TTS event for objects that leave zones -- TTS event for objects that leave zones
function onObjectLeaveZone(zone, object) function onObjectLeaveZone(zone, object)
if zone.isDestroyed() or object.isDestroyed() then return end -- 1 frame delay to avoid error messages when exiting the game
if zone.type == "Hand" and object.hasTag("CardWithHelper") then Wait.frames(
object.call("updateDisplay") function()
end if zone.isDestroyed() or object.isDestroyed() then return end
if zone.type == "Hand" and object.hasTag("CardWithHelper") then
object.call("updateDisplay")
end
end, 1)
end end
-- handle card drawing via number typing for multihanded gameplay -- handle card drawing via number typing for multihanded gameplay
@ -224,15 +228,6 @@ function onObjectNumberTyped(hoveredObject, playerColor, number)
-- only continue for decks or cards -- only continue for decks or cards
if hoveredObject.type ~= "Deck" and hoveredObject.type ~= "Card" then return end if hoveredObject.type ~= "Deck" and hoveredObject.type ~= "Card" then return end
-- check whether the hovered object is part of a players draw objects
for _, color in ipairs(playermatApi.getUsedMatColors()) do
local deckAreaObjects = playermatApi.getDeckAreaObjects(color)
if deckAreaObjects.topCard == hoveredObject or deckAreaObjects.draw == hoveredObject then
playermatApi.drawCardsWithReshuffle(color, number)
return true
end
end
-- check if this is a card with states (and then change state instead of drawing it) -- check if this is a card with states (and then change state instead of drawing it)
local states = hoveredObject.getStates() local states = hoveredObject.getStates()
if states ~= nil and #states > 0 then if states ~= nil and #states > 0 then
@ -242,6 +237,15 @@ function onObjectNumberTyped(hoveredObject, playerColor, number)
return true return true
end end
end end
-- check whether the hovered object is part of a players draw objects
for _, color in ipairs(playermatApi.getUsedMatColors()) do
local deckAreaObjects = playermatApi.getDeckAreaObjects(color)
if deckAreaObjects.topCard == hoveredObject or deckAreaObjects.draw == hoveredObject then
playermatApi.drawCardsWithReshuffle(color, number)
return true
end
end
end end
-- TTS event, used to redraw the playermat slot symbols after a small delay to account for the custom font loading -- TTS event, used to redraw the playermat slot symbols after a small delay to account for the custom font loading
@ -249,8 +253,9 @@ function onPlayerConnect()
Wait.time(function() playermatApi.redrawSlotSymbols("All") end, 0.2) Wait.time(function() playermatApi.redrawSlotSymbols("All") end, 0.2)
end end
-- disable delete action (only applies to promoted players) and discard objects instead
function onPlayerAction(player, action, targets) function onPlayerAction(player, action, targets)
if action == Player.Action.Delete and player.admin == false then if action == Player.Action.Delete and not player.admin then
for _, target in ipairs(targets) do for _, target in ipairs(targets) do
local matColor = playermatApi.getMatColorByPosition(target.getPosition()) local matColor = playermatApi.getMatColorByPosition(target.getPosition())
local trash = guidReferenceApi.getObjectByOwnerAndType(matColor, "Trash") local trash = guidReferenceApi.getObjectByOwnerAndType(matColor, "Trash")
@ -1364,7 +1369,8 @@ function contentDownloadCallback(request, params)
if pos then if pos then
spawnTable.position = pos spawnTable.position = pos
else else
broadcastToAll("Please make space in the area below the tentacle stand in the upper middle of the table and try again.", "Red") broadcastToAll(
"Please make space in the area below the tentacle stand in the upper middle of the table and try again.", "Red")
return return
end end
end end
@ -1515,10 +1521,11 @@ function playermatRemovalSelected(player, selectedIndex, id)
if mat then if mat then
-- confirmation dialog about deletion -- confirmation dialog about deletion
player.pingTable(mat.getPosition()) player.pingTable(mat.getPosition())
player.showConfirmDialog("Do you really want to remove " .. matColor .. "'s playermat and related objects? This can't be reversed.", player.showConfirmDialog(
function() "Do you really want to remove " .. matColor .. "'s playermat and related objects? This can't be reversed.",
removePlayermat(matColor) function()
end) removePlayermat(matColor)
end)
else else
-- info dialog that it is already deleted -- info dialog that it is already deleted
player.showInfoDialog(matColor .. "'s playermat has already been removed.") player.showInfoDialog(matColor .. "'s playermat has already been removed.")
@ -1593,6 +1600,7 @@ function applyOptionPanelChange(id, state)
local counter = guidReferenceApi.getObjectByOwnerAndType("Mythos", "MasterClueCounter") local counter = guidReferenceApi.getObjectByOwnerAndType("Mythos", "MasterClueCounter")
counter.setVar("useClickableCounters", state) counter.setVar("useClickableCounters", state)
-- option: Enable card helpers
elseif id == "enableCardHelpers" then elseif id == "enableCardHelpers" then
toggleCardHelpers(state) toggleCardHelpers(state)

View File

@ -8,12 +8,12 @@ local tokenChecker = require("core/token/TokenChecker")
local tokenSpawnTrackerApi = require("core/token/TokenSpawnTrackerApi") local tokenSpawnTrackerApi = require("core/token/TokenSpawnTrackerApi")
local ENCOUNTER_DECK_AREA = { local ENCOUNTER_DECK_AREA = {
upperLeft = { x = 0.9, z = 0.42 }, upperLeft = { x = 1.05, z = 0.15 },
lowerRight = { x = 0.86, z = 0.38 } lowerRight = { x = 0.70, z = 0.59 }
} }
local ENCOUNTER_DISCARD_AREA = { local ENCOUNTER_DISCARD_AREA = {
upperLeft = { x = 1.62, z = 0.42 }, upperLeft = { x = 1.77, z = 0.15 },
lowerRight = { x = 1.58, z = 0.38 } lowerRight = { x = 1.42, z = 0.59 }
} }
-- global position of encounter deck and discard pile -- global position of encounter deck and discard pile
@ -45,7 +45,7 @@ end
-- collison and container event handling -- collison and container event handling
--------------------------------------------------------- ---------------------------------------------------------
-- TTS event handler. Handles scenario name event triggering and encounter card token resets. -- TTS event handler. Handles scenario name event triggering and encounter card token resets.
function onCollisionEnter(collisionInfo) function onCollisionEnter(collisionInfo)
if not collisionEnabled then return end if not collisionEnabled then return end
@ -240,18 +240,16 @@ end
function inArea(point, bounds) function inArea(point, bounds)
return (point.x < bounds.upperLeft.x return (point.x < bounds.upperLeft.x
and point.x > bounds.lowerRight.x and point.x > bounds.lowerRight.x
and point.z < bounds.upperLeft.z and point.z > bounds.upperLeft.z
and point.z > bounds.lowerRight.z) and point.z < bounds.lowerRight.z)
end end
-- removes tokens from the provided card/deck -- removes tokens from the provided card/deck
function removeTokensFromObject(object) function removeTokensFromObject(object)
local TRASH = guidReferenceApi.getObjectByOwnerAndType("Mythos", "Trash") local TRASH = guidReferenceApi.getObjectByOwnerAndType("Mythos", "Trash")
for _, obj in ipairs(searchLib.onObject(object)) do for _, obj in ipairs(searchLib.onObject(object, "isTileOrToken")) do
if obj.getGUID() ~= "4ee1f2" and -- table if obj.getGUID() ~= "4ee1f2" and -- table
obj ~= self and obj ~= self and
obj.type ~= "Deck" and
obj.type ~= "Card" and
obj.memo ~= nil and obj.memo ~= nil and
obj.getLock() == false and obj.getLock() == false and
not tokenChecker.isChaosToken(obj) then not tokenChecker.isChaosToken(obj) then

View File

@ -128,6 +128,8 @@ function onLoad(savedData)
slotData = loadedData.slotData slotData = loadedData.slotData
end end
updateMessageColor(playerColor)
self.interactable = false self.interactable = false
-- get object references to owned objects -- get object references to owned objects

View File

@ -30,7 +30,7 @@ do
max_distance = maxDistance or 0 max_distance = maxDistance or 0
}) })
-- filtering the result -- filter the result for matching objects
local objList = {} local objList = {}
for _, v in ipairs(searchResult) do for _, v in ipairs(searchResult) do
if not filter or filterFunc(v.hit_object) then if not filter or filterFunc(v.hit_object) then
@ -47,22 +47,22 @@ do
-- searches the area on an object -- searches the area on an object
SearchLib.onObject = function(obj, filter) SearchLib.onObject = function(obj, filter)
pos = obj.getPosition() local pos = obj.getPosition()
size = obj.getBounds().size:setAt("y", 1) local size = obj.getBounds().size:setAt("y", 1)
return returnSearchResult(pos, _, size, filter) return returnSearchResult(pos, _, size, filter)
end end
-- searches the specified position (a single point) -- searches the specified position (a single point)
SearchLib.atPosition = function(pos, filter) SearchLib.atPosition = function(pos, filter)
size = { 0.1, 2, 0.1 } local size = { 0.1, 2, 0.1 }
return returnSearchResult(pos, _, size, filter) return returnSearchResult(pos, _, size, filter)
end end
-- searches below the specified position (downwards until y = 0) -- searches below the specified position (downwards until y = 0)
SearchLib.belowPosition = function(pos, filter) SearchLib.belowPosition = function(pos, filter)
size = { 0.1, 2, 0.1 } local size = { 0.1, 2, 0.1 }
direction = { 0, -1, 0 } local direction = { 0, -1, 0 }
maxDistance = pos.y local maxDistance = pos.y
return returnSearchResult(pos, _, size, filter, direction, maxDistance) return returnSearchResult(pos, _, size, filter, direction, maxDistance)
end end