diff --git a/src/core/VictoryDisplay.ttslua b/src/core/VictoryDisplay.ttslua index 13c56694..d5541102 100644 --- a/src/core/VictoryDisplay.ttslua +++ b/src/core/VictoryDisplay.ttslua @@ -234,28 +234,28 @@ end -- places the provided card in the first empty spot function placeCard(card) - local trash = guidReferenceApi.getObjectByOwnerAndType("Mythos", "Trash") - - -- check snap point states + -- get sorted list of snap points to check slots local snaps = self.getSnapPoints() table.sort(snaps, function(a, b) return a.position.x > b.position.x end) table.sort(snaps, function(a, b) return a.position.z < b.position.z end) -- get first empty slot - local fullSlots = {} - local positions = {} + local emptyIndex, emptyPos for i, snap in ipairs(snaps) do - positions[i] = self.positionToWorld(snap.position) - local searchResult = searchLib.atPosition(positions[i], "isCardOrDeck") - fullSlots[i] = #searchResult > 0 + local snapPos = self.positionToWorld(snap.position) + local searchResult = searchLib.atPosition(snapPos, "isCardOrDeck") + if #searchResult == 0 then + emptyPos = snapPos + emptyIndex = i + break + end end -- remove tokens from the card - for _, obj in ipairs(searchLib.onObject(card)) do - -- don't touch decks / cards - if obj.type == "Deck" or obj.type == "Card" then + local trash = guidReferenceApi.getObjectByOwnerAndType("Mythos", "Trash") + for _, obj in ipairs(searchLib.onObject(card, "isTileOrToken")) do + if tokenChecker.isChaosToken(obj) then -- put chaos tokens back into bag - elseif tokenChecker.isChaosToken(obj) then local chaosBag = chaosBagApi.findChaosBag() chaosBag.putObject(obj) elseif obj.memo ~= nil and obj.getLock() == false then @@ -264,17 +264,14 @@ function placeCard(card) end -- place the card + card.setRotation({ 0, 270, card.getRotation().z }) local name = card.getName() or "Unnamed card" - for i = 1, 10 do - if fullSlots[i] ~= true then - local rot = { 0, 270, card.getRotation().z } - card.setPositionSmooth(positions[i], false, true) - card.setRotation(rot) - broadcastToAll("Victory Display: " .. name .. " placed into slot " .. i .. ".", "Green") - return - end + if emptyPos then + card.setPositionSmooth(emptyPos, false, true) + broadcastToAll("Victory Display: " .. name .. " placed into slot " .. emptyIndex .. ".", "Green") + else + -- use the first snap position in case all slots are full + card.setPositionSmooth(self.positionToWorld(snaps[1].position), false, true) + broadcastToAll("Victory Display is full! " .. name .. " placed into slot 1.", "Orange") end - - broadcastToAll("Victory Display is full! " .. name .. " placed into slot 1.", "Orange") - card.setPositionSmooth(positions[1], false, true) end diff --git a/src/playercards/cards/KohakuNarukami.ttslua b/src/playercards/cards/KohakuNarukami.ttslua index 1d4c20d9..adb9d069 100644 --- a/src/playercards/cards/KohakuNarukami.ttslua +++ b/src/playercards/cards/KohakuNarukami.ttslua @@ -1,13 +1,20 @@ require("playercards/CardsWithHelper") -local blessCurseManagerApi = require("chaosbag/BlessCurseManagerApi") -local guidReferenceApi = require("core/GUIDReferenceApi") -local playermatApi = require("playermat/PlayermatApi") -local searchLib = require("util/SearchLib") -local tokenManager = require("core/token/TokenManager") +local blessCurseManagerApi = require("chaosbag/BlessCurseManagerApi") +local guidReferenceApi = require("core/GUIDReferenceApi") +local playermatApi = require("playermat/PlayermatApi") +local searchLib = require("util/SearchLib") +local tokenManager = require("core/token/TokenManager") -local isHelperEnabled = false +local isHelperEnabled = false local updated +local xmlData = { + Action = { color = "#6D202CE6", onClick = "removeAndExtraAction" }, + Bless = { color = "#9D702CE6", onClick = "addTokenToBag" }, + Curse = { color = "#633A84E6", onClick = "addTokenToBag" }, + ElderSign = { color = "#50A8CEE6", onClick = "elderSignAbility" } +} + function updateSave() self.script_state = JSON.encode({ isHelperEnabled = isHelperEnabled }) end @@ -57,32 +64,29 @@ function removeAndExtraAction() local mat = guidReferenceApi.getObjectByOwnerAndType(matColor, "Playermat") local rotation = mat.getRotation() - -- find empty action token slots - -- check snap point states + -- find empty action token slots by checking snap points local snaps = mat.getSnapPoints() - - -- get first empty slot - local fullSlots = {} - local positions = {} - for _, snap in ipairs(snaps) do - if snap.tags[1] == "UniversalToken" then - table.insert(positions, mat.positionToWorld(snap.position)) - local searchResult = searchLib.atPosition(positions[#positions], "isUniversalToken") - table.insert(fullSlots, #searchResult > 0) + + -- get first empty slot in the top row (so the second empty slot because of the ability token) + local emptyPos = position -- default to card position + for i, snap in ipairs(snaps) do + if i > 1 then + if snap.tags[1] == "UniversalToken" then + local snapPos = mat.positionToWorld(snap.position) + local searchResult = searchLib.atPosition(snapPos, "isUniversalToken") + if #searchResult == 0 then + emptyPos = snapPos + break + end + end end end - for i = 2, 6 do -- look at all 5 slots above investigator card - if fullSlots[i] ~= true then - callback = function(spawned) spawned.call("updateClassAndSymbol", { class = "Mystic", symbol = "Mystic" }) spawned.addTag("Temporary") end - tokenManager.spawnToken(positions[i] + Vector(0, 0.7, 0), "universalActionAbility", rotation, callback) - return - end + callback = function(spawned) + spawned.call("updateClassAndSymbol", { class = "Mystic", symbol = "Mystic" }) + spawned.addTag("Temporary") end - - -- if all slots are full - callback = function(spawned) spawned.call("updateClassAndSymbol", { class = "Mystic", symbol = "Mystic" }) spawned.addTag("Temporary") end - tokenManager.spawnToken(position + Vector(0, 0.7, 0), "universalActionAbility", rotation, callback) + tokenManager.spawnToken(emptyPos + Vector(0, 0.7, 0), "universalActionAbility", rotation, callback) end function elderSignAbility() @@ -97,37 +101,39 @@ function maybeUpdateButtonState() if numInBag.Bless <= numInBag.Curse and numInBag.Bless < 10 then state.Bless = true + state.ElderSign = true end if numInBag.Curse <= numInBag.Bless and numInBag.Curse < 10 then state.Curse = true + state.ElderSign = true end - if numInBag.Curse >= 2 and numInBag.Bless >= 2 then + if numInBag.Curse >= 2 and numInBag.Bless >= 2 then state.Action = true end - state.ElderSign = true - setUiState(state) updated = true end function setUiState(params) - for _, tokenName in ipairs({ "Bless", "Curse", "Action", "ElderSign" }) do - if params[tokenName] then - self.UI.show(tokenName) - self.UI.hide("inactive" .. tokenName) + for buttonId, state in ipairs(params) do + if state then + self.UI.setAttribute(buttonId, "color", xmlData[buttonId].color) + self.UI.setAttribute(buttonId, "onClick", xmlData[buttonId].onClick) + self.UI.setAttribute(buttonId, "textColor", "white") else - self.UI.show("inactive" .. tokenName) - self.UI.hide(tokenName) + self.UI.setAttribute(buttonId, "color", "#353535E6") + self.UI.setAttribute(buttonId, "onClick", "errorMessage") + self.UI.setAttribute(buttonId, "textColor", "#A0A0A0") end end end function errorMessage(_, _, triggeringButton) local numInBag = blessCurseManagerApi.getBlessCurseInBag() - if triggeringButton == "inactiveAction" then + if triggeringButton == "Action" then broadcastToAll("There are not enough Blesses and/or Curses in the chaos bag.", "Red") elseif numInBag.Bless == 10 and numInBag.Curse == 10 then broadcastToAll("No more tokens can be added to the chaos bag.", "Red") diff --git a/src/util/DeckLib.ttslua b/src/util/DeckLib.ttslua index a88cb50c..0655ce1d 100644 --- a/src/util/DeckLib.ttslua +++ b/src/util/DeckLib.ttslua @@ -2,23 +2,25 @@ do local DeckLib = {} local searchLib = require("util/SearchLib") - -- places a card/deck at a position or merges into an existing deck + -- places a card/deck at a position or merges into an existing deck below ---@param obj tts__Object Object to move ---@param pos table New position for the object ---@param rot? table New rotation for the object ---@param below? boolean Should the object be placed below an existing deck? DeckLib.placeOrMergeIntoDeck = function(obj, pos, rot, below) - if obj == nil or pos == nil then return end + if obj == nil or obj.isDestroyed() or pos == nil then return end -- search the new position for existing card/deck local searchResult = searchLib.atPosition(pos, "isCardOrDeck") + local targetObj -- get new position local offset = 0.5 local newPos = Vector(pos) + Vector(0, offset, 0) if #searchResult == 1 then - local bounds = searchResult[1].getBounds() + targetObj = searchResult[1] + local bounds = targetObj.getBounds() if below then newPos = Vector(pos):setAt("y", bounds.center.y - bounds.size.y / 2) else @@ -26,7 +28,8 @@ do end end - -- allow moving the objects smoothly out of the hand + -- allow moving the objects smoothly out of the hand and temporarily lock it + obj.setLock(true) obj.use_hands = false if rot then @@ -34,17 +37,17 @@ do end obj.setPositionSmooth(newPos, false, true) - -- continue if the card stops smooth moving + -- use putObject if the card stops smooth moving to avoid a TTS bug that merges unrelated cards that are not resting + -- pcall avoids errors (physics is sometimes too fast so the object doesn't exist for the put) Wait.condition( - function() - obj.use_hands = true - -- this avoids a TTS bug that merges unrelated cards that are not resting - if #searchResult == 1 and searchResult[1] ~= obj and searchResult[1] ~= nil then - -- call this with avoiding errors (physics is sometimes too fast so the object doesn't exist for the put) - pcall(function() searchResult[1].putObject(obj) end) - end - end, - function() return not obj.isSmoothMoving() end, 3) + pcall(function() + obj.setLock(false) + obj.use_hands = true + if #searchResult == 1 and targetObj ~= obj then + targetObj.putObject(obj) + end + end), + function() return not obj.isSmoothMoving() end, 3) end return DeckLib diff --git a/xml/playercards/KohakuNarukami.xml b/xml/playercards/KohakuNarukami.xml index 277dfcd8..adea3dba 100644 --- a/xml/playercards/KohakuNarukami.xml +++ b/xml/playercards/KohakuNarukami.xml @@ -4,14 +4,6 @@ fontSize="200" iconWidth="300" iconAlignment="Right"/> -