Skip to content

Commit

Permalink
Merge branch 'main' into action-tracker
Browse files Browse the repository at this point in the history
  • Loading branch information
Chr1Z93 committed Jan 3, 2025
2 parents a854292 + c78caa6 commit 5e936f3
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 22 deletions.
118 changes: 100 additions & 18 deletions src/core/Global.ttslua
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ local lastDrawnTokens = {}

local bagSearchers = {}
local hideTitleSplashWaitFunctionId = nil
local lastZoneEnterObject = nil

-- online functionality related variables
local library, requestObj, modMeta, searchFilter, authorFilter
Expand Down Expand Up @@ -78,6 +79,7 @@ local actionsPerMatColor = {}

-- track cards' tokens
local cardTokens = {}
local cardSettings = {}

---------------------------------------------------------
-- data for tokens
Expand Down Expand Up @@ -212,6 +214,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)
Expand All @@ -220,16 +224,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
Expand Down Expand Up @@ -304,15 +324,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" and not target.hasTag("Minicard") then
handleTokenAttaching({ player = player, card = target })
end
end
end
end

Expand Down Expand Up @@ -3036,18 +3063,72 @@ 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
if card == nil then return end

local player = params.player
local searchResult = searchLib.onObject(card, "isTileOrToken", 0.9)

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() 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
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
return removedTokens
end

function moveCardWithTokens(params)
local card = params.card
local position = params.position
local rotation = params.rotation

Expand All @@ -3073,7 +3154,6 @@ function moveCardWithTokens(params)
updateTokenTransform(card)
return card.resting and not card.isSmoothMoving()
end

return true
end
)
Expand Down Expand Up @@ -3124,6 +3204,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
Expand Down
6 changes: 6 additions & 0 deletions src/core/GlobalApi.ttslua
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions src/mythos/MythosArea.ttslua
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions src/playarea/PlayAreaImageData.ttslua
Original file line number Diff line number Diff line change
Expand Up @@ -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/"
},
{
Expand Down
2 changes: 2 additions & 0 deletions src/playermat/Playermat.ttslua
Original file line number Diff line number Diff line change
Expand Up @@ -1298,6 +1298,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)

Expand Down
9 changes: 9 additions & 0 deletions src/tokens/TokenChecker.ttslua
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 1 addition & 1 deletion src/util/SearchLib.ttslua
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}

Expand Down

0 comments on commit 5e936f3

Please sign in to comment.