From f66598ab9241ccc0815aa4dc6588f0ddda75cf8d Mon Sep 17 00:00:00 2001 From: Chr1Z93 Date: Sun, 15 Dec 2024 20:14:54 +0100 Subject: [PATCH 1/5] Re-added token attaching from Yumi --- src/core/Global.ttslua | 82 ++++++++++++++++++++++++++++++---- src/core/GlobalApi.ttslua | 6 +++ src/mythos/MythosArea.ttslua | 1 + src/playermat/Playermat.ttslua | 1 + 4 files changed, 81 insertions(+), 9 deletions(-) diff --git a/src/core/Global.ttslua b/src/core/Global.ttslua index 782935778..e0cb389c8 100644 --- a/src/core/Global.ttslua +++ b/src/core/Global.ttslua @@ -75,6 +75,7 @@ local blurseVisibility = {} -- track cards' tokens local cardTokens = {} +local cardSettings = {} --------------------------------------------------------- -- data for tokens @@ -208,6 +209,8 @@ function tryObjectEnterContainer(container, object) -- stop mini cards from forming decks if object.hasTag("Minicard") and container.hasTag("Minicard") then return false + elseif object.type == "Card" and object.getName() ~= "Atlach-Nacha" then + handleTokenDetaching({ card = object }) end playAreaApi.tryObjectEnterContainer(container, object) @@ -300,15 +303,22 @@ function onObjectNumberTyped(hoveredObject, playerColor, number) end end --- disable delete action (only applies to promoted players) and discard objects instead function onPlayerAction(player, action, targets) if action == Player.Action.Delete and not player.admin then + -- disable delete action (only applies to promoted players) and discard objects instead for _, target in ipairs(targets) do local matColor = playermatApi.getMatColorByPosition(target.getPosition()) local trash = guidReferenceApi.getObjectByOwnerAndType(matColor, "Trash") trash.putObject(target) end return false + elseif action == Player.Action.PickUp then + -- attach tokens to each card -> might need to add a limit if performance is an issue + for _, target in ipairs(targets) do + if target.type == "Card" then + handleTokenAttaching({ player = player, card = target }) + end + end end end @@ -2858,18 +2868,73 @@ function moveAndRotatePlayermat(params) playermatApi.moveAndRotate(params.matColor, params.position, params.rotationY) end --- check if an element is in a table -function tableContains(thisTable, thisElement) - for _, element in pairs(thisTable) do - if element == thisElement then - return true +function handleTokenAttaching(params) + local card = params.card + local player = params.player + local searchResult = searchLib.onObject(card, "isTileOrToken", 0.95) + + if card.is_face_down and next(searchResult) ~= nil then + cardSettings[card] = { + hideFacedown = card.hide_when_face_down, + tooltip = card.tooltip + } + card.hide_when_face_down = false + card.tooltip = false + end + + for _, token in ipairs(searchResult) do + if not token.locked then + card.addAttachment(token) end end - return false + + Wait.condition( + function() + if card ~= nil then + handleTokenDetaching({ card = card }) + end + end, + function() + if card ~= nil and player ~= nil and player.seated then + return card.resting and card.held_by_color ~= player.color + else + return true + end + end + ) end -function moveCardWithTokens(params) +function handleTokenDetaching(params) local card = params.card + if card == nil or next(card.getAttachments()) == nil then return end + + -- restore card settings + if cardSettings[card] ~= nil then + card.hide_when_face_down = cardSettings[card]["hideFacedown"] + card.tooltip = cardSettings[card]["tooltip"] + cardSettings[card] = nil + end + + -- remove attachments (move tokens below the card on top) + local removedTokens = card.removeAttachments() + for _, token in ipairs(removedTokens) do + if token.getPosition().y < card.getPosition().y then + local posY = card.getPosition().y + 0.05 + token.setPosition(token.getPosition():setAt("y", posY)) + end + end + + -- redraw token xml for cards with sealing + if card.hasTag("CardThatSeals") then + local func = card.getVar("updateStackSize") -- make sure function exists + if func ~= nil then + card.call("updateStackSize") + end + end +end + +function moveCardWithTokens(params) + local card = params.card local position = params.position local rotation = params.rotation @@ -2895,7 +2960,6 @@ function moveCardWithTokens(params) updateTokenTransform(card) return card.resting and not card.isSmoothMoving() end - return true end ) diff --git a/src/core/GlobalApi.ttslua b/src/core/GlobalApi.ttslua index e39a64d91..451e4290a 100644 --- a/src/core/GlobalApi.ttslua +++ b/src/core/GlobalApi.ttslua @@ -68,6 +68,12 @@ do Global.call("moveCardWithTokens", { card = card, position = position, rotation = rotation }) end + -- handles token detaching for cards + ---@param card tts__Object Card that should get tokens detached + function GlobalApi.handleTokenDetaching(card) + Global.call("handleTokenDetaching", { card = card }) + end + -- loads saved options ---@param options table Set a new state for the option table function GlobalApi.loadOptionPanelSettings(options) diff --git a/src/mythos/MythosArea.ttslua b/src/mythos/MythosArea.ttslua index b52998ab4..e378d4ff2 100644 --- a/src/mythos/MythosArea.ttslua +++ b/src/mythos/MythosArea.ttslua @@ -104,6 +104,7 @@ function onCollisionEnter(collisionInfo) if inArea(localPos, ENCOUNTER_DECK_AREA) or inArea(localPos, ENCOUNTER_DISCARD_AREA) then -- reset spawned tokens and remove tokens from cards in encounter deck / discard area Wait.frames(function() tokenSpawnTrackerApi.resetTokensSpawned(object) end, 1) + GlobalApi.handleTokenDetaching(object) GlobalApi.removeTokensFromObject(object, "Mythos") elseif inArea(localPos, SCENARIO_REFERENCE_AREA) then diff --git a/src/playermat/Playermat.ttslua b/src/playermat/Playermat.ttslua index e4221920a..a2623d5d3 100644 --- a/src/playermat/Playermat.ttslua +++ b/src/playermat/Playermat.ttslua @@ -1299,6 +1299,7 @@ function onCollisionEnter(collisionInfo) -- encounter types / committed skill cards in the threat area if inArea(localCardPos, THREAT_AREA) and (md.type == "Treachery" or md.type == "Enemy" or md.type == "Skill" or md.weakness) then + GlobalApi.handleTokenDetaching(object) spawnTokensOrShowHelper(object) end end From fc6ce3d3aeb942a1de7a31aa4250e58969c81877 Mon Sep 17 00:00:00 2001 From: Chr1Z93 Date: Mon, 16 Dec 2024 22:11:08 +0100 Subject: [PATCH 2/5] Mini card exclusion --- src/core/Global.ttslua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/Global.ttslua b/src/core/Global.ttslua index e0cb389c8..8cca040a7 100644 --- a/src/core/Global.ttslua +++ b/src/core/Global.ttslua @@ -315,7 +315,7 @@ function onPlayerAction(player, action, targets) elseif action == Player.Action.PickUp then -- attach tokens to each card -> might need to add a limit if performance is an issue for _, target in ipairs(targets) do - if target.type == "Card" then + if target.type == "Card" and not target.hasTag("Minicard") then handleTokenAttaching({ player = player, card = target }) end end From e0701bc53de0f070b01e5028bea9d266a1273983 Mon Sep 17 00:00:00 2001 From: Chr1Z93 Date: Wed, 18 Dec 2024 21:42:29 +0100 Subject: [PATCH 3/5] updated code --- src/core/Global.ttslua | 10 +++++----- src/playermat/Playermat.ttslua | 3 ++- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/core/Global.ttslua b/src/core/Global.ttslua index d48720c66..be7b155f0 100644 --- a/src/core/Global.ttslua +++ b/src/core/Global.ttslua @@ -2891,6 +2891,8 @@ end function handleTokenAttaching(params) local card = params.card + if card == nil then return end + local player = params.player local searchResult = searchLib.onObject(card, "isTileOrToken", 0.95) @@ -2910,11 +2912,7 @@ function handleTokenAttaching(params) end Wait.condition( - function() - if card ~= nil then - handleTokenDetaching({ card = card }) - end - end, + function() handleTokenDetaching({ card = card }) end, function() if card ~= nil and player ~= nil and player.seated then return card.resting and card.held_by_color ~= player.color @@ -3031,6 +3029,8 @@ end -- removes tokens from the provided card/deck function removeTokensFromObject(params) local object = params.object + if object == nil then return end + local trash = guidReferenceApi.getObjectByOwnerAndType(params.owner, "Trash") if object.hasTag("CardThatSeals") then diff --git a/src/playermat/Playermat.ttslua b/src/playermat/Playermat.ttslua index a2623d5d3..3e9f1a98a 100644 --- a/src/playermat/Playermat.ttslua +++ b/src/playermat/Playermat.ttslua @@ -1269,6 +1269,8 @@ function onCollisionEnter(collisionInfo) collisionTable[object] = true Wait.frames(function() collisionTable[object] = nil end, 1) + GlobalApi.handleTokenDetaching(object) + local md = JSON.decode(object.getGMNotes()) or {} syncCustomizableMetadata(object, md) @@ -1299,7 +1301,6 @@ function onCollisionEnter(collisionInfo) -- encounter types / committed skill cards in the threat area if inArea(localCardPos, THREAT_AREA) and (md.type == "Treachery" or md.type == "Enemy" or md.type == "Skill" or md.weakness) then - GlobalApi.handleTokenDetaching(object) spawnTokensOrShowHelper(object) end end From e65defc992c8fceba957cdd2a8183a9d9f338cbe Mon Sep 17 00:00:00 2001 From: Chr1Z93 Date: Fri, 20 Dec 2024 10:29:52 +0100 Subject: [PATCH 4/5] stop PDFs from attaching and make token remover functional again --- src/core/Global.ttslua | 42 ++++++++++++++++++++++++---------- src/tokens/TokenChecker.ttslua | 9 ++++++++ src/util/SearchLib.ttslua | 2 +- 3 files changed, 40 insertions(+), 13 deletions(-) diff --git a/src/core/Global.ttslua b/src/core/Global.ttslua index be7b155f0..716613da0 100644 --- a/src/core/Global.ttslua +++ b/src/core/Global.ttslua @@ -37,6 +37,7 @@ local lastDrawnTokens = {} local bagSearchers = {} local hideTitleSplashWaitFunctionId = nil +local lastZoneEnterObject = nil -- online functionality related variables local library, requestObj, modMeta, searchFilter, authorFilter @@ -219,16 +220,32 @@ end -- TTS event for objects that enter zones function onObjectEnterZone(zone, object) + if lastZoneEnterObject == object then return end + lastZoneEnterObject = object + Wait.frames(function() lastZoneEnterObject = nil end, 3) + -- detect the "token discard zones" beneath the hand zones - if zone.getName() == "TokenDiscardZone" and - not tokenChecker.isChaosToken(object) and - object.type == "Tile" and - object.getMemo() and - not object.getLock() and - object.interactable == true then - local matcolor = playermatApi.getMatColorByPosition(object.getPosition()) - local trash = guidReferenceApi.getObjectByOwnerAndType(matcolor, "Trash") - trash.putObject(object) + if zone.getName() == "TokenDiscardZone" then + if object.type == "Card" then + local attachments = object.getAttachments() + if not attachments then return end + + local matcolor = playermatApi.getMatColorByPosition(object.getPosition()) + local trash = guidReferenceApi.getObjectByOwnerAndType(matcolor, "Trash") + + for i = #attachments, 1, -1 do + local deepObj = attachments[i] + if (deepObj["name"] == "Custom Token" or deepObj["name"] == "Custom Tile") and + not tokenChecker.isChaosTokenName(deepObj["nickname"]) and deepObj["memo"] ~= nil then + trash.putObject(object.removeAttachment(deepObj["index"])) + end + end + elseif object.type == "Tile" and not tokenChecker.isChaosToken(object) and object.getMemo() and + not object.getLock() and object.interactable == true then + local matcolor = playermatApi.getMatColorByPosition(object.getPosition()) + local trash = guidReferenceApi.getObjectByOwnerAndType(matcolor, "Trash") + trash.putObject(object) + end elseif zone.type == "Hand" and object.type == "Card" then -- make sure the card is face-up if object.is_face_down then @@ -2890,14 +2907,14 @@ function moveAndRotatePlayermat(params) end function handleTokenAttaching(params) - local card = params.card + local card = params.card if card == nil then return end local player = params.player - local searchResult = searchLib.onObject(card, "isTileOrToken", 0.95) + local searchResult = searchLib.onObject(card, "isTileOrToken", 0.9) if card.is_face_down and next(searchResult) ~= nil then - cardSettings[card] = { + cardSettings[card] = { hideFacedown = card.hide_when_face_down, tooltip = card.tooltip } @@ -2950,6 +2967,7 @@ function handleTokenDetaching(params) card.call("updateStackSize") end end + return removedTokens end function moveCardWithTokens(params) diff --git a/src/tokens/TokenChecker.ttslua b/src/tokens/TokenChecker.ttslua index 905d7878d..2aa158ffe 100644 --- a/src/tokens/TokenChecker.ttslua +++ b/src/tokens/TokenChecker.ttslua @@ -32,5 +32,14 @@ do end end + -- returns true if the passed name is a chaos token name + TokenChecker.isChaosTokenName = function(objName) + if CHAOS_TOKEN_NAMES[objName] then + return true + else + return false + end + end + return TokenChecker end diff --git a/src/util/SearchLib.ttslua b/src/util/SearchLib.ttslua index f56069014..c8017899b 100644 --- a/src/util/SearchLib.ttslua +++ b/src/util/SearchLib.ttslua @@ -7,7 +7,7 @@ do isClue = function(x) return x.memo == "clueDoom" and x.is_face_down == false end, isDoom = function(x) return x.memo == "clueDoom" and x.is_face_down == true end, isInteractable = function(x) return x.interactable end, - isTileOrToken = function(x) return x.type == "Tile" or x.type == "Generic" end, + isTileOrToken = function(x) return not x.Book and (x.type == "Tile" or x.type == "Generic") end, isUniversalToken = function(x) return x.getMemo() == "universalActionAbility" end, } From b0e1302dfbf1bfd1f9264626354266954c654785 Mon Sep 17 00:00:00 2001 From: Chr1Z93 Date: Wed, 1 Jan 2025 22:24:28 +0100 Subject: [PATCH 5/5] Removed extra space --- src/playarea/PlayAreaImageData.ttslua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/playarea/PlayAreaImageData.ttslua b/src/playarea/PlayAreaImageData.ttslua index a5b55d6ec..f6dc353a9 100644 --- a/src/playarea/PlayAreaImageData.ttslua +++ b/src/playarea/PlayAreaImageData.ttslua @@ -256,15 +256,15 @@ PLAYAREA_IMAGE_DATA = { URL = "https://steamusercontent-a.akamaihd.net/ugc/2279446315725449814/30BB7E4F8D9F1571A420372E78ACAF2D7792811F/" }, { - Name = "VII - The Depths of Yoth 1", + Name = "VII - The Depths of Yoth 1", URL = "https://steamusercontent-a.akamaihd.net/ugc/2279446315725449962/D69532827DFF2D654F8A606B7917D593F52D7624/" }, { - Name = "VII - The Depths of Yoth 2", + Name = "VII - The Depths of Yoth 2", URL = "https://steamusercontent-a.akamaihd.net/ugc/2279446315725450085/479A8A1BDD7BE80B43AE4F2C14DFA811D7B28482/" }, { - Name = "VII - The Depths of Yoth 3", + Name = "VII - The Depths of Yoth 3", URL = "https://steamusercontent-a.akamaihd.net/ugc/2279446315725450258/E617F5A78DFBE913652E20BF97D38B91087FACAE/" }, {