From a40960457d74b54995ee7d24d690dc61e4e04bde Mon Sep 17 00:00:00 2001 From: Chr1Z93 Date: Tue, 29 Oct 2024 22:45:26 +0100 Subject: [PATCH] updated attachment helper handling --- src/accessories/AttachmentHelper.ttslua | 39 +++-- src/arkhamdb/ArkhamDb.ttslua | 6 +- src/arkhamdb/DeckImporter.ttslua | 204 ++++++++++++++---------- src/playermat/Zones.ttslua | 163 +++++++------------ 4 files changed, 214 insertions(+), 198 deletions(-) diff --git a/src/accessories/AttachmentHelper.ttslua b/src/accessories/AttachmentHelper.ttslua index 16012562..87b950b3 100644 --- a/src/accessories/AttachmentHelper.ttslua +++ b/src/accessories/AttachmentHelper.ttslua @@ -164,28 +164,47 @@ function onDrop(playerColor) -- assume the first eligible object as intended sync object local syncObj = searchResult[1] local syncName = syncObj.getName() - local notes = syncObj.getGMNotes() - local md = JSON.decode(notes) or {} + local md = JSON.decode(syncObj.getGMNotes()) or {} + + local found = loadDataFromMetadata({ + md = md, + playerColor = playerColor, + syncName = syncName, + syncRotation = syncObj.getRotation() + }) + if not found then + printToColor("Didn't find background for '" .. syncName .. "'!", playerColor, "Orange") + end +end + +function loadDataFromMetadata(params) + local md = params.md + local syncRotation = params.syncRotation + local playerColor = params.playerColor + local syncName = params.syncName -- loop through background table for _, bgInfo in ipairs(BACKGROUNDS) do if bgInfo.id == md.id or bgInfo.id2 == md.id then - printToColor("Background for '" .. syncName .. "' loaded!", playerColor, "Green") + if syncName and playerColor then + printToColor("Background for '" .. syncName .. "' loaded!", playerColor, "Green") + end showIcons = bgInfo.icons - -- update rotation - local syncRotY = syncObj.getRotation().y - if md.type == "Investigator" then - syncRotY = syncRotY + 90 + -- maybe update rotation + if syncRotation then + if md.type == "Investigator" then + syncRotation.y = syncRotation.y + 90 + end + self.setRotation(self.getRotation():setAt("y", syncRotation.y)) end - self.setRotation(self.getRotation():setAt("y", syncRotY)) -- update the image updateImage(bgInfo.url) - return + return true end end - printToColor("Didn't find background for '" .. syncName .. "'!", playerColor, "Orange") + return false end -- called by context menu to change background image diff --git a/src/arkhamdb/ArkhamDb.ttslua b/src/arkhamdb/ArkhamDb.ttslua index 6a9e1812..91a82bef 100644 --- a/src/arkhamdb/ArkhamDb.ttslua +++ b/src/arkhamdb/ArkhamDb.ttslua @@ -193,7 +193,11 @@ do for _, weaknessId in ipairs(weaknessIds) do slots[weaknessId] = (slots[weaknessId] or 0) + 1 end - internal.maybePrint("Added " .. #weaknessIds .. " random basic weakness(es) to deck", playerColor) + if #weaknessIds == 1 then + internal.maybePrint("Added 1 random basic weakness to deck", playerColor) + else + internal.maybePrint("Added " .. #weaknessIds .. " random basic weaknesses to deck", playerColor) + end end end diff --git a/src/arkhamdb/DeckImporter.ttslua b/src/arkhamdb/DeckImporter.ttslua index 14e93203..08f79b37 100644 --- a/src/arkhamdb/DeckImporter.ttslua +++ b/src/arkhamdb/DeckImporter.ttslua @@ -1,17 +1,17 @@ require("playercards/PlayerCardSpawner") -local allCardsBagApi = require("playercards/AllCardsBagApi") -local arkhamDb = require("arkhamdb/ArkhamDb") -local GlobalApi = require("core/GlobalApi") -local guidReferenceApi = require("core/GUIDReferenceApi") -local playermatApi = require("playermat/PlayermatApi") -local zones = require("playermat/Zones") +local allCardsBagApi = require("playercards/AllCardsBagApi") +local arkhamDb = require("arkhamdb/ArkhamDb") +local GlobalApi = require("core/GlobalApi") +local guidReferenceApi = require("core/GUIDReferenceApi") +local playermatApi = require("playermat/PlayermatApi") +local zones = require("playermat/Zones") -local matsWithInvestigator = {} -local startsInPlayCount = 0 -local INPUT_FIELD_HEIGHT = 340 -local INPUT_FIELD_WIDTH = 1500 -local FIELD_COLOR = { 0.9, 0.7, 0.5 } +local matsWithInvestigator = {} +local startsInPlayCount = 0 +local INPUT_FIELD_HEIGHT = 340 +local INPUT_FIELD_WIDTH = 1500 +local FIELD_COLOR = { 0.9, 0.7, 0.5 } local PRIVATE_TOGGLE_LABELS = {} PRIVATE_TOGGLE_LABELS[true] = "Private" @@ -25,14 +25,14 @@ local STANDALONE_TOGGLE_LABELS = {} STANDALONE_TOGGLE_LABELS[true] = "Yes" STANDALONE_TOGGLE_LABELS[false] = "No" -redDeckId = "" -orangeDeckId = "" -whiteDeckId = "" -greenDeckId = "" +redDeckId = "" +orangeDeckId = "" +whiteDeckId = "" +greenDeckId = "" -local privateDeck = true -local loadNewestDeck = true -local standalone = false +local privateDeck = true +local loadNewestDeck = true +local standalone = false function onLoad(script_state) initializeUi(JSON.decode(script_state)) @@ -47,13 +47,13 @@ function onSave() return JSON.encode(getUiState()) end ---@return uiStateTable uiStateTable Contains data about the current UI state function getUiState() return { - redDeck = redDeckId, - orangeDeck = orangeDeckId, - whiteDeck = whiteDeckId, - greenDeck = greenDeckId, + redDeck = redDeckId, + orangeDeck = orangeDeckId, + whiteDeck = whiteDeckId, + greenDeck = greenDeckId, privateDeck = privateDeck, - loadNewest = loadNewestDeck, - standalone = standalone + loadNewest = loadNewestDeck, + standalone = standalone } end @@ -68,13 +68,13 @@ end -- Sets up the UI for the deck loader, populating fields from the given save state table decoded from onLoad() function initializeUi(savedUiState) if savedUiState ~= nil then - redDeckId = savedUiState.redDeck - orangeDeckId = savedUiState.orangeDeck - whiteDeckId = savedUiState.whiteDeck - greenDeckId = savedUiState.greenDeck - privateDeck = savedUiState.privateDeck + redDeckId = savedUiState.redDeck + orangeDeckId = savedUiState.orangeDeck + whiteDeckId = savedUiState.whiteDeck + greenDeckId = savedUiState.greenDeck + privateDeck = savedUiState.privateDeck loadNewestDeck = savedUiState.loadNewest - standalone = savedUiState.standalone + standalone = savedUiState.standalone end makeOptionToggles() @@ -205,7 +205,7 @@ function loadDecksCoroutine() local deckId = _G[string.lower(matColor) .. "DeckId"] if deckId ~= nil and deckId ~= "" then buildDeck(matColor, deckId) - coroutine.yield() + coWaitFrames(3) end end end @@ -224,14 +224,17 @@ end function getDefaultCardZone(cardMetadata, bondedList) if cardMetadata.id == "09080-m" then -- Have to check the Servitor before other minicards - return "SetAside6" + return "SetAside5" elseif cardMetadata.id == "09006" or cardMetadata.id == "06233" or cardMetadata.id == "06275" or cardMetadata.id == "71052" or bondedList[cardMetadata.id] then -- On The Mend, False Awakening, Jewel of Sarnath and bonded cards are set aside return "SetAside2" - elseif cardMetadata.id == "07303" or cardMetadata.id == "09077" then - -- Ancestral Knowledge / Underworld Market + elseif cardMetadata.id == "07303" then + -- Ancestral Knowledge return "SetAside3" + elseif cardMetadata.id == "09077" then + -- Underworld Market + return "SetAside6" elseif cardMetadata.type == "Investigator" then return "Investigator" elseif cardMetadata.type == "Minicard" then @@ -292,26 +295,29 @@ function loadCards(slots, investigatorId, bondedList, customizations, playerColo ["09077"] = true, ["10079"] = true } + local zoneWithAttachments = {} -- reset the startsInPlayCount startsInPlayCount = 0 - -- reserve slots for cards with attachments + -- reserve slots for cards with attachments (not for Underworld Market) for cardId, _ in pairs(cardsWithAttachments) do - if slotsCopy[cardId] and slotsCopy[cardId] > 0 then + if cardId ~= "09077" and slotsCopy[cardId] and slotsCopy[cardId] > 0 then -- increase startsInPlayCount by 1 and reserve slot for this card startsInPlayCount = startsInPlayCount + 1 cardsWithAttachments[cardId] = startsInPlayCount -- reserve an additional slot for the attachments startsInPlayCount = startsInPlayCount + 1 + zoneWithAttachments["Blank" .. startsInPlayCount] = true end end for cardId, cardCount in pairs(slots) do local card = allCardsBagApi.getCardById(cardId) if card ~= nil then - if cardsWithAttachments[cardId] and cardsWithAttachments[cardId] < 6 then + local reservedSlot = cardsWithAttachments[cardId] + if type(reservedSlot) == "number" and reservedSlot < 6 then cardZone = "Blank" .. cardsWithAttachments[cardId] else cardZone = getDefaultCardZone(card.metadata, bondedList) @@ -347,25 +353,35 @@ function loadCards(slots, investigatorId, bondedList, customizations, playerColo -- Check for existing cards in zones and maybe skip them removeBusyZones(playerColor, zoneDecks) + -- Spawn attachment helpers if option is enabled + if GlobalApi.getOptionPanelState()["showAttachmentHelper"] then + local objs = getObjectsWithTag("AttachmentHelperBag") + if #objs > 0 then + local helperRot = zones.getDefaultCardRotation(playerColor, "Blank1") + for cardId, reservedSlot in pairs(cardsWithAttachments) do + if type(reservedSlot) == "number" and reservedSlot < 6 then + local helper = objs[1].takeObject({ + position = zones.getZonePosition(playerColor, "Blank" .. (reservedSlot + 1)):setAt("y", 1.8), + rotation = helperRot, + smooth = false + }) + coWaitFrames(3) + helper.call("loadDataFromMetadata", { md = { id = cardId } }) + coWaitFrames(3) + end + end + end + end + -- Spawn the list for each zone for zone, zoneCards in pairs(zoneDecks) do local deckPos = zones.getZonePosition(playerColor, zone):setAt("y", 3) local deckRot = zones.getDefaultCardRotation(playerColor, zone) local callback = nil - -- spawn attachment helpers if option is enabled - if GlobalApi.getOptionPanelState()["showAttachmentHelper"] then - local objs = getObjectsWithTag("AttachmentHelperBag") - if #objs > 0 then - for cardId, reservedSlot in pairs(cardsWithAttachments) do - if reservedSlot < 7 then - objs[1].takeObject({ - position = zones.getZonePosition(playerColor, "Blank" .. reservedSlot):setAt("y", 1.6), - rotation = deckRot - }) - end - end - end + -- if this is a zone with attachments, spawn cards facedown and add additional delay + if zoneWithAttachments[zone] then + deckRot = deckRot:setAt("z", 180) end -- If cards are spread too close together TTS groups them weirdly, selecting multiples @@ -388,7 +404,7 @@ function loadCards(slots, investigatorId, bondedList, customizations, playerColo callback = function(card) loadAltArt(card, loadAltInvestigator) end end Spawner.spawnCards(zoneCards, deckPos, deckRot, true, callback) - coroutine.yield(0) + coWaitFrames(3) end -- Look for any cards which haven't been loaded @@ -529,6 +545,7 @@ function removeBusyZones(playerColor, zoneDecks) zoneDecks["Blank" .. i] = nil end zoneDecks["UnderSetAside3"] = nil + zoneDecks["UnderSetAside6"] = nil zoneDecks["Deck"] = nil printToAll("Skipped deck import", playerColor) end @@ -548,7 +565,6 @@ function handleAncestralKnowledge(cardsToSpawn) for i = 1, 5 do local skillListIndex = math.random(#skillList) cardsToSpawn[skillList[skillListIndex]].zone = "UnderSetAside3" - table.remove(skillList, skillListIndex) end end @@ -556,10 +572,10 @@ end function handleAllAttachments(cardsToSpawn, slotsCopy, bondedList, customizations, playerColor) for cardId, reservedSlot in pairs(cardsWithAttachments) do if slotsCopy[cardId] and slotsCopy[cardId] > 0 then - if customizations["attachments_" .. cardId] and reservedSlot < 6 then + if customizations["attachments_" .. cardId] and type(reservedSlot) == "number" and reservedSlot < 6 then handleAttachment(cardId, cardsToSpawn, customizations) elseif cardId == "09077" then - handleUnderworldMarket(cardsToSpawn, slotsCopy, playerColor) + handleUnderworldMarket(cardsToSpawn, customizations, playerColor) elseif cardId == "05002" then handleHunchDeck(cardsToSpawn, bondedList, playerColor) elseif cardId == "07303" then @@ -580,7 +596,7 @@ function handleAttachment(parentId, cardsToSpawn, customizations) local zone = "Blank" .. (cardsWithAttachments[parentId] + 1) for i = #attachmentList, 1, -1 do for j = #cardsToSpawn, 1, -1 do - if cardsToSpawn[j].metadata.id == attachmentList[i] and cardsToSpawn[j].zone ~= zone then + if cardsToSpawn[j].metadata.id == attachmentList[i] and cardsToSpawn[j].zone == "Deck" then cardsToSpawn[j].zone = zone break end @@ -588,38 +604,51 @@ function handleAttachment(parentId, cardsToSpawn, customizations) end end --- Check for and handle Underworld Market by moving all Illicit cards to UnderSetAside3 ----@param cardList table Deck list being created +-- Check for and handle Underworld Market by moving all Illicit cards to UnderSetAside6 +---@param cardsToSpawn table Deck list being created ---@param playerColor string Color this deck is being loaded for -function handleUnderworldMarket(cardList, slotsCopy, playerColor) - if not slotsCopy["09077"] or slotsCopy["09077"] == 0 then return end - - local illicitList = {} - - -- get all possible Illicit cards - for i, card in ipairs(cardList) do - if card.metadata.traits ~= nil and string.find(card.metadata.traits, "Illicit", 1, true) and card.zone == "Deck" then - table.insert(illicitList, i) +function handleUnderworldMarket(cardsToSpawn, customizations, playerColor) + local attachmentList = {} + if customizations["attachments_09077"] then + -- get list of cards that are attached (split by ",") + for str in string.gmatch(customizations["attachments_09077"], "([^,]+)") do + table.insert(attachmentList, str) end end - if #illicitList < 10 then - printToAll("Only " .. #illicitList .. " Illicit cards in your deck, you can't trigger Underworld Market's ability.", playerColor) + if #attachmentList == 10 then + -- handling for 10 cards selected in deck data + for i = #attachmentList, 1, -1 do + for j = #cardsToSpawn, 1, -1 do + if cardsToSpawn[j].metadata.id == attachmentList[i] and cardsToSpawn[j].zone == "Deck" then + cardsToSpawn[j].zone = "UnderSetAside6" + break + end + end + end else - -- Process cards to move them to the market deck. This is done in reverse order because the sorting needs - -- to be reversed (deck sorts for face down). Performance here may be an issue, as table.remove() is an O(n) - -- operation which makes the full shift O(n^2). But keep it simple unless it becomes a problem - for i = #illicitList, 1, -1 do - local moving = cardList[illicitList[i]] - moving.zone = "UnderSetAside3" - table.remove(cardList, illicitList[i]) - table.insert(cardList, moving) + -- regular handling + local illicitList = {} + + -- get all possible Illicit cards + for i, card in ipairs(cardsToSpawn) do + if card.metadata.traits ~= nil and string.find(card.metadata.traits, "Illicit", 1, true) and card.zone == "Deck" then + table.insert(illicitList, i) + end end - if #illicitList > 10 then - printToAll("Moved all " .. #illicitList .. " Illicit cards to the Market deck, reduce it to 10", playerColor) + if #illicitList < 10 then + printToAll("Only " .. #illicitList .. " Illicit cards in your deck, you can't trigger Underworld Market's ability.", playerColor) else - printToAll("Built the Market deck", playerColor) + for i = #illicitList, 1, -1 do + cardsToSpawn[illicitList[i]].zone = "UnderSetAside6" + end + + if #illicitList > 10 then + printToAll("Moved all " .. #illicitList .. " Illicit cards to the Market deck, reduce it to 10", playerColor) + else + printToAll("Built the Market deck", playerColor) + end end end end @@ -630,10 +659,10 @@ end function handleHunchDeck(cardList, bondedList, playerColor) local insightList = {} for i, card in ipairs(cardList) do - if (card.metadata.type == "Event" + if card.metadata.type == "Event" and card.metadata.traits ~= nil and string.match(card.metadata.traits, "Insight") - and bondedList[card.metadata.id] == nil) then + and bondedList[card.metadata.id] == nil then table.insert(insightList, i) end end @@ -696,11 +725,9 @@ function handleSpiritDeck(cardList, playerColor, customizations) end if #spiritList < 10 then - printToAll("Jim's spirit deck must have 9 Ally assets but the deck only has " .. - (#spiritList - 1) .. " Ally assets.", playerColor) + printToAll("Jim's spirit deck must have 9 Ally assets but the deck only has " .. (#spiritList - 1) .. " Ally assets.", playerColor) elseif #spiritList > 11 then - printToAll("Moved all " .. (#spiritList - 1) .. - " Ally assets to the spirit deck, reduce it to 10 (including Vengeful Shade).", playerColor) + printToAll("Moved all " .. (#spiritList - 1) .. " Ally assets to the spirit deck, reduce it to 10 (including Vengeful Shade).", playerColor) else printToAll("Built Jim's spirit deck", playerColor) end @@ -835,3 +862,10 @@ function deepCopy(data) end return copiedList end + +-- pauses the current coroutine for 'frameCount' frames +function coWaitFrames(frameCount) + for k = 1, frameCount do + coroutine.yield(0) + end +end diff --git a/src/playermat/Zones.ttslua b/src/playermat/Zones.ttslua index 27d5aac6..7d689136 100644 --- a/src/playermat/Zones.ttslua +++ b/src/playermat/Zones.ttslua @@ -15,108 +15,70 @@ -- SetAside[4-6]: Column farther away from the mat, with 4 at the top and 6 at the bottom. -- SetAside1: Permanent cards -- SetAside2: Bonded cards --- SetAside3: Ancestral Knowledge / Underworld Market +-- SetAside3: Ancestral Knowledge -- SetAside4: Upgrade sheets for customizable cards --- SetAside5: Hunch Deck for Joe Diamond --- SetAside6: currently unused +-- SetAside5: Hunch Deck for Joe Diamond // Summoned Servitor Minicard +-- SetAside6: Underworld Market -- AboveSetAside: Investigator specific object -- BelowSetAside: Investigator specific object do - local playermatApi = require("playermat/PlayermatApi") - local Zones = { } + local playermatApi = require("playermat/PlayermatApi") + local Zones = {} - local commonZones = {} - commonZones["Investigator"] = { -1.177, 0, 0.002 } - commonZones["Deck"] = { -1.82, 0, 0 } - commonZones["Discard"] = { -1.82, 0, 0.61 } - commonZones["Ally"] = { -0.615, 0, 0.024 } - commonZones["Body"] = { -0.630, 0, 0.553 } - commonZones["Hand1"] = { 0.215, 0, 0.042 } - commonZones["Hand2"] = { -0.180, 0, 0.037 } - commonZones["Arcane1"] = { 0.212, 0, 0.559 } - commonZones["Arcane2"] = { -0.171, 0, 0.557 } - commonZones["Tarot"] = { 0.602, 0, 0.033 } - commonZones["Accessory"] = { 0.602, 0, 0.555 } - commonZones["Blank1"] = { 1.758, 0, 0.040 } - commonZones["Blank2"] = { 1.754, 0, 0.563 } - commonZones["Blank3"] = { 1.371, 0, 0.038 } - commonZones["Blank4"] = { 1.371, 0, 0.558 } - commonZones["Blank5"] = { 0.98, 0, 0.035 } - commonZones["Blank6"] = { 0.977, 0, 0.556 } - commonZones["Threat1"] = { -0.911, 0, -0.625 } - commonZones["Threat2"] = { -0.454, 0, -0.625 } - commonZones["Threat3"] = { 0.002, 0, -0.625 } - commonZones["Threat4"] = { 0.459, 0, -0.625 } + -- local coordinates for each playermat + local commonZones = {} + commonZones["Investigator"] = Vector(-1.177, 0, 0.002) + commonZones["Deck"] = Vector(-1.82, 0, 0) + commonZones["Discard"] = Vector(-1.82, 0, 0.61) + commonZones["Ally"] = Vector(-0.616, 0, 0.024) + commonZones["Body"] = Vector(-0.631, 0, 0.551) + commonZones["Hand1"] = Vector(0.217, 0, 0.035) + commonZones["Hand2"] = Vector(-0.177, 0, 0.032) + commonZones["Arcane1"] = Vector(0.212, 0, 0.559) + commonZones["Arcane2"] = Vector(-0.174, 0, 0.551) + commonZones["Tarot"] = Vector(0.602, 0, 0.033) + commonZones["Accessory"] = Vector(0.605, 0, 0.555) + commonZones["Blank1"] = Vector(1.758, 0, 0.040) + commonZones["Blank2"] = Vector(1.754, 0, 0.563) + commonZones["Blank3"] = Vector(1.371, 0, 0.038) + commonZones["Blank4"] = Vector(1.371, 0, 0.558) + commonZones["Blank5"] = Vector(0.98, 0, 0.035) + commonZones["Blank6"] = Vector(0.977, 0, 0.556) + commonZones["Threat1"] = Vector(-0.911, 0, -0.625) + commonZones["Threat2"] = Vector(-0.454, 0, -0.625) + commonZones["Threat3"] = Vector(0.002, 0, -0.625) + commonZones["Threat4"] = Vector(0.459, 0, -0.625) - local zoneData = {} - zoneData["White"] = {} - zoneData["White"]["Investigator"] = commonZones["Investigator"] - zoneData["White"]["Deck"] = commonZones["Deck"] - zoneData["White"]["Discard"] = commonZones["Discard"] - zoneData["White"]["Ally"] = commonZones["Ally"] - zoneData["White"]["Body"] = commonZones["Body"] - zoneData["White"]["Hand1"] = commonZones["Hand1"] - zoneData["White"]["Hand2"] = commonZones["Hand2"] - zoneData["White"]["Arcane1"] = commonZones["Arcane1"] - zoneData["White"]["Arcane2"] = commonZones["Arcane2"] - zoneData["White"]["Tarot"] = commonZones["Tarot"] - zoneData["White"]["Accessory"] = commonZones["Accessory"] - zoneData["White"]["Blank1"] = commonZones["Blank1"] - zoneData["White"]["Blank2"] = commonZones["Blank2"] - zoneData["White"]["Blank3"] = commonZones["Blank3"] - zoneData["White"]["Blank4"] = commonZones["Blank4"] - zoneData["White"]["Blank5"] = commonZones["Blank5"] - zoneData["White"]["Blank6"] = commonZones["Blank6"] - zoneData["White"]["Threat1"] = commonZones["Threat1"] - zoneData["White"]["Threat2"] = commonZones["Threat2"] - zoneData["White"]["Threat3"] = commonZones["Threat3"] - zoneData["White"]["Threat4"] = commonZones["Threat4"] - zoneData["White"]["Minicard"] = { -1, 0, -1.45 } - zoneData["White"]["SetAside1"] = { 2.35, 0, -0.520 } - zoneData["White"]["SetAside2"] = { 2.35, 0, 0.042 } - zoneData["White"]["SetAside3"] = { 2.35, 0, 0.605 } - zoneData["White"]["UnderSetAside3"] = { 2.50, 0, 0.805 } - zoneData["White"]["SetAside4"] = { 2.78, 0, -0.520 } - zoneData["White"]["SetAside5"] = { 2.78, 0, 0.042 } - zoneData["White"]["SetAside6"] = { 2.78, 0, 0.605 } - zoneData["White"]["UnderSetAside6"] = { 2.93, 0, 0.805 } - zoneData["White"]["AboveSetAside"] = { 2.35, 0, -1.069 } - zoneData["White"]["BelowSetAside"] = { 2.85, 0, 1.650 } + -- local coordinates for white / green (inverted X for orange / red) + local mirrorZones = {} + mirrorZones["Minicard"] = Vector(-1, 0, -1.45) + mirrorZones["SetAside1"] = Vector(2.35, 0, -0.520) + mirrorZones["SetAside2"] = Vector(2.35, 0, 0.042) + mirrorZones["SetAside3"] = Vector(2.35, 0, 0.605) + mirrorZones["UnderSetAside3"] = Vector(2.50, 0, 0.805) + mirrorZones["SetAside4"] = Vector(2.78, 0, -0.520) + mirrorZones["SetAside5"] = Vector(2.78, 0, 0.042) + mirrorZones["SetAside6"] = Vector(2.78, 0, 0.605) + mirrorZones["UnderSetAside6"] = Vector(2.93, 0, 0.805) + mirrorZones["AboveSetAside"] = Vector(2.35, 0, -1.069) + mirrorZones["BelowSetAside"] = Vector(2.85, 0, 1.650) - zoneData["Orange"] = {} - zoneData["Orange"]["Investigator"] = commonZones["Investigator"] - zoneData["Orange"]["Deck"] = commonZones["Deck"] - zoneData["Orange"]["Discard"] = commonZones["Discard"] - zoneData["Orange"]["Ally"] = commonZones["Ally"] - zoneData["Orange"]["Body"] = commonZones["Body"] - zoneData["Orange"]["Hand1"] = commonZones["Hand1"] - zoneData["Orange"]["Hand2"] = commonZones["Hand2"] - zoneData["Orange"]["Arcane1"] = commonZones["Arcane1"] - zoneData["Orange"]["Arcane2"] = commonZones["Arcane2"] - zoneData["Orange"]["Tarot"] = commonZones["Tarot"] - zoneData["Orange"]["Accessory"] = commonZones["Accessory"] - zoneData["Orange"]["Blank1"] = commonZones["Blank1"] - zoneData["Orange"]["Blank2"] = commonZones["Blank2"] - zoneData["Orange"]["Blank3"] = commonZones["Blank3"] - zoneData["Orange"]["Blank4"] = commonZones["Blank4"] - zoneData["Orange"]["Blank5"] = commonZones["Blank5"] - zoneData["Orange"]["Blank6"] = commonZones["Blank6"] - zoneData["Orange"]["Threat1"] = commonZones["Threat1"] - zoneData["Orange"]["Threat2"] = commonZones["Threat2"] - zoneData["Orange"]["Threat3"] = commonZones["Threat3"] - zoneData["Orange"]["Threat4"] = commonZones["Threat4"] - zoneData["Orange"]["Minicard"] = { 1, 0, -1.45 } - zoneData["Orange"]["SetAside1"] = { -2.35, 0, -0.520 } - zoneData["Orange"]["SetAside2"] = { -2.35, 0, 0.042} - zoneData["Orange"]["SetAside3"] = { -2.35, 0, 0.605 } - zoneData["Orange"]["UnderSetAside3"] = { -2.50, 0, 0.805 } - zoneData["Orange"]["SetAside4"] = { -2.78, 0, -0.520 } - zoneData["Orange"]["SetAside5"] = { -2.78, 0, 0.042 } - zoneData["Orange"]["SetAside6"] = { -2.78, 0, 0.605 } - zoneData["Orange"]["UnderSetAside6"] = { -2.93, 0, 0.805 } - zoneData["Orange"]["AboveSetAside"] = { -2.35, 0, -1.069 } - zoneData["Orange"]["BelowSetAside"] = { -2.85, 0, 1.650 } + local zoneData = {} + zoneData["White"] = {} + zoneData["Orange"] = {} + + -- copy common coordinates + for zoneName, zonePos in pairs(commonZones) do + zoneData["White"][zoneName] = zonePos + zoneData["Orange"][zoneName] = zonePos + end + + -- copy mirrored coordinates + for zoneName, zonePos in pairs(mirrorZones) do + zoneData["White"][zoneName] = zonePos + zoneData["Orange"][zoneName] = zonePos * Vector(-1, 1, 1) + end -- Green positions are the same as White and Red the same as Orange zoneData["Red"] = zoneData["Orange"] @@ -127,13 +89,10 @@ do ---@param zoneName string Name of the zone to get the position for. See Zones object documentation for a list of valid zones. ---@return tts__Vector|nil: Global position table, or nil if an invalid player color or zone is specified Zones.getZonePosition = function(playerColor, zoneName) - if (playerColor ~= "Red" - and playerColor ~= "Orange" - and playerColor ~= "White" - and playerColor ~= "Green") then - return nil + if zoneData[playerColor] then + return playermatApi.transformLocalPosition(zoneData[playerColor][zoneName], playerColor) end - return playermatApi.transformLocalPosition(zoneData[playerColor][zoneName], playerColor) + return nil end -- Return the global rotation for a card on the given player mat, based on its zone. @@ -144,8 +103,8 @@ do -- Z rotation to place the card face up or face down. Zones.getDefaultCardRotation = function(playerColor, zoneName) local cardRotation = playermatApi.returnRotation(playerColor) - if zoneName == "Deck" then - cardRotation = cardRotation + Vector(0, 0, 180) + if zoneName == "Deck" or zoneName == "UnderSetAside3" or zoneName == "UnderSetAside6" then + cardRotation = cardRotation:setAt("z", 180) end return cardRotation end