From 756223274f315190be59c477f5d606a82239a01d Mon Sep 17 00:00:00 2001 From: Chr1Z93 Date: Mon, 4 Mar 2024 22:19:17 +0100 Subject: [PATCH 001/157] allcards bag speed up --- .../HonedInstinct.1cde62.gmnotes | 10 +-- .../RunicAxe.7cdb0a.gmnotes | 4 +- src/playercards/AllCardsBag.ttslua | 77 ++++++++++--------- 3 files changed, 48 insertions(+), 43 deletions(-) diff --git a/objects/AllPlayerCards.15bb07/HonedInstinct.1cde62.gmnotes b/objects/AllPlayerCards.15bb07/HonedInstinct.1cde62.gmnotes index eeccbba3..55cccc9f 100644 --- a/objects/AllPlayerCards.15bb07/HonedInstinct.1cde62.gmnotes +++ b/objects/AllPlayerCards.15bb07/HonedInstinct.1cde62.gmnotes @@ -10,27 +10,27 @@ { "name": "Reflex Response", "xp": 1, - "text": "Add the following play condition: “\u003d You take damage or horror.”" + "text": "Add the following play condition: “- You take damage or horror.”" }, { "name": "Situational Awareness", "xp": 1, - "text": "Add the following play condition: “\u003d A location enters play or is revealed.”" + "text": "Add the following play condition: “- A location enters play or is revealed.”" }, { "name": "Killer Instinct", "xp": 1, - "text": "Add the following play condition: “\u003d An enemy engages you.”" + "text": "Add the following play condition: “- An enemy engages you.”" }, { "name": "Gut Reaction", "xp": 1, - "text": "Add the following play condition: “\u003d A treachery enters your threat area .”" + "text": "Add the following play condition: “- A treachery enters your threat area .”" }, { "name": "Muscle Memory", "xp": 1, - "text": "Add the following play condition: “\u003d You play an asset.”" + "text": "Add the following play condition: “- You play an asset.”" }, { "name": "Sharpened Talent", diff --git a/objects/AllPlayerCards.15bb07/RunicAxe.7cdb0a.gmnotes b/objects/AllPlayerCards.15bb07/RunicAxe.7cdb0a.gmnotes index 7ebbcb1a..095f48d8 100644 --- a/objects/AllPlayerCards.15bb07/RunicAxe.7cdb0a.gmnotes +++ b/objects/AllPlayerCards.15bb07/RunicAxe.7cdb0a.gmnotes @@ -33,7 +33,7 @@ { "name": "Inscription of the Elders", "xp": 1, - "text": "Add this inscription: “⟐ Elders - If this attack succeeds by an amount equal to or grather than your location\u0027s shroud, discover 1 clue at your location.”" + "text": "Add this inscription: “⟐ Elders - If this attack succeeds by an amount equal to or grather than your location's shroud, discover 1 clue at your location.”" }, { "name": "Inscription of the Hunt", @@ -53,7 +53,7 @@ { "name": "Saga", "xp": 3, - "text": "Replenish 2 of Runic Axe\u0027s charges at the start of each round, instead of only one", + "text": "Replenish 2 of Runic Axe's charges at the start of each round, instead of only one", "replaces": { "uses": [ { diff --git a/src/playercards/AllCardsBag.ttslua b/src/playercards/AllCardsBag.ttslua index 33d6515d..346e228c 100644 --- a/src/playercards/AllCardsBag.ttslua +++ b/src/playercards/AllCardsBag.ttslua @@ -60,45 +60,39 @@ end -- Create the card indexes by iterating all cards in the bag, parsing their -- metadata, and creating the keyed lookup tables for the cards. This is a -- coroutine which will spread the workload by processing 20 cards before --- yielding. Based on the current count of cards this will require --- approximately 60 frames to complete. +-- yielding. function buildIndex() + local start = os.time() local cardCount = 0 indexingDone = false - if (self.getData().ContainedObjects == nil) then - return 1 - end - for i, cardData in ipairs(self.getData().ContainedObjects) do - local cardMetadata = JSON.decode(cardData.GMNotes) - if (cardMetadata ~= nil) then + + -- process the allcardsbag itself + for _, cardData in ipairs(self.getData().ContainedObjects) do + -- using the more efficient 'json.parse()' to speed this process up + local cardMetadata = json.parse(cardData.GMNotes) + if cardMetadata then addCardToIndex(cardData, cardMetadata) cardCount = cardCount + 1 - if cardCount > 9 then + if cardCount > 19 then cardCount = 0 coroutine.yield(0) end end end - local hotfixBags = getObjectsWithTag("AllCardsHotfix") - for _, hotfixBag in ipairs(hotfixBags) do - if (#hotfixBag.getObjects() > 0) then - for i, cardData in ipairs(hotfixBag.getData().ContainedObjects) do - if cardData.ContainedObjects then - for j, deepCardData in ipairs(cardData.ContainedObjects) do - local deepCardMetadata = JSON.decode(deepCardData.GMNotes) - if deepCardMetadata ~= nil then - addCardToIndex(deepCardData, deepCardMetadata) - cardCount = cardCount + 1 - if cardCount > 9 then - cardCount = 0 - coroutine.yield(0) - end - end - end - else - local cardMetadata = JSON.decode(cardData.GMNotes) - if cardMetadata ~= nil then - addCardToIndex(cardData, cardMetadata) + log(os.time() - start) + + -- process hotfix bags (and the additional playercards bag) + for _, hotfixBag in ipairs(getObjectsWithTag("AllCardsHotfix")) do + local hotfixData = hotfixBag.getData() + if not hotfixData.ContainedObjects then break end + + for _, cardData in ipairs(hotfixData.ContainedObjects) do + -- process containers + if cardData.ContainedObjects then + for _, deepCardData in ipairs(cardData.ContainedObjects) do + local deepCardMetadata = json.parse(deepCardData.GMNotes) + if deepCardMetadata ~= nil then + addCardToIndex(deepCardData, deepCardMetadata) cardCount = cardCount + 1 if cardCount > 9 then cardCount = 0 @@ -106,11 +100,24 @@ function buildIndex() end end end + -- process single cards + else + local cardMetadata = json.parse(cardData.GMNotes) + if cardMetadata ~= nil then + addCardToIndex(cardData, cardMetadata) + cardCount = cardCount + 1 + if cardCount > 9 then + cardCount = 0 + coroutine.yield(0) + end + end end end end + log(os.time() - start) buildSupplementalIndexes() indexingDone = true + log(os.time() - start) return 1 end @@ -118,21 +125,19 @@ end ---@param cardData table TTS object data for the card ---@param cardMetadata table SCED metadata for the card function addCardToIndex(cardData, cardMetadata) + local dataTable = { data = cardData, metadata = cardMetadata } + -- use the ZoopGuid as fallback if no id present - if cardMetadata.id == nil and cardMetadata.TtsZoopGuid then - cardMetadata.id = cardMetadata.TtsZoopGuid - end - cardIdIndex[cardMetadata.id] = { data = cardData, metadata = cardMetadata } - if (cardMetadata.alternate_ids ~= nil) then + cardIdIndex[cardMetadata.id or cardMetadata.TtsZoopGuid] = dataTable + if cardMetadata.alternate_ids ~= nil then for _, alternateId in ipairs(cardMetadata.alternate_ids) do - cardIdIndex[alternateId] = { data = cardData, metadata = cardMetadata } + cardIdIndex[alternateId] = dataTable end end end function buildSupplementalIndexes() for cardId, card in pairs(cardIdIndex) do - local cardData = card.data local cardMetadata = card.metadata -- If the ID key and the metadata ID don't match this is a duplicate card created by an -- alternate_id, and we should skip it From d930b97da81d3ced7c256af7c105ba127e377341 Mon Sep 17 00:00:00 2001 From: Chr1Z93 Date: Mon, 4 Mar 2024 22:33:22 +0100 Subject: [PATCH 002/157] removed log statements --- src/playercards/AllCardsBag.ttslua | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/playercards/AllCardsBag.ttslua b/src/playercards/AllCardsBag.ttslua index 346e228c..8c12d906 100644 --- a/src/playercards/AllCardsBag.ttslua +++ b/src/playercards/AllCardsBag.ttslua @@ -62,7 +62,6 @@ end -- coroutine which will spread the workload by processing 20 cards before -- yielding. function buildIndex() - local start = os.time() local cardCount = 0 indexingDone = false @@ -79,7 +78,6 @@ function buildIndex() end end end - log(os.time() - start) -- process hotfix bags (and the additional playercards bag) for _, hotfixBag in ipairs(getObjectsWithTag("AllCardsHotfix")) do @@ -114,10 +112,8 @@ function buildIndex() end end end - log(os.time() - start) buildSupplementalIndexes() indexingDone = true - log(os.time() - start) return 1 end From a42440013725d6cd27d43a9d9c8a3a6008445228 Mon Sep 17 00:00:00 2001 From: dscarpac Date: Wed, 6 Mar 2024 11:00:10 -0600 Subject: [PATCH 003/157] version 1 --- modsettings/CustomUIAssets.json | 15 +++ .../NkosiMabati3.6c5628.json | 4 +- src/playercards/cards/NkosiMabati3.ttslua | 110 ++++++++++++++++++ xml/playercards/NkosiMabati3.xml | 72 ++++++++++++ 4 files changed, 199 insertions(+), 2 deletions(-) create mode 100644 src/playercards/cards/NkosiMabati3.ttslua create mode 100644 xml/playercards/NkosiMabati3.xml diff --git a/modsettings/CustomUIAssets.json b/modsettings/CustomUIAssets.json index 3f31c3b3..7853f75d 100644 --- a/modsettings/CustomUIAssets.json +++ b/modsettings/CustomUIAssets.json @@ -238,5 +238,20 @@ "Name": "box-cover-mask-wide", "Type": 0, "URL": "http://cloud-3.steamusercontent.com/ugc/2115061298538827369/A20C2ECB8ECDC1B0AD8B2B38F68CA1C1F5E07D37/" + }, + { + "Name": "token-skull", + "Type": 0, + "URL": "http://cloud-3.steamusercontent.com/ugc/2380784374775547231/E0FEEF462DE4E7704832CA2415D0D027A6BF5041/" + }, + { + "Name": "token-bless", + "Type": 0, + "URL": "http://cloud-3.steamusercontent.com/ugc/2380784374775547028/7855033DE0EB1FDDF706E1303054D35FE0902532/" + }, + { + "Name": "token-curse", + "Type": 0, + "URL": "http://cloud-3.steamusercontent.com/ugc/2380784374775547135/2360372CBE9452CB7B4D135BE13BBA6D46B7D427/" } ] diff --git a/objects/AllPlayerCards.15bb07/NkosiMabati3.6c5628.json b/objects/AllPlayerCards.15bb07/NkosiMabati3.6c5628.json index e937c8b1..0a08a89d 100644 --- a/objects/AllPlayerCards.15bb07/NkosiMabati3.6c5628.json +++ b/objects/AllPlayerCards.15bb07/NkosiMabati3.6c5628.json @@ -33,7 +33,7 @@ "IgnoreFoW": false, "LayoutGroupSortIndex": 0, "Locked": false, - "LuaScript": "", + "LuaScript": "require(\"playercards/cards/NkosiMabati3\")", "LuaScriptState": "", "MeasureMovement": false, "Name": "Card", @@ -58,5 +58,5 @@ "scaleZ": 1 }, "Value": 0, - "XmlUI": "" + "XmlUI": "\u003cInclude src=\"playercards/NkosiMabati3.xml\"/\u003e" } diff --git a/src/playercards/cards/NkosiMabati3.ttslua b/src/playercards/cards/NkosiMabati3.ttslua new file mode 100644 index 00000000..d8e416a0 --- /dev/null +++ b/src/playercards/cards/NkosiMabati3.ttslua @@ -0,0 +1,110 @@ +local playmatApi = require("playermat/PlaymatApi") +local guidReferenceApi = require("core/GUIDReferenceApi") +local chaosBagApi = require("chaosbag/ChaosBagApi") + +function onSave() + return JSON.encode() +end + +function onLoad(savedData) + self.addContextMenuItem("Enable Helper", createButtons) + self.addContextMenuItem("Clear Helper", deleteButtons) +end + +-- Create buttons to choose sigil +function createButtons() + self.clearContextMenu() + self.addContextMenuItem("Clear Helper", deleteButtons) + self.UI.show("choose") + self.UI.show("sigils") +end + +-- Delete button and remove sigil +function deleteButtons() + self.clearContextMenu() + self.addContextMenuItem("Enable Helper", createButtons) + self.UI.hide("resolve_skull") +end + +function chooseSigil(_,_,id) + if id == "Bless" then + sigil = "Bless" + self.UI.hide("sigils") + self.UI.hide("choose") + self.UI.show("resolve_bless") + elseif id == "Curse" then + sigil = "Curse" + self.UI.hide("sigils") + self.UI.hide("choose") + self.UI.show("resolve_curse") + else + sigil = "Skull" + self.UI.hide("sigils") + self.UI.hide("choose") + self.UI.show("resolve_skull") + end + log("Sigil is " .. sigil) + +end + +function resolveSigil() + local closestMatColor = playmatApi.getMatColorByPosition(self.getPosition()) + local mat = guidReferenceApi.getObjectByOwnerAndType(closestMatColor, "Playermat") + tokenType = sigil + local tokensInPlay = chaosBagApi.getTokensInPlay() + local chaosbag = chaosBagApi.findChaosBag() + for i, obj in ipairs(chaosbag.getObjects()) do + -- if there are any sigils in the bag + log(obj.name) + if obj.name == tokenType then + log(tokensInPlay) + if tokensInPlay ~= nil then + for j, token in ipairs(tokensInPlay) do + if token.getName() == "Cultist" then + -- draw XML to return token to bag + + token.UI.setXmlTable({ + { + tag="HorizontalLayout", + attributes={ + height=200, + width=600, + scale="0.3 0.3 1", + rotation="0 0 180", + position="0 120 -22", + color="rgba(0,0,0,0.7)", + }, + children={ + { + tag="Button", + attributes={ + fontSize=100, + color="White", + }, + id="hi", + value="Nkosi React", + onClick="drawSigil", + }, + } + } + }) + return + end + end + broadcastToAll("Cultist token not found in play area", "Red") + return + end + + end + + end + broadcastToAll(tokenType .. " token not found in chaos bag", "Red") + +end + +function drawSigil(_,_,id) + log(id) + --chaosBagApi.returnChaosTokenToBag(token) + tokenType = "Skull" + chaosBagApi.drawChaosToken(mat, true, tokenType, _) +end \ No newline at end of file diff --git a/xml/playercards/NkosiMabati3.xml b/xml/playercards/NkosiMabati3.xml new file mode 100644 index 00000000..b0c8b815 --- /dev/null +++ b/xml/playercards/NkosiMabati3.xml @@ -0,0 +1,72 @@ + + Choose sigil: + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From f41f4f9107e30ce2153f7e902ba5e28a9998030a Mon Sep 17 00:00:00 2001 From: Chr1Z93 Date: Mon, 25 Mar 2024 17:28:26 +0100 Subject: [PATCH 004/157] updted allcardsbag --- src/playercards/AllCardsBag.ttslua | 143 ++++++++++++----------------- 1 file changed, 57 insertions(+), 86 deletions(-) diff --git a/src/playercards/AllCardsBag.ttslua b/src/playercards/AllCardsBag.ttslua index 8c12d906..6717f055 100644 --- a/src/playercards/AllCardsBag.ttslua +++ b/src/playercards/AllCardsBag.ttslua @@ -57,25 +57,20 @@ function onObjectLeaveContainer(container, _) end end --- Create the card indexes by iterating all cards in the bag, parsing their --- metadata, and creating the keyed lookup tables for the cards. This is a --- coroutine which will spread the workload by processing 20 cards before --- yielding. +-- Create the card indexes by iterating all cards in the bag, parsing their metadata +-- and creating the keyed lookup tables for the cards. This is a coroutine which will +-- spread the workload by processing 20 cards before yielding. function buildIndex() local cardCount = 0 indexingDone = false -- process the allcardsbag itself for _, cardData in ipairs(self.getData().ContainedObjects) do - -- using the more efficient 'json.parse()' to speed this process up - local cardMetadata = json.parse(cardData.GMNotes) - if cardMetadata then - addCardToIndex(cardData, cardMetadata) - cardCount = cardCount + 1 - if cardCount > 19 then - cardCount = 0 - coroutine.yield(0) - end + addCardToIndex(cardData) + cardCount = cardCount + 1 + if cardCount > 19 then + cardCount = 0 + coroutine.yield(0) end end @@ -88,46 +83,44 @@ function buildIndex() -- process containers if cardData.ContainedObjects then for _, deepCardData in ipairs(cardData.ContainedObjects) do - local deepCardMetadata = json.parse(deepCardData.GMNotes) - if deepCardMetadata ~= nil then - addCardToIndex(deepCardData, deepCardMetadata) - cardCount = cardCount + 1 - if cardCount > 9 then - cardCount = 0 - coroutine.yield(0) - end - end - end - -- process single cards - else - local cardMetadata = json.parse(cardData.GMNotes) - if cardMetadata ~= nil then - addCardToIndex(cardData, cardMetadata) + addCardToIndex(deepCardData) cardCount = cardCount + 1 - if cardCount > 9 then + if cardCount > 19 then cardCount = 0 coroutine.yield(0) end end + -- process single cards + else + addCardToIndex(cardData) + cardCount = cardCount + 1 + if cardCount > 19 then + cardCount = 0 + coroutine.yield(0) + end end end end + buildSupplementalIndexes() indexingDone = true return 1 end --- Adds a card to any indexes it should be a part of, based on its metadata. +-- Adds a card to any indexes it should be a part of, based on its metadata ---@param cardData table TTS object data for the card ----@param cardMetadata table SCED metadata for the card -function addCardToIndex(cardData, cardMetadata) - local dataTable = { data = cardData, metadata = cardMetadata } +function addCardToIndex(cardData) + -- using the more efficient 'json.parse()' to speed this process up + local cardMetadata = json.parse(cardData.GMNotes) + if not cardMetadata then return end -- use the ZoopGuid as fallback if no id present - cardIdIndex[cardMetadata.id or cardMetadata.TtsZoopGuid] = dataTable + cardIdIndex[cardMetadata.id or cardMetadata.TtsZoopGuid] = { data = cardData, metadata = cardMetadata } + + -- also add data for alternate ids if cardMetadata.alternate_ids ~= nil then for _, alternateId in ipairs(cardMetadata.alternate_ids) do - cardIdIndex[alternateId] = dataTable + cardIdIndex[alternateId] = { data = cardData, metadata = cardMetadata } end end end @@ -135,11 +128,9 @@ end function buildSupplementalIndexes() for cardId, card in pairs(cardIdIndex) do local cardMetadata = card.metadata - -- If the ID key and the metadata ID don't match this is a duplicate card created by an - -- alternate_id, and we should skip it + -- If the ID key and the metadata ID don't match this is a duplicate card created by an alternate_id, and we should skip it if cardId == cardMetadata.id then - -- Add card to the basic weakness list, if appropriate. Some weaknesses have - -- multiple copies, and are added multiple times + -- Add card to the basic weakness list, if appropriate. Some weaknesses have multiple copies, and are added multiple times if cardMetadata.weakness then table.insert(uniqueWeaknessList, cardMetadata.id) if cardMetadata.basicWeaknessCount ~= nil then @@ -149,56 +140,31 @@ function buildSupplementalIndexes() end end - -- Add the card to the appropriate class and level indexes - local isGuardian = false - local isSeeker = false - local isMystic = false - local isRogue = false - local isSurvivor = false - local isNeutral = false - local upgradeKey - -- Excludes signature cards (which have no class or level) and alternate - -- ID entries - if (cardMetadata.class ~= nil and cardMetadata.level ~= nil) then - isGuardian = string.match(cardMetadata.class, "Guardian") - isSeeker = string.match(cardMetadata.class, "Seeker") - isMystic = string.match(cardMetadata.class, "Mystic") - isRogue = string.match(cardMetadata.class, "Rogue") - isSurvivor = string.match(cardMetadata.class, "Survivor") - isNeutral = string.match(cardMetadata.class, "Neutral") - if (cardMetadata.level > 0) then + -- Excludes signature cards (which have no class or level) + if cardMetadata.class ~= nil and cardMetadata.level ~= nil then + local upgradeKey + if cardMetadata.level > 0 then upgradeKey = "-upgrade" else upgradeKey = "-level0" end - if (isGuardian) then - table.insert(classAndLevelIndex["Guardian"..upgradeKey], cardMetadata.id) - end - if (isSeeker) then - table.insert(classAndLevelIndex["Seeker"..upgradeKey], cardMetadata.id) - end - if (isMystic) then - table.insert(classAndLevelIndex["Mystic"..upgradeKey], cardMetadata.id) - end - if (isRogue) then - table.insert(classAndLevelIndex["Rogue"..upgradeKey], cardMetadata.id) - end - if (isSurvivor) then - table.insert(classAndLevelIndex["Survivor"..upgradeKey], cardMetadata.id) - end - if (isNeutral) then - table.insert(classAndLevelIndex["Neutral"..upgradeKey], cardMetadata.id) + + -- parse classes (separated by "|") and add the card to the appropriate class and level indices + for str in cardMetadata.class:gmatch("([^|]+)") do + table.insert(classAndLevelIndex[str .. upgradeKey], cardMetadata.id) end + -- add to cycle index local cycleName = cardMetadata.cycle if cycleName ~= nil then cycleName = string.lower(cycleName) - if string.match(cycleName, "return") then - cycleName = string.sub(cycleName, 11) - end - if cycleName == "the night of the zealot" then - cycleName = "core" - end + + -- remove "return to " from cycle names + cycleName = cycleName:gsub("return to ", "") + + -- override cycle name for night of the zealot + cycleName = cycleName:gsub("the night of the zealot", "core") + if cycleIndex[cycleName] == nil then cycleIndex[cycleName] = { } end @@ -207,29 +173,34 @@ function buildSupplementalIndexes() end end end + + -- sort class and level indices for _, indexTable in pairs(classAndLevelIndex) do table.sort(indexTable, cardComparator) end + + -- sort cycle indices for _, indexTable in pairs(cycleIndex) do table.sort(indexTable) end + + -- sort weakness indices table.sort(basicWeaknessList, cardComparator) table.sort(uniqueWeaknessList, cardComparator) end --- Comparison function used to sort the class card bag indexes. Sorts by card --- level, then name, then subname. +-- Comparison function used to sort the class card bag indexes. Sorts by card level, then name, then subname. function cardComparator(id1, id2) local card1 = cardIdIndex[id1] local card2 = cardIdIndex[id2] - if (card1.metadata.level ~= card2.metadata.level) then + if card1.metadata.level ~= card2.metadata.level then return card1.metadata.level < card2.metadata.level - end - if (card1.data.Nickname ~= card2.data.Nickname) then + elseif card1.data.Nickname ~= card2.data.Nickname then return card1.data.Nickname < card2.data.Nickname + else + return card1.data.Description < card2.data.Description end - return card1.data.Description < card2.data.Description end function isIndexReady() From 7cb3545cab96344fb2f24f342c5ae17d6ff79d38 Mon Sep 17 00:00:00 2001 From: Chr1Z93 Date: Mon, 25 Mar 2024 17:36:03 +0100 Subject: [PATCH 005/157] updated onLoad functions --- src/accessories/PhaseTracker.ttslua | 2 ++ src/accessories/TokenArranger.ttslua | 6 +++--- src/core/DoomCounter.ttslua | 2 +- src/core/GenericCounter.ttslua | 8 ++++---- src/core/Global.ttslua | 11 +++++------ src/core/MasterClueCounter.ttslua | 4 +++- src/core/MythosArea.ttslua | 6 +++--- src/core/NavigationOverlayHandler.ttslua | 2 +- src/core/PlayArea.ttslua | 16 ++++++++++------ src/core/PlayAreaSelector.ttslua | 9 ++++++--- src/core/token/TokenSpawnTracker.ttslua | 12 +++++------- src/playercards/PlayerCardPanel.ttslua | 6 +++--- src/playermat/InvestigatorSkillTracker.ttslua | 4 +++- src/playermat/Playmat.ttslua | 17 ++++++++--------- src/util/ConnectionDrawingTool.ttslua | 4 +++- src/util/TokenRemover.ttslua | 4 ++-- 16 files changed, 62 insertions(+), 51 deletions(-) diff --git a/src/accessories/PhaseTracker.ttslua b/src/accessories/PhaseTracker.ttslua index 72e79520..d77f2be7 100644 --- a/src/accessories/PhaseTracker.ttslua +++ b/src/accessories/PhaseTracker.ttslua @@ -11,6 +11,8 @@ local phaseImages = { "http://cloud-3.steamusercontent.com/ugc/982233321870237261/C287CAED2423970F33E72D6C7415CBEC6794C533/" } +local phaseId, broadcastChange + function onSave() return JSON.encode({ phaseId = phaseId, diff --git a/src/accessories/TokenArranger.ttslua b/src/accessories/TokenArranger.ttslua index 6064fa0e..159a1a4b 100644 --- a/src/accessories/TokenArranger.ttslua +++ b/src/accessories/TokenArranger.ttslua @@ -55,9 +55,9 @@ function onSave() end -- loading data, button creation and initial layouting -function onLoad(saveState) - if saveState ~= nil and saveState ~= "" then - local loadedData = JSON.decode(saveState) +function onLoad(savedData) + if savedData and savedData ~= "" then + local loadedData = JSON.decode(savedData) tokenPrecedence = loadedData.tokenPrecedence percentage = loadedData.percentage includeDrawnTokens = loadedData.includeDrawnTokens diff --git a/src/core/DoomCounter.ttslua b/src/core/DoomCounter.ttslua index eb6ce5cc..2057389b 100644 --- a/src/core/DoomCounter.ttslua +++ b/src/core/DoomCounter.ttslua @@ -15,7 +15,7 @@ val = 0 function onSave() return JSON.encode({ val, options }) end function onLoad(savedData) - if savedData ~= "" then + if savedData and savedData ~= "" then local loadedData = JSON.decode(savedData) val = loadedData[1] options = loadedData[2] diff --git a/src/core/GenericCounter.ttslua b/src/core/GenericCounter.ttslua index b8409383..8f64d949 100644 --- a/src/core/GenericCounter.ttslua +++ b/src/core/GenericCounter.ttslua @@ -5,21 +5,20 @@ val = 0 function onSave() return JSON.encode(val) end function onLoad(savedData) - if savedData ~= nil then + if savedData and savedData ~= "" then val = JSON.decode(savedData) end local name = self.getName() - local position = {} + local position = { 0, 0.06, 0 } + -- set position of label depending on object if name == "Damage" or name == "Resources" or name == "Resource Counter" then position = { 0, 0.06, 0.1 } elseif name == "Horror" then position = { -0.025, 0.06, -0.025 } elseif name == "Elder Sign Counter" or name == "Auto-fail Counter" then position = { 0, 0.1, 0 } - else - position = { 0, 0.06, 0 } end self.createButton({ @@ -35,6 +34,7 @@ function onLoad(savedData) color = { 0, 0, 0, 0 } }) + -- add context menu entries self.addContextMenuItem("Add 5", function() updateVal(val + 5) end) self.addContextMenuItem("Subtract 5", function() updateVal(val - 5) end) self.addContextMenuItem("Add 10", function() updateVal(val + 10) end) diff --git a/src/core/Global.ttslua b/src/core/Global.ttslua index c5d23006..4f244fe3 100644 --- a/src/core/Global.ttslua +++ b/src/core/Global.ttslua @@ -127,19 +127,18 @@ function onSave() end function onLoad(savedData) - if savedData then - loadedData = JSON.decode(savedData) + if savedData and savedData ~= "" then + local loadedData = JSON.decode(savedData) optionPanel = loadedData.optionPanel acknowledgedUpgradeVersions = loadedData.acknowledgedUpgradeVersions - updateOptionPanelState() + chaosTokensLastMatGUID = loadedData.chaosTokensLastMatGUID -- restore saved state for drawn chaos tokens for _, guid in ipairs(loadedData.chaosTokensGUID or {}) do table.insert(chaosTokens, getObjectFromGUID(guid)) end - chaosTokensLastMatGUID = loadedData.chaosTokensLastMatGUID - else - print("Saved state could not be found!") + + updateOptionPanelState() end for _, guid in ipairs(NOT_INTERACTABLE) do diff --git a/src/core/MasterClueCounter.ttslua b/src/core/MasterClueCounter.ttslua index 9b1d837e..ec2cc78a 100644 --- a/src/core/MasterClueCounter.ttslua +++ b/src/core/MasterClueCounter.ttslua @@ -7,9 +7,10 @@ useClickableCounters = false function onSave() return JSON.encode(useClickableCounters) end function onLoad(savedData) - if savedData ~= nil then + if savedData and savedData ~= "" then useClickableCounters = JSON.decode(savedData) end + self.createButton({ label = "0", click_function = "removeAllPlayerClues", @@ -23,6 +24,7 @@ function onLoad(savedData) font_color = { 1, 1, 1, 100 }, color = { 0, 0, 0, 0 } }) + Wait.time(sumClues, 2, -1) end diff --git a/src/core/MythosArea.ttslua b/src/core/MythosArea.ttslua index 34ad046c..b9494169 100644 --- a/src/core/MythosArea.ttslua +++ b/src/core/MythosArea.ttslua @@ -23,9 +23,9 @@ local collisionEnabled = false local currentScenario, useFrontData, tokenData local TRASH, DATA_HELPER -function onLoad(saveState) - if saveState ~= nil then - local loadedState = JSON.decode(saveState) or {} +function onLoad(savedData) + if savedData and savedData ~= "" then + local loadedState = JSON.decode(savedData) or {} currentScenario = loadedState.currentScenario or "" useFrontData = loadedState.useFrontData or true tokenData = loadedState.tokenData or {} diff --git a/src/core/NavigationOverlayHandler.ttslua b/src/core/NavigationOverlayHandler.ttslua index 21a09a3d..e79f5184 100644 --- a/src/core/NavigationOverlayHandler.ttslua +++ b/src/core/NavigationOverlayHandler.ttslua @@ -82,7 +82,7 @@ function onSave() end function onLoad(savedData) - if savedData ~= "" then + if savedData and savedData ~= "" then local loadedData = JSON.decode(savedData) visibility = loadedData.visibility claims = loadedData.claims diff --git a/src/core/PlayArea.ttslua b/src/core/PlayArea.ttslua index 13a62947..3cf0ebe7 100644 --- a/src/core/PlayArea.ttslua +++ b/src/core/PlayArea.ttslua @@ -60,12 +60,16 @@ function onSave() end function onLoad(savedData) - self.interactable = false -- this needs to be here since the playarea will be reloaded when the image changes - local loadedData = JSON.decode(savedData) or {} - locations = loadedData.trackedLocations or {} - currentScenario = loadedData.currentScenario - connectionColor = loadedData.connectionColor or { 0.4, 0.4, 0.4, 1 } - connectionsEnabled = loadedData.connectionsEnabled or true + if savedData and savedData ~= "" then + local loadedData = JSON.decode(savedData) or {} + locations = loadedData.trackedLocations or {} + currentScenario = loadedData.currentScenario + connectionColor = loadedData.connectionColor or { 0.4, 0.4, 0.4, 1 } + connectionsEnabled = loadedData.connectionsEnabled or true + end + + -- this needs to be here since the playarea will be reloaded when the image changes + self.interactable = false Wait.time(function() collisionEnabled = true end, 0.1) end diff --git a/src/core/PlayAreaSelector.ttslua b/src/core/PlayAreaSelector.ttslua index 8a77b9b0..e5431e1a 100644 --- a/src/core/PlayAreaSelector.ttslua +++ b/src/core/PlayAreaSelector.ttslua @@ -6,6 +6,12 @@ local typeIndex, selectionIndex, plainNameCache function onSave() return JSON.encode({ typeIndex = typeIndex, selectionIndex = selectionIndex }) end function onLoad(savedData) + if savedData and savedData ~= "" then + local loadedData = JSON.decode(savedData) or {} + typeIndex = loadedData.typeIndex or 1 + selectionIndex = loadedData.selectionIndex or 1 + end + self.createButton({ function_owner = self, click_function = "onClick_toggleGallery", @@ -16,9 +22,6 @@ function onLoad(savedData) color = { 1, 1, 1, 0 } }) - local loadedData = JSON.decode(savedData) or {} - typeIndex = loadedData.typeIndex or 1 - selectionIndex = loadedData.selectionIndex or 1 Wait.time(updatePlayAreaGallery, 0.5) math.randomseed(os.time()) end diff --git a/src/core/token/TokenSpawnTracker.ttslua b/src/core/token/TokenSpawnTracker.ttslua index 02aaf415..0340ae91 100644 --- a/src/core/token/TokenSpawnTracker.ttslua +++ b/src/core/token/TokenSpawnTracker.ttslua @@ -2,15 +2,13 @@ local spawnedCardGuids = {} function onSave() return JSON.encode({ cards = spawnedCardGuids }) end -function onLoad(saveState) - if saveState ~= nil then - local saveTable = JSON.decode(saveState) or {} - spawnedCardGuids = saveTable.cards or {} +function onLoad(savedData) + if savedData and savedData ~= "" then + local loadedData = JSON.decode(savedData) or {} + spawnedCardGuids = loadedData.cards or {} end - createResetMenuItems() -end -function createResetMenuItems() + -- context menu entries self.addContextMenuItem("Reset All", resetAll) self.addContextMenuItem("Reset Locations", resetAllLocations) self.addContextMenuItem("Reset Player Cards", resetAllAssetAndEvents) diff --git a/src/playercards/PlayerCardPanel.ttslua b/src/playercards/PlayerCardPanel.ttslua index 41089e3c..d1ae7311 100644 --- a/src/playercards/PlayerCardPanel.ttslua +++ b/src/playercards/PlayerCardPanel.ttslua @@ -103,13 +103,13 @@ function onSave() end function onLoad(savedData) - arkhamDb.initialize() - if (savedData ~= nil) then + if savedData and savedData ~= "" then local saveState = JSON.decode(savedData) or { } - if (saveState.spawnBagState ~= nil) then + if saveState.spawnBagState ~= nil then spawnBag.loadFromSave(saveState.spawnBagState) end end + arkhamDb.initialize() buildExcludedWeaknessList() createButtons() end diff --git a/src/playermat/InvestigatorSkillTracker.ttslua b/src/playermat/InvestigatorSkillTracker.ttslua index c709b1a1..13bd2429 100644 --- a/src/playermat/InvestigatorSkillTracker.ttslua +++ b/src/playermat/InvestigatorSkillTracker.ttslua @@ -11,7 +11,9 @@ function onSave() return JSON.encode(stats) end -- load stats and make buttons (left to right) function onLoad(savedData) - stats = JSON.decode(savedData) or { 1, 1, 1, 1 } + if savedData and savedData ~= "" then + stats = JSON.decode(savedData) or { 1, 1, 1, 1 } + end for index = 1, 4 do local fnName = "buttonClick" .. index diff --git a/src/playermat/Playmat.ttslua b/src/playermat/Playmat.ttslua index fa129b32..e1dc0390 100644 --- a/src/playermat/Playmat.ttslua +++ b/src/playermat/Playmat.ttslua @@ -95,7 +95,14 @@ function onSave() }) end -function onLoad(saveState) +function onLoad(savedData) + if savedData and savedData ~= "" then + local loadedData = JSON.decode(savedData) + playerColor = loadedData.playerColor + activeInvestigatorId = loadedData.activeInvestigatorId + isDrawButtonVisible = loadedData.isDrawButtonVisible + end + self.interactable = false -- get object references to owned objects @@ -135,14 +142,6 @@ function onLoad(saveState) font_size = 180 }) - -- save state loading - local state = JSON.decode(saveState) - if state ~= nil then - playerColor = state.playerColor - activeInvestigatorId = state.activeInvestigatorId - isDrawButtonVisible = state.isDrawButtonVisible - end - showDrawButton(isDrawButtonVisible) math.randomseed(os.time()) Wait.time(function() collisionEnabled = true end, 0.1) diff --git a/src/util/ConnectionDrawingTool.ttslua b/src/util/ConnectionDrawingTool.ttslua index fe182f5a..89fdf225 100644 --- a/src/util/ConnectionDrawingTool.ttslua +++ b/src/util/ConnectionDrawingTool.ttslua @@ -6,7 +6,9 @@ function onSave() end function onLoad(savedData) - lines = JSON.decode(savedData) or {} + if savedData and savedData ~= "" then + lines = JSON.decode(savedData) or {} + end end -- create timer when numpad 0 is pressed diff --git a/src/util/TokenRemover.ttslua b/src/util/TokenRemover.ttslua index d1a76c00..62369544 100644 --- a/src/util/TokenRemover.ttslua +++ b/src/util/TokenRemover.ttslua @@ -1,8 +1,8 @@ -local zone = nil +local zone -- general code function onSave() - return JSON.encode(zone and zone.getGUID() or nil) + return JSON.encode(zone and zone.getGUID()) end function onLoad(savedData) From b28c9c08cd02dd5148a2f24b12aed31d298ff916 Mon Sep 17 00:00:00 2001 From: dscarpac Date: Thu, 11 Apr 2024 20:38:33 -0500 Subject: [PATCH 006/157] more updates --- modsettings/CustomUIAssets.json | 35 +++ .../NkosiMabati3.6c5628.json | 2 +- src/chaosbag/ChaosBagApi.ttslua | 5 +- src/core/Global.ttslua | 29 ++- src/playercards/cards/NkosiMabati3.ttslua | 232 ++++++++++++------ xml/playercards/NkosiMabati3.xml | 72 ------ 6 files changed, 214 insertions(+), 161 deletions(-) delete mode 100644 xml/playercards/NkosiMabati3.xml diff --git a/modsettings/CustomUIAssets.json b/modsettings/CustomUIAssets.json index 7853f75d..69bb9dee 100644 --- a/modsettings/CustomUIAssets.json +++ b/modsettings/CustomUIAssets.json @@ -54,6 +54,11 @@ "Type": 0, "URL": "http://cloud-3.steamusercontent.com/ugc/2026086584372569912/5CB461AEAE2E59D3064D90A776EB86C46081EC78/" }, + { + "Name": "font_arkhamslim", + "Type": 1, + "URL": "http://cloud-3.steamusercontent.com/ugc/2510267299454546112/8CDF773519FEC8C488569072280AC848BCC293D5/" + }, { "Name": "font_birmingham", "Type": 1, @@ -253,5 +258,35 @@ "Name": "token-curse", "Type": 0, "URL": "http://cloud-3.steamusercontent.com/ugc/2380784374775547135/2360372CBE9452CB7B4D135BE13BBA6D46B7D427/" + }, + { + "Name": "token-cultist", + "Type": 0, + "URL": "http://cloud-3.steamusercontent.com/ugc/2380784374792650461/10D8037632900AA86045BDD42A564716D5855B1B/" + }, + { + "Name": "token-tablet", + "Type": 0, + "URL": "http://cloud-3.steamusercontent.com/ugc/2380784374792650857/29DAE514E5C838C24C90ABBFFF92B1359B9A2F76/" + }, + { + "Name": "token-elder-thing", + "Type": 0, + "URL": "http://cloud-3.steamusercontent.com/ugc/2380784374792650683/1C046B6335317CA1AEBFC80645EEC18852D83D80/" + }, + { + "Name": "token-frost", + "Type": 0, + "URL": "http://cloud-3.steamusercontent.com/ugc/2380784374792650766/73E07A50BE6FD9BED266F3421B472C4BF913DE81/" + }, + { + "Name": "token-auto-fail", + "Type": 0, + "URL": "http://cloud-3.steamusercontent.com/ugc/2510267932886739653/CB7AA2D73777EF5938A6E6CD664B2ABA52B6E20A/" + }, + { + "Name": "token-custom", + "Type": 0, + "URL": "http://cloud-3.steamusercontent.com/ugc/2380784374792650571/E4C2B2B69282A4EE15FE290FF6B08BEFC8FCA65C/" } ] diff --git a/objects/AllPlayerCards.15bb07/NkosiMabati3.6c5628.json b/objects/AllPlayerCards.15bb07/NkosiMabati3.6c5628.json index 0a08a89d..add19374 100644 --- a/objects/AllPlayerCards.15bb07/NkosiMabati3.6c5628.json +++ b/objects/AllPlayerCards.15bb07/NkosiMabati3.6c5628.json @@ -58,5 +58,5 @@ "scaleZ": 1 }, "Value": 0, - "XmlUI": "\u003cInclude src=\"playercards/NkosiMabati3.xml\"/\u003e" + "XmlUI": "" } diff --git a/src/chaosbag/ChaosBagApi.ttslua b/src/chaosbag/ChaosBagApi.ttslua index 9f4db6ad..03a84693 100644 --- a/src/chaosbag/ChaosBagApi.ttslua +++ b/src/chaosbag/ChaosBagApi.ttslua @@ -71,8 +71,9 @@ do ---@param drawAdditional boolean Controls whether additional tokens should be drawn ---@param tokenType? string Name of token (e.g. "Bless") to be drawn from the bag ---@param guidToBeResolved? string GUID of the sealed token to be resolved instead of drawing a token from the bag - ChaosBagApi.drawChaosToken = function(mat, drawAdditional, tokenType, guidToBeResolved) - return Global.call("drawChaosToken", {mat = mat, drawAdditional = drawAdditional, tokenType = tokenType, guidToBeResolved = guidToBeResolved}) + ---@param returnedToken tts__Object Token to be replaced with newly drawn token + ChaosBagApi.drawChaosToken = function(mat, drawAdditional, tokenType, guidToBeResolved, returnedToken) + return Global.call("drawChaosToken", {mat = mat, drawAdditional = drawAdditional, tokenType = tokenType, guidToBeResolved = guidToBeResolved, returnedToken = returnedToken}) end -- returns a Table List of chaos token ids in the current chaos bag diff --git a/src/core/Global.ttslua b/src/core/Global.ttslua index e154deb9..3f28d194 100644 --- a/src/core/Global.ttslua +++ b/src/core/Global.ttslua @@ -257,6 +257,14 @@ function returnChaosTokenToBag(token) end end +function getTokenIndex(token) + for i, obj in ipairs(chaosTokens) do + if obj == token then + return i + end + end +end + -- Checks to see if the chaos bag can be manipulated. If a player is searching the bag when tokens -- are drawn or replaced a TTS bug can cause those tokens to vanish. Any functions which change the -- contents of the bag should check this method before doing so. @@ -295,13 +303,24 @@ function drawChaosToken(params) chaosBag.shuffle() -- add the token to the list, compute new position based on list length - tokenOffset[1] = tokenOffset[1] + (0.17 * #chaosTokens) + if params.returnedToken then + indexOfReturnedToken = getTokenIndex(params.returnedToken) + tokenPosition = params.returnedToken.getPosition() + if #chaosTokens > indexOfReturnedToken then + tokenRotation = params.mat.getRotation() + Vector(0, 0, -8) + end + returnChaosTokenToBag(params.returnedToken) + else + tokenOffset[1] = tokenOffset[1] + (0.17 * #chaosTokens) + tokenPosition = params.mat.positionToWorld(tokenOffset) + tokenRotation = params.mat.getRotation() + end local token if params.guidToBeResolved then -- resolve a sealed token from a card token = getObjectFromGUID(params.guidToBeResolved) - token.setPositionSmooth(params.mat.positionToWorld(tokenOffset)) + token.setPositionSmooth(tokenPosition) local guid = token.getGUID() local tokenType = token.getName() if tokenType == "Bless" or tokenType == "Curse" then @@ -310,13 +329,13 @@ function drawChaosToken(params) tokenArrangerApi.layout() else -- take a token from the bag, either specified or random local takeParameters = { - position = params.mat.positionToWorld(tokenOffset), - rotation = params.mat.getRotation() + position = tokenPosition, + rotation = tokenRotation } if params.tokenType then for i, lookedForToken in ipairs(chaosBag.getObjects()) do - if lookedForToken.name == params.tokenType then + if lookedForToken.nickname == params.tokenType then takeParameters.index = i - 1 end end diff --git a/src/playercards/cards/NkosiMabati3.ttslua b/src/playercards/cards/NkosiMabati3.ttslua index d8e416a0..e8643ec4 100644 --- a/src/playercards/cards/NkosiMabati3.ttslua +++ b/src/playercards/cards/NkosiMabati3.ttslua @@ -1,110 +1,180 @@ -local playmatApi = require("playermat/PlaymatApi") -local guidReferenceApi = require("core/GUIDReferenceApi") -local chaosBagApi = require("chaosbag/ChaosBagApi") +local chaosBagApi = require("chaosbag/ChaosBagApi") +local guidReferenceApi = require("core/GUIDReferenceApi") +local playmatApi = require("playermat/PlaymatApi") + +local tokenNames = { + "Skull", + "Cultist", + "Tablet", + "Elder Thing", + "Auto-fail", + "Bless", + "Curse", + "Frost", + "Custom Token" +} + +local dataForToken = { + ["Skull"] = { color = "#4A0400E6", icon = "token-skull"}, + ["Cultist"] = { color = "#173B0BE6", icon = "token-cultist"}, + ["Tablet"] = { color = "#1D2238E6", icon = "token-tablet"}, + ["Elder Thing"] = { color = "#4D2331E6", icon = "token-elder-thing"}, + ["Auto-fail"] = { color = "#9B0004E6", icon = "token-auto-fail"}, + ["Bless"] = { color = "#9D702CE6", icon = "token-bless"}, + ["Curse"] = { color = "#633A84E6", icon = "token-curse"}, + ["Frost"] = { color = "#404450E6", icon = "token-frost"}, + [""] = { color = "#77674DE6", icon = "token-custom"} +} + +local sigil function onSave() - return JSON.encode() + return JSON.encode(sigil) end function onLoad(savedData) self.addContextMenuItem("Enable Helper", createButtons) - self.addContextMenuItem("Clear Helper", deleteButtons) + sigil= JSON.decode(savedData) + if sigil and sigil ~= nil then + makeXMLButton(sigil) + self.clearContextMenu() + self.addContextMenuItem("Clear Helper", deleteButtons) + end end +function makeXMLButton(chosenToken) + self.UI.setXmlTable({ + { + tag="Button", + attributes={ + height=450, + width=1400, + rotation="0 0 180", + scale="0.1 0.1 1", + position="0 -55 -22", + padding="50 50 50 50", + font="font_teutonic-arkham", + fontSize=300, + iconWidth=400, + iconAlignment="Right", + onClick="resolveSigil", + id=sigil, + icon=dataForToken[sigil].icon, + color=dataForToken[sigil].color, + textColor="White", + }, + value="Resolve", + } + } +) +end + -- Create buttons to choose sigil -function createButtons() +function createButtons(playerColor) self.clearContextMenu() self.addContextMenuItem("Clear Helper", deleteButtons) - self.UI.show("choose") - self.UI.show("sigils") + Player[playerColor].showOptionsDialog("Choose Sigil", tokenNames, 1, + function(chosenToken) + if chosenToken == "Custom Token" then + sigil = "" + else + sigil = chosenToken + end + makeXMLButton(sigil) + end + ) end -- Delete button and remove sigil function deleteButtons() self.clearContextMenu() self.addContextMenuItem("Enable Helper", createButtons) - self.UI.hide("resolve_skull") -end - -function chooseSigil(_,_,id) - if id == "Bless" then - sigil = "Bless" - self.UI.hide("sigils") - self.UI.hide("choose") - self.UI.show("resolve_bless") - elseif id == "Curse" then - sigil = "Curse" - self.UI.hide("sigils") - self.UI.hide("choose") - self.UI.show("resolve_curse") - else - sigil = "Skull" - self.UI.hide("sigils") - self.UI.hide("choose") - self.UI.show("resolve_skull") - end - log("Sigil is " .. sigil) - + self.UI.setXml("") + sigil = nil end function resolveSigil() - local closestMatColor = playmatApi.getMatColorByPosition(self.getPosition()) - local mat = guidReferenceApi.getObjectByOwnerAndType(closestMatColor, "Playermat") - tokenType = sigil local tokensInPlay = chaosBagApi.getTokensInPlay() local chaosbag = chaosBagApi.findChaosBag() + local match = false for i, obj in ipairs(chaosbag.getObjects()) do -- if there are any sigils in the bag - log(obj.name) - if obj.name == tokenType then - log(tokensInPlay) - if tokensInPlay ~= nil then - for j, token in ipairs(tokensInPlay) do - if token.getName() == "Cultist" then - -- draw XML to return token to bag - - token.UI.setXmlTable({ - { - tag="HorizontalLayout", - attributes={ - height=200, - width=600, - scale="0.3 0.3 1", - rotation="0 0 180", - position="0 120 -22", - color="rgba(0,0,0,0.7)", - }, - children={ - { - tag="Button", - attributes={ - fontSize=100, - color="White", - }, - id="hi", - value="Nkosi React", - onClick="drawSigil", - }, - } - } - }) - return - end - end - broadcastToAll("Cultist token not found in play area", "Red") - return - end - + if obj.nickname == sigil then + match = true + break end - end - broadcastToAll(tokenType .. " token not found in chaos bag", "Red") - + if not match then + if sigil == "" then + broadcastToAll("Custom token not found in chaos bag", "Red") + else + broadcastToAll(sigil .. " token not found in chaos bag", "Red") + end + return + end + + local symbolMatch = false + + for j, token in ipairs(tokensInPlay) do + if (token.getName() == "Cultist" or token.getName() == "Elder Thing" or token.getName() == "Tablet") and token.getName() ~= sigil then + symbolMatch = true + -- draw XML to return token to bag + token.UI.setXmlTable({ + { + tag="VerticalLayout", + attributes={ + height=275, + width=275, + spacing=0, + padding="0 0 20 25", + scale="0.4 0.4 1", + rotation="0 0 180", + position="0 0 -15", + color="rgba(0,0,0,0.7)", + onClick=self.getGUID() .. "/drawSigil(" .. token.getGUID() .. ")", + }, + children={ + { + tag="Text", + attributes={ + fontSize="100", + font="font_teutonic-arkham", + color="#ffffff", + text="Nkosi", + }, + }, + { + tag="Text", + attributes={ + fontSize="125", + font="font_arkhamslim", + color="#ffffff", + text="U", + }, + }, + } + } + }) + end + end + + if not symbolMatch then + broadcastToAll("No eligible symbol token found in play area", "Red") + return + end end -function drawSigil(_,_,id) - log(id) - --chaosBagApi.returnChaosTokenToBag(token) - tokenType = "Skull" - chaosBagApi.drawChaosToken(mat, true, tokenType, _) +function drawSigil(player, tokenGUID) + + returnedToken = getObjectFromGUID(tokenGUID) + local matColor = playmatApi.getMatColorByPosition(returnedToken.getPosition()) + local mat = guidReferenceApi.getObjectByOwnerAndType(matColor, "Playermat") + + chaosBagApi.drawChaosToken(mat, true, sigil, _, returnedToken) + local tokensInPlay = chaosBagApi.getTokensInPlay() + for j, returnedToken in ipairs(tokensInPlay) do + if returnedToken.getName() == "Cultist" or returnedToken.getName() == "Elder Thing" or returnedToken.getName() == "Tablet" then + returnedToken.UI.setXml("") + end + end end \ No newline at end of file diff --git a/xml/playercards/NkosiMabati3.xml b/xml/playercards/NkosiMabati3.xml deleted file mode 100644 index b0c8b815..00000000 --- a/xml/playercards/NkosiMabati3.xml +++ /dev/null @@ -1,72 +0,0 @@ - - Choose sigil: - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file From 4955c09e65dc151aebf7228e08582b91d6e9869b Mon Sep 17 00:00:00 2001 From: dscarpac Date: Wed, 17 Apr 2024 18:07:14 -0500 Subject: [PATCH 007/157] updates --- src/core/Global.ttslua | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/core/Global.ttslua b/src/core/Global.ttslua index 3f28d194..4a5b8e58 100644 --- a/src/core/Global.ttslua +++ b/src/core/Global.ttslua @@ -317,8 +317,8 @@ function drawChaosToken(params) end local token - - if params.guidToBeResolved then -- resolve a sealed token from a card + -- resolve a sealed token from a card + if params.guidToBeResolved then token = getObjectFromGUID(params.guidToBeResolved) token.setPositionSmooth(tokenPosition) local guid = token.getGUID() @@ -327,7 +327,8 @@ function drawChaosToken(params) blessCurseManagerApi.releasedToken(tokenType, guid) end tokenArrangerApi.layout() - else -- take a token from the bag, either specified or random + -- take a token from the bag, either specified or random + else local takeParameters = { position = tokenPosition, rotation = tokenRotation @@ -345,6 +346,8 @@ function drawChaosToken(params) end -- get data for token description local name = token.getName() + if name == "" then name = "Custom" end + local tokenData = mythosAreaApi.returnTokenData().tokenData or {} local specificData = tokenData[name] or {} token.setDescription(specificData.description or "") From a878a15efd836ceccaae38a80cf53262309d81c4 Mon Sep 17 00:00:00 2001 From: dscarpac Date: Wed, 17 Apr 2024 23:08:30 -0500 Subject: [PATCH 008/157] fixed empty space --- src/core/Global.ttslua | 29 ++++++++++++++++------- src/playercards/cards/NkosiMabati3.ttslua | 27 ++++++++++++--------- 2 files changed, 36 insertions(+), 20 deletions(-) diff --git a/src/core/Global.ttslua b/src/core/Global.ttslua index 4a5b8e58..d55dafbb 100644 --- a/src/core/Global.ttslua +++ b/src/core/Global.ttslua @@ -304,6 +304,7 @@ function drawChaosToken(params) -- add the token to the list, compute new position based on list length if params.returnedToken then + trackChaosToken(params.returnedToken.getName(), matGUID, "subtract") indexOfReturnedToken = getTokenIndex(params.returnedToken) tokenPosition = params.returnedToken.getPosition() if #chaosTokens > indexOfReturnedToken then @@ -317,8 +318,9 @@ function drawChaosToken(params) end local token + -- resolve a sealed token from a card - if params.guidToBeResolved then + if params.guidToBeResolved then token = getObjectFromGUID(params.guidToBeResolved) token.setPositionSmooth(tokenPosition) local guid = token.getGUID() @@ -328,7 +330,7 @@ function drawChaosToken(params) end tokenArrangerApi.layout() -- take a token from the bag, either specified or random - else + else local takeParameters = { position = tokenPosition, rotation = tokenRotation @@ -346,15 +348,18 @@ function drawChaosToken(params) end -- get data for token description local name = token.getName() - if name == "" then name = "Custom" end local tokenData = mythosAreaApi.returnTokenData().tokenData or {} local specificData = tokenData[name] or {} token.setDescription(specificData.description or "") -- track the chaos token (for stat tracker and future returning) - trackChaosToken(name, matGUID) - chaosTokens[#chaosTokens + 1] = token + trackChaosToken(name, matGUID, "add") + if params.returnedToken then + chaosTokens[indexOfReturnedToken] = token + else + chaosTokens[#chaosTokens + 1] = token + end else returnChaosTokens() end @@ -375,13 +380,19 @@ end -- chaos token stat tracker --------------------------------------------------------- -function trackChaosToken(tokenName, matGUID) +function trackChaosToken(tokenName, matGUID, addOrSubtract) -- initialize tables if not tokenDrawingStats[matGUID] then tokenDrawingStats[matGUID] = {} end + if tokenName == "" then tokenName = "Custom" end - -- increase stats by 1 - tokenDrawingStats["Overall"][tokenName] = (tokenDrawingStats["Overall"][tokenName] or 0) + 1 - tokenDrawingStats[matGUID][tokenName] = (tokenDrawingStats[matGUID][tokenName] or 0) + 1 + -- increase stats by 1 or decreause if token is returned + if addOrSubtract == "add" then + tokenDrawingStats["Overall"][tokenName] = (tokenDrawingStats["Overall"][tokenName] or 0) + 1 + tokenDrawingStats[matGUID][tokenName] = (tokenDrawingStats[matGUID][tokenName] or 0) + 1 + else + tokenDrawingStats["Overall"][tokenName] = (tokenDrawingStats["Overall"][tokenName] or 0) - 1 + tokenDrawingStats[matGUID][tokenName] = (tokenDrawingStats[matGUID][tokenName] or 0) - 1 + end end -- Left-click: print stats, Right-click: reset stats diff --git a/src/playercards/cards/NkosiMabati3.ttslua b/src/playercards/cards/NkosiMabati3.ttslua index e8643ec4..bdc90f77 100644 --- a/src/playercards/cards/NkosiMabati3.ttslua +++ b/src/playercards/cards/NkosiMabati3.ttslua @@ -33,7 +33,7 @@ function onSave() end function onLoad(savedData) - self.addContextMenuItem("Enable Helper", createButtons) + self.addContextMenuItem("Enable Helper", chooseSigil) sigil= JSON.decode(savedData) if sigil and sigil ~= nil then makeXMLButton(sigil) @@ -69,8 +69,8 @@ function makeXMLButton(chosenToken) ) end --- Create buttons to choose sigil -function createButtons(playerColor) +-- Create dialog window to choose sigil and create sigil-drawing button +function chooseSigil(playerColor) self.clearContextMenu() self.addContextMenuItem("Clear Helper", deleteButtons) Player[playerColor].showOptionsDialog("Choose Sigil", tokenNames, 1, @@ -88,7 +88,7 @@ end -- Delete button and remove sigil function deleteButtons() self.clearContextMenu() - self.addContextMenuItem("Enable Helper", createButtons) + self.addContextMenuItem("Enable Helper", chooseSigil) self.UI.setXml("") sigil = nil end @@ -113,11 +113,19 @@ function resolveSigil() return end - local symbolMatch = false + local matchingSymbolsInPlay = {} for j, token in ipairs(tokensInPlay) do if (token.getName() == "Cultist" or token.getName() == "Elder Thing" or token.getName() == "Tablet") and token.getName() ~= sigil then - symbolMatch = true + matchingSymbolsInPlay[#matchingSymbolsInPlay + 1] = token + end + end + + if #matchingSymbolsInPlay == 0 then + broadcastToAll("No eligible symbol token found in play area", "Red") + return + elseif #matchingSymbolsInPlay > 1 then + for j, token in ipairs(matchingSymbolsInPlay) do -- draw XML to return token to bag token.UI.setXmlTable({ { @@ -156,11 +164,8 @@ function resolveSigil() } }) end - end - - if not symbolMatch then - broadcastToAll("No eligible symbol token found in play area", "Red") - return + else + drawSigil(_, matchingSymbolsInPlay[1].getGUID()) end end From 8a8ff43302c47ef1bdb4fcad7b4a2d25ea582d5d Mon Sep 17 00:00:00 2001 From: dscarpac Date: Thu, 18 Apr 2024 06:22:54 -0500 Subject: [PATCH 009/157] issues resolved --- src/chaosbag/ChaosBagApi.ttslua | 2 +- src/core/Global.ttslua | 203 ++++++++------- src/playercards/cards/NkosiMabati3.ttslua | 291 +++++++++++----------- 3 files changed, 255 insertions(+), 241 deletions(-) diff --git a/src/chaosbag/ChaosBagApi.ttslua b/src/chaosbag/ChaosBagApi.ttslua index 03a84693..cf333a8e 100644 --- a/src/chaosbag/ChaosBagApi.ttslua +++ b/src/chaosbag/ChaosBagApi.ttslua @@ -71,7 +71,7 @@ do ---@param drawAdditional boolean Controls whether additional tokens should be drawn ---@param tokenType? string Name of token (e.g. "Bless") to be drawn from the bag ---@param guidToBeResolved? string GUID of the sealed token to be resolved instead of drawing a token from the bag - ---@param returnedToken tts__Object Token to be replaced with newly drawn token + ---@param returnedToken? tts__Object Token to be replaced with newly drawn token ChaosBagApi.drawChaosToken = function(mat, drawAdditional, tokenType, guidToBeResolved, returnedToken) return Global.call("drawChaosToken", {mat = mat, drawAdditional = drawAdditional, tokenType = tokenType, guidToBeResolved = guidToBeResolved, returnedToken = returnedToken}) end diff --git a/src/core/Global.ttslua b/src/core/Global.ttslua index d55dafbb..2c82356e 100644 --- a/src/core/Global.ttslua +++ b/src/core/Global.ttslua @@ -76,33 +76,33 @@ local RESOURCE_OPTIONS = { --------------------------------------------------------- TOKEN_DATA = { - damage = {image = "http://cloud-3.steamusercontent.com/ugc/1758068501357115146/903D11AAE7BD5C254C8DC136E9202EE516289DEA/", scale = {0.17, 0.17, 0.17}}, - horror = {image = "http://cloud-3.steamusercontent.com/ugc/1758068501357163535/6D9E0756503664D65BDB384656AC6D4BD713F5FC/", scale = {0.17, 0.17, 0.17}}, - resource = {image = "http://cloud-3.steamusercontent.com/ugc/1758068501357192910/11DDDC7EF621320962FDCF3AE3211D5EDC3D1573/", scale = {0.17, 0.17, 0.17}}, - doom = {image = "https://i.imgur.com/EoL7yaZ.png", scale = {0.17, 0.17, 0.17}}, - clue = {image = "http://cloud-3.steamusercontent.com/ugc/1758068501357164917/1D06F1DC4D6888B6F57124BD2AFE20D0B0DA15A8/", scale = {0.15, 0.15, 0.15}} + damage = { image = "http://cloud-3.steamusercontent.com/ugc/1758068501357115146/903D11AAE7BD5C254C8DC136E9202EE516289DEA/", scale = { 0.17, 0.17, 0.17 } }, + horror = { image = "http://cloud-3.steamusercontent.com/ugc/1758068501357163535/6D9E0756503664D65BDB384656AC6D4BD713F5FC/", scale = { 0.17, 0.17, 0.17 } }, + resource = { image = "http://cloud-3.steamusercontent.com/ugc/1758068501357192910/11DDDC7EF621320962FDCF3AE3211D5EDC3D1573/", scale = { 0.17, 0.17, 0.17 } }, + doom = { image = "https://i.imgur.com/EoL7yaZ.png", scale = { 0.17, 0.17, 0.17 } }, + clue = { image = "http://cloud-3.steamusercontent.com/ugc/1758068501357164917/1D06F1DC4D6888B6F57124BD2AFE20D0B0DA15A8/", scale = { 0.15, 0.15, 0.15 } } } ID_URL_MAP = { - ['blue'] = {name = "Elder Sign", url = 'https://i.imgur.com/nEmqjmj.png'}, - ['p1'] = {name = "+1", url = 'https://i.imgur.com/uIx8jbY.png'}, - ['0'] = {name = "0", url = 'https://i.imgur.com/btEtVfd.png'}, - ['m1'] = {name = "-1", url = 'https://i.imgur.com/w3XbrCC.png'}, - ['m2'] = {name = "-2", url = 'https://i.imgur.com/bfTg2hb.png'}, - ['m3'] = {name = "-3", url = 'https://i.imgur.com/yfs8gHq.png'}, - ['m4'] = {name = "-4", url = 'https://i.imgur.com/qrgGQRD.png'}, - ['m5'] = {name = "-5", url = 'https://i.imgur.com/3Ym1IeG.png'}, - ['m6'] = {name = "-6", url = 'https://i.imgur.com/c9qdSzS.png'}, - ['m7'] = {name = "-7", url = 'https://i.imgur.com/4WRD42n.png'}, - ['m8'] = {name = "-8", url = 'https://i.imgur.com/9t3rPTQ.png'}, - ['skull'] = {name = "Skull", url = 'https://i.imgur.com/stbBxtx.png'}, - ['cultist'] = {name = "Cultist", url = 'https://i.imgur.com/VzhJJaH.png'}, - ['tablet'] = {name = "Tablet", url = 'https://i.imgur.com/1plY463.png'}, - ['elder'] = {name = "Elder Thing", url = 'https://i.imgur.com/ttnspKt.png'}, - ['red'] = {name = "Auto-fail", url = 'https://i.imgur.com/lns4fhz.png'}, - ['bless'] = {name = "Bless", url = 'http://cloud-3.steamusercontent.com/ugc/1655601092778627699/339FB716CB25CA6025C338F13AFDFD9AC6FA8356/'}, - ['curse'] = {name = "Curse", url = 'http://cloud-3.steamusercontent.com/ugc/1655601092778636039/2A25BD38E8C44701D80DD96BF0121DA21843672E/'}, - ['frost'] = {name = "Frost", url = 'http://cloud-3.steamusercontent.com/ugc/1858293462583104677/195F93C063A8881B805CE2FD4767A9718B27B6AE/'} + ['blue'] = { name = "Elder Sign", url = 'https://i.imgur.com/nEmqjmj.png' }, + ['p1'] = { name = "+1", url = 'https://i.imgur.com/uIx8jbY.png' }, + ['0'] = { name = "0", url = 'https://i.imgur.com/btEtVfd.png' }, + ['m1'] = { name = "-1", url = 'https://i.imgur.com/w3XbrCC.png' }, + ['m2'] = { name = "-2", url = 'https://i.imgur.com/bfTg2hb.png' }, + ['m3'] = { name = "-3", url = 'https://i.imgur.com/yfs8gHq.png' }, + ['m4'] = { name = "-4", url = 'https://i.imgur.com/qrgGQRD.png' }, + ['m5'] = { name = "-5", url = 'https://i.imgur.com/3Ym1IeG.png' }, + ['m6'] = { name = "-6", url = 'https://i.imgur.com/c9qdSzS.png' }, + ['m7'] = { name = "-7", url = 'https://i.imgur.com/4WRD42n.png' }, + ['m8'] = { name = "-8", url = 'https://i.imgur.com/9t3rPTQ.png' }, + ['skull'] = { name = "Skull", url = 'https://i.imgur.com/stbBxtx.png' }, + ['cultist'] = { name = "Cultist", url = 'https://i.imgur.com/VzhJJaH.png' }, + ['tablet'] = { name = "Tablet", url = 'https://i.imgur.com/1plY463.png' }, + ['elder'] = { name = "Elder Thing", url = 'https://i.imgur.com/ttnspKt.png' }, + ['red'] = { name = "Auto-fail", url = 'https://i.imgur.com/lns4fhz.png' }, + ['bless'] = { name = "Bless", url = 'http://cloud-3.steamusercontent.com/ugc/1655601092778627699/339FB716CB25CA6025C338F13AFDFD9AC6FA8356/' }, + ['curse'] = { name = "Curse", url = 'http://cloud-3.steamusercontent.com/ugc/1655601092778636039/2A25BD38E8C44701D80DD96BF0121DA21843672E/' }, + ['frost'] = { name = "Frost", url = 'http://cloud-3.steamusercontent.com/ugc/1858293462583104677/195F93C063A8881B805CE2FD4767A9718B27B6AE/' } } --------------------------------------------------------- @@ -189,7 +189,7 @@ end function onObjectEnterZone(zone, enteringObj) if zone.getName() ~= "TokenDiscardZone" then return end if tokenChecker.isChaosToken(enteringObj) then return end - + if enteringObj.type == "Tile" and enteringObj.getMemo() and enteringObj.getLock() == false then local matcolor = playmatApi.getMatColorByPosition(enteringObj.getPosition()) local trash = guidReferenceApi.getObjectByOwnerAndType(matcolor, "Trash") @@ -202,7 +202,7 @@ end function onObjectNumberTyped(hoveredObject, playerColor, number) -- only continue for decks or cards 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(playmatApi.getUsedMatColors()) do local deckAreaObjects = playmatApi.getDeckAreaObjects(color) @@ -280,11 +280,27 @@ function canTouchChaosTokens() return true end +-- converts the human readable name to the empty name that the bag uses +function getChaosTokenName(tokenName) + if tokenName == "Custom Token" then + tokenName = "" + end + return tokenName +end + +-- converts the empty name to the human readable name +function getReadableTokenName(tokenName) + if tokenName == "" then + tokenName = "Custom Token" + end + return tokenName +end + -- called by playermats (by the "Draw chaos token" button) function drawChaosToken(params) if not canTouchChaosTokens() then return end - local tokenOffset = {-1.55, 0.25, -0.58} + local tokenOffset = { -1.55, 0.25, -0.58 } local matGUID = params.mat.getGUID() -- return token(s) on other playmat first @@ -302,59 +318,62 @@ function drawChaosToken(params) if #chaosBag.getObjects() == 0 then return end chaosBag.shuffle() + local indexOfReturnedToken + local takeParameters = { + position, + rotation, + index + } + -- add the token to the list, compute new position based on list length if params.returnedToken then - trackChaosToken(params.returnedToken.getName(), matGUID, "subtract") + trackChaosToken(params.returnedToken.getName(), matGUID, true) indexOfReturnedToken = getTokenIndex(params.returnedToken) - tokenPosition = params.returnedToken.getPosition() + takeParameters.position = params.returnedToken.getPosition() + takeParameters.rotation = params.returnedToken.getRotation() if #chaosTokens > indexOfReturnedToken then - tokenRotation = params.mat.getRotation() + Vector(0, 0, -8) + takeParameters.rotation = params.mat.getRotation() + Vector(0, 0, -8) end returnChaosTokenToBag(params.returnedToken) - else + else tokenOffset[1] = tokenOffset[1] + (0.17 * #chaosTokens) - tokenPosition = params.mat.positionToWorld(tokenOffset) - tokenRotation = params.mat.getRotation() + takeParameters.position = params.mat.positionToWorld(tokenOffset) + takeParameters.rotation = params.mat.getRotation() end - + local token -- resolve a sealed token from a card - if params.guidToBeResolved then + if params.guidToBeResolved then token = getObjectFromGUID(params.guidToBeResolved) - token.setPositionSmooth(tokenPosition) + token.setPositionSmooth(takeParameters.position) local guid = token.getGUID() local tokenType = token.getName() if tokenType == "Bless" or tokenType == "Curse" then blessCurseManagerApi.releasedToken(tokenType, guid) end tokenArrangerApi.layout() - -- take a token from the bag, either specified or random - else - local takeParameters = { - position = tokenPosition, - rotation = tokenRotation - } - + -- take a token from the bag, either specified or random + else if params.tokenType then - for i, lookedForToken in ipairs(chaosBag.getObjects()) do - if lookedForToken.nickname == params.tokenType then - takeParameters.index = i - 1 - end + for i, lookedForToken in ipairs(chaosBag.getObjects()) do + if lookedForToken.nickname == params.tokenType then + takeParameters.index = i - 1 end + end end token = chaosBag.takeObject(takeParameters) - end + end -- get data for token description local name = token.getName() - + local tokenData = mythosAreaApi.returnTokenData().tokenData or {} local specificData = tokenData[name] or {} token.setDescription(specificData.description or "") -- track the chaos token (for stat tracker and future returning) - trackChaosToken(name, matGUID, "add") + trackChaosToken(name, matGUID) if params.returnedToken then chaosTokens[indexOfReturnedToken] = token else @@ -380,13 +399,13 @@ end -- chaos token stat tracker --------------------------------------------------------- -function trackChaosToken(tokenName, matGUID, addOrSubtract) +function trackChaosToken(tokenName, matGUID, subtract) -- initialize tables if not tokenDrawingStats[matGUID] then tokenDrawingStats[matGUID] = {} end - if tokenName == "" then tokenName = "Custom" end + local tokenName = getReadableTokenName(tokenName) -- increase stats by 1 or decreause if token is returned - if addOrSubtract == "add" then + if subtract == false or subtract == nil then tokenDrawingStats["Overall"][tokenName] = (tokenDrawingStats["Overall"][tokenName] or 0) + 1 tokenDrawingStats[matGUID][tokenName] = (tokenDrawingStats[matGUID][tokenName] or 0) + 1 else @@ -755,7 +774,7 @@ end function onClick_select(_, _, identificationKey) UI.setAttribute("panel" .. currentListItem, "color", "clear") UI.setAttribute(contentToShow .. "_" .. currentListItem, "color", "white") - + -- parses the identification key (contentToShow_currentListItem) if identificationKey then contentToShow = nil @@ -824,7 +843,7 @@ function placeholder_download(params) end local url = SOURCE_REPO .. '/' .. params.url - requestObj = WebRequest.get(url, function (request) contentDownloadCallback(request, params) end) + requestObj = WebRequest.get(url, function(request) contentDownloadCallback(request, params) end) startLuaCoroutine(Global, 'downloadCoroutine') end @@ -876,7 +895,7 @@ function coroutineDownloadAll() contained = contained .. request.text .. "," downloadedItems = downloadedItems + 1 break - -- time-out if item can't be loaded in 5s + -- time-out if item can't be loaded in 5s elseif request.is_error or (os.time() - start) > 5 then skippedItems = skippedItems + 1 break @@ -888,7 +907,7 @@ function coroutineDownloadAll() JSONCopy = JSONCopy .. contained .. "]}" JSONCopy = JSONCopy:gsub("{{POSX}}", posx) JSONCopy = JSONCopy:gsub("{{NICKNAME}}", contentType) - spawnObjectJSON({json = JSONCopy}) + spawnObjectJSON({ json = JSONCopy }) posx = posx + 3 end @@ -910,7 +929,7 @@ function onClick_spawnPlaceholder(player) end -- get data for placeholder - local spawnPos = {-39.5, 2, -87} + local spawnPos = { -39.5, 2, -87 } local meshTable = { big = "https://raw.githubusercontent.com/RobMayer/TTSLibrary/master/advboxes/core_h_MSH.obj", @@ -919,15 +938,15 @@ function onClick_spawnPlaceholder(player) } local scaleTable = { - big = {1.00, 0.14, 1.00}, - small = {2.21, 0.46, 2.42}, - wide = {2.00, 0.11, 1.69} + big = { 1.00, 0.14, 1.00 }, + small = { 2.21, 0.46, 2.42 }, + wide = { 2.00, 0.11, 1.69 } } local placeholder = spawnObject({ type = "Custom_Model", position = spawnPos, - rotation = {0, 270, 0}, + rotation = { 0, 270, 0 }, scale = scaleTable[item.boxsize], }) @@ -941,7 +960,7 @@ function onClick_spawnPlaceholder(player) placeholder.addTag("LargeBox") end - placeholder.setColorTint({1, 1, 1, 71/255}) + placeholder.setColorTint({ 1, 1, 1, 71 / 255 }) placeholder.setName(item.name) placeholder.setDescription("by " .. (item.author or "Unknown")) placeholder.setGMNotes(item.url) @@ -964,7 +983,7 @@ function onClick_toggleUi(player, windowId) -- hide the playAreaGallery if visible if windowId == "downloadWindow" then changeWindowVisibilityForColor(player.color, "playAreaGallery", false) - -- hide the downloadWindow if visible + -- hide the downloadWindow if visible elseif windowId == "playAreaGallery" then changeWindowVisibilityForColor(player.color, "downloadWindow", false) end @@ -1032,7 +1051,8 @@ end -- updates the preview window function updatePreviewWindow() local item = library[contentToShow][currentListItem] - local tempImage = "http://cloud-3.steamusercontent.com/ugc/2115061845788345842/2CD6ABC551555CCF58F9D0DDB7620197BA398B06/" + local tempImage = + "http://cloud-3.steamusercontent.com/ugc/2115061845788345842/2CD6ABC551555CCF58F9D0DDB7620197BA398B06/" -- set default image if not defined if item.boxsize == nil or item.boxsize == "" or item.boxart == nil or item.boxart == "" then @@ -1071,7 +1091,7 @@ function updatePreviewWindow() -- loading empty image as placeholder until real image is loaded UI.setAttribute("previewArtImage", "image", tempImage) - + -- insert the image itself UI.setAttribute("previewArtImage", "image", item.boxart) UI.setAttributes("previewArtMask", maskData) @@ -1188,13 +1208,14 @@ function contentDownloadCallback(request, params) -- if position is undefined, get empty position if not spawnTable.position then - spawnTable.rotation = { 0, 270, 0} + spawnTable.rotation = { 0, 270, 0 } local pos = getValidSpawnPosition() if pos then spawnTable.position = pos 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 end end @@ -1212,7 +1233,7 @@ function contentDownloadCallback(request, params) distance = 65 }) end - + -- ping object local pingPlayer = params.player or Player.getPlayers()[1] pingPlayer.pingTable(obj.getPosition()) @@ -1265,7 +1286,7 @@ function libraryDownloadCallback(request) end local json_response = nil - if pcall(function () json_response = JSON.decode(request.text) end) then + if pcall(function() json_response = JSON.decode(request.text) end) then formatLibrary(json_response) updateDownloadItemList() else @@ -1352,7 +1373,9 @@ function playermatRemovalSelected(player, selectedIndex, id) if mat then -- confirmation dialog about deletion player.pingTable(mat.getPosition()) - player.showConfirmDialog("Do you really want to remove " .. matColor .. "'s playermat and related objects? This can't be reversed.", function() removePlayermat(matColor) end) + player.showConfirmDialog( + "Do you really want to remove " .. matColor .. "'s playermat and related objects? This can't be reversed.", + function() removePlayermat(matColor) end) else -- info dialog that it is already deleted player.showInfoDialog(matColor .. "'s playermat has already been removed.") @@ -1410,12 +1433,12 @@ function applyOptionPanelChange(id, state) playmatApi.setLimitSnapsByType(state, "All") optionPanel[id] = state - -- option: Draw 1 button + -- option: Draw 1 button elseif id == "showDrawButton" then playmatApi.showDrawButton(state, "All") optionPanel[id] = state - -- option: Clickable clue counters + -- option: Clickable clue counters elseif id == "useClueClickers" then playmatApi.clickableClues(state, "All") optionPanel[id] = state @@ -1424,55 +1447,55 @@ function applyOptionPanelChange(id, state) local counter = guidReferenceApi.getObjectByOwnerAndType("Mythos", "MasterClueCounter") counter.setVar("useClickableCounters", state) - -- option: Play area snap tags + -- option: Play area snap tags elseif id == "playAreaConnections" then playAreaApi.setConnectionDrawState(state) optionPanel[id] = state - -- option: Play area connection color + -- option: Play area connection color elseif id == "playAreaConnectionColor" then playAreaApi.setConnectionColor(state) UI.setAttribute(id, "color", "#" .. Color.new(state):toHex()) optionPanel[id] = state - -- option: Play area snap tags + -- option: Play area snap tags elseif id == "playAreaSnapTags" then playAreaApi.setLimitSnapsByType(state) optionPanel[id] = state - -- option: Show Title on placing scenarios + -- option: Show Title on placing scenarios elseif id == "showTitleSplash" then optionPanel[id] = state - -- option: Change custom playarea image on setup + -- option: Change custom playarea image on setup elseif id == "changePlayAreaImage" then optionPanel[id] = state - -- option: Show clean up helper + -- option: Show clean up helper elseif id == "showCleanUpHelper" then - optionPanel[id] = spawnOrRemoveHelper(state, "Clean Up Helper", {-66, 1.6, 46}) + optionPanel[id] = spawnOrRemoveHelper(state, "Clean Up Helper", { -66, 1.6, 46 }) - -- option: Show hand helper for each player + -- option: Show hand helper for each player elseif id == "showHandHelper" then spawnOrRemoveHelperForPlayermats("Hand Helper", state) optionPanel[id] = state - -- option: Show search assistant for each player + -- option: Show search assistant for each player elseif id == "showSearchAssistant" then spawnOrRemoveHelperForPlayermats("Search Assistant", state) optionPanel[id] = state - -- option: Show attachment helper + -- option: Show attachment helper elseif id == "showAttachmentHelper" then - optionPanel[id] = spawnOrRemoveHelper(state, "Attachment Helper", {-62, 1.4, 0}) + optionPanel[id] = spawnOrRemoveHelper(state, "Attachment Helper", { -62, 1.4, 0 }) - -- option: Show CYOA campaign guides + -- option: Show CYOA campaign guides elseif id == "showCYOA" then - optionPanel[id] = spawnOrRemoveHelper(state, "CYOA Campaign Guides", { 39, 1.3, -20}) + optionPanel[id] = spawnOrRemoveHelper(state, "CYOA Campaign Guides", { 39, 1.3, -20 }) - -- option: Show displacement tool + -- option: Show displacement tool elseif id == "showDisplacementTool" then - optionPanel[id] = spawnOrRemoveHelper(state, "Displacement Tool", {-57, 1.6, 46}) + optionPanel[id] = spawnOrRemoveHelper(state, "Displacement Tool", { -57, 1.6, 46 }) end end @@ -1669,8 +1692,8 @@ function updateNotificationLoading() -- update the XML UI UI.setValue("notificationHeader", "New version available: " .. modMeta["latestVersion"]) UI.setValue("releaseHighlightText", highlightText) - UI.setAttribute("highlightRow", "preferredHeight", 20*#highlights) - UI.setAttribute("updateNotification", "height", 20*#highlights + 125) + UI.setAttribute("highlightRow", "preferredHeight", 20 * #highlights) + UI.setAttribute("updateNotification", "height", 20 * #highlights + 125) end -- close / don't show again buttons on the update notification diff --git a/src/playercards/cards/NkosiMabati3.ttslua b/src/playercards/cards/NkosiMabati3.ttslua index bdc90f77..d003bdd3 100644 --- a/src/playercards/cards/NkosiMabati3.ttslua +++ b/src/playercards/cards/NkosiMabati3.ttslua @@ -1,185 +1,176 @@ -local chaosBagApi = require("chaosbag/ChaosBagApi") -local guidReferenceApi = require("core/GUIDReferenceApi") -local playmatApi = require("playermat/PlaymatApi") +local chaosBagApi = require("chaosbag/ChaosBagApi") +local guidReferenceApi = require("core/GUIDReferenceApi") +local playmatApi = require("playermat/PlaymatApi") -local tokenNames = { - "Skull", - "Cultist", - "Tablet", - "Elder Thing", - "Auto-fail", - "Bless", - "Curse", - "Frost", - "Custom Token" +local tokenNames = { + "Skull", + "Cultist", + "Tablet", + "Elder Thing", + "Auto-fail", + "Bless", + "Curse", + "Frost", + "Custom Token" } -local dataForToken = { - ["Skull"] = { color = "#4A0400E6", icon = "token-skull"}, - ["Cultist"] = { color = "#173B0BE6", icon = "token-cultist"}, - ["Tablet"] = { color = "#1D2238E6", icon = "token-tablet"}, - ["Elder Thing"] = { color = "#4D2331E6", icon = "token-elder-thing"}, - ["Auto-fail"] = { color = "#9B0004E6", icon = "token-auto-fail"}, - ["Bless"] = { color = "#9D702CE6", icon = "token-bless"}, - ["Curse"] = { color = "#633A84E6", icon = "token-curse"}, - ["Frost"] = { color = "#404450E6", icon = "token-frost"}, - [""] = { color = "#77674DE6", icon = "token-custom"} +local dataForToken = { + ["Skull"] = { color = "#4A0400E6", icon = "token-skull" }, + ["Cultist"] = { color = "#173B0BE6", icon = "token-cultist" }, + ["Tablet"] = { color = "#1D2238E6", icon = "token-tablet" }, + ["Elder Thing"] = { color = "#4D2331E6", icon = "token-elder-thing" }, + ["Auto-fail"] = { color = "#9B0004E6", icon = "token-auto-fail" }, + ["Bless"] = { color = "#9D702CE6", icon = "token-bless" }, + ["Curse"] = { color = "#633A84E6", icon = "token-curse" }, + ["Frost"] = { color = "#404450E6", icon = "token-frost" }, + [""] = { color = "#77674DE6", icon = "token-custom" } } local sigil function onSave() - return JSON.encode(sigil) + return JSON.encode(sigil) end - + function onLoad(savedData) - self.addContextMenuItem("Enable Helper", chooseSigil) - sigil= JSON.decode(savedData) - if sigil and sigil ~= nil then - makeXMLButton(sigil) - self.clearContextMenu() - self.addContextMenuItem("Clear Helper", deleteButtons) - end + self.addContextMenuItem("Enable Helper", chooseSigil) + sigil = JSON.decode(savedData) + if sigil and sigil ~= nil then + makeXMLButton(sigil) + self.clearContextMenu() + self.addContextMenuItem("Clear Helper", deleteButtons) + end end function makeXMLButton(chosenToken) - self.UI.setXmlTable({ - { - tag="Button", - attributes={ - height=450, - width=1400, - rotation="0 0 180", - scale="0.1 0.1 1", - position="0 -55 -22", - padding="50 50 50 50", - font="font_teutonic-arkham", - fontSize=300, - iconWidth=400, - iconAlignment="Right", - onClick="resolveSigil", - id=sigil, - icon=dataForToken[sigil].icon, - color=dataForToken[sigil].color, - textColor="White", - }, - value="Resolve", - } + self.UI.setXmlTable({ + { + tag = "Button", + attributes = { + height = 450, + width = 1400, + rotation = "0 0 180", + scale = "0.1 0.1 1", + position = "0 -55 -22", + padding = "50 50 50 50", + font = "font_teutonic-arkham", + fontSize = 300, + iconWidth = 400, + iconAlignment = "Right", + onClick = "resolveSigil", + id = sigil, + icon = dataForToken[sigil].icon, + color = dataForToken[sigil].color, + textColor = "White", + }, + value = "Resolve", } -) -end + } + ) +end -- Create dialog window to choose sigil and create sigil-drawing button function chooseSigil(playerColor) - self.clearContextMenu() - self.addContextMenuItem("Clear Helper", deleteButtons) - Player[playerColor].showOptionsDialog("Choose Sigil", tokenNames, 1, - function(chosenToken) - if chosenToken == "Custom Token" then - sigil = "" - else - sigil = chosenToken - end - makeXMLButton(sigil) - end - ) + self.clearContextMenu() + self.addContextMenuItem("Clear Helper", deleteButtons) + Player[playerColor].showOptionsDialog("Choose Sigil", tokenNames, 1, + function(chosenToken) + sigil = Global.call("getChaosTokenName", chosenToken) + makeXMLButton(sigil) + end + ) end -- Delete button and remove sigil function deleteButtons() - self.clearContextMenu() - self.addContextMenuItem("Enable Helper", chooseSigil) - self.UI.setXml("") - sigil = nil + self.clearContextMenu() + self.addContextMenuItem("Enable Helper", chooseSigil) + self.UI.setXml("") + sigil = nil end function resolveSigil() - local tokensInPlay = chaosBagApi.getTokensInPlay() - local chaosbag = chaosBagApi.findChaosBag() - local match = false - for i, obj in ipairs(chaosbag.getObjects()) do - -- if there are any sigils in the bag - if obj.nickname == sigil then - match = true - break - end - end - if not match then - if sigil == "" then - broadcastToAll("Custom token not found in chaos bag", "Red") - else - broadcastToAll(sigil .. " token not found in chaos bag", "Red") - end - return + local tokensInPlay = chaosBagApi.getTokensInPlay() + local chaosbag = chaosBagApi.findChaosBag() + local match = false + for i, obj in ipairs(chaosbag.getObjects()) do + -- if there are any sigils in the bag + if obj.nickname == sigil then + match = true + break end + end + if not match then + broadcastToAll(Global.call("getReadableTokenName", sigil) .. " not found in chaos bag", "Red") + return + end - local matchingSymbolsInPlay = {} + local matchingSymbolsInPlay = {} - for j, token in ipairs(tokensInPlay) do - if (token.getName() == "Cultist" or token.getName() == "Elder Thing" or token.getName() == "Tablet") and token.getName() ~= sigil then - matchingSymbolsInPlay[#matchingSymbolsInPlay + 1] = token - end + for j, token in ipairs(tokensInPlay) do + if (token.getName() == "Cultist" or token.getName() == "Elder Thing" or token.getName() == "Tablet") and token.getName() ~= sigil then + matchingSymbolsInPlay[#matchingSymbolsInPlay + 1] = token end + end - if #matchingSymbolsInPlay == 0 then - broadcastToAll("No eligible symbol token found in play area", "Red") - return - elseif #matchingSymbolsInPlay > 1 then - for j, token in ipairs(matchingSymbolsInPlay) do - -- draw XML to return token to bag - token.UI.setXmlTable({ - { - tag="VerticalLayout", - attributes={ - height=275, - width=275, - spacing=0, - padding="0 0 20 25", - scale="0.4 0.4 1", - rotation="0 0 180", - position="0 0 -15", - color="rgba(0,0,0,0.7)", - onClick=self.getGUID() .. "/drawSigil(" .. token.getGUID() .. ")", - }, - children={ - { - tag="Text", - attributes={ - fontSize="100", - font="font_teutonic-arkham", - color="#ffffff", - text="Nkosi", - }, - }, - { - tag="Text", - attributes={ - fontSize="125", - font="font_arkhamslim", - color="#ffffff", - text="U", - }, - }, - } - } - }) - end - else - drawSigil(_, matchingSymbolsInPlay[1].getGUID()) + if #matchingSymbolsInPlay == 0 then + broadcastToAll("No eligible symbol token found in play area", "Red") + return + elseif #matchingSymbolsInPlay > 1 then + for j, token in ipairs(matchingSymbolsInPlay) do + -- draw XML to return token to bag + token.UI.setXmlTable({ + { + tag = "VerticalLayout", + attributes = { + height = 275, + width = 275, + spacing = 0, + padding = "0 0 20 25", + scale = "0.4 0.4 1", + rotation = "0 0 180", + position = "0 0 -15", + color = "rgba(0,0,0,0.7)", + onClick = self.getGUID() .. "/drawSigil(" .. token.getGUID() .. ")", + }, + children = { + { + tag = "Text", + attributes = { + fontSize = "100", + font = "font_teutonic-arkham", + color = "#ffffff", + text = "Nkosi", + }, + }, + { + tag = "Text", + attributes = { + fontSize = "125", + font = "font_arkhamslim", + color = "#ffffff", + text = "U", + }, + }, + } + } + }) end + else + drawSigil(_, matchingSymbolsInPlay[1].getGUID()) + end end function drawSigil(player, tokenGUID) - - returnedToken = getObjectFromGUID(tokenGUID) - local matColor = playmatApi.getMatColorByPosition(returnedToken.getPosition()) - local mat = guidReferenceApi.getObjectByOwnerAndType(matColor, "Playermat") + returnedToken = getObjectFromGUID(tokenGUID) + local matColor = playmatApi.getMatColorByPosition(returnedToken.getPosition()) + local mat = guidReferenceApi.getObjectByOwnerAndType(matColor, "Playermat") - chaosBagApi.drawChaosToken(mat, true, sigil, _, returnedToken) - local tokensInPlay = chaosBagApi.getTokensInPlay() - for j, returnedToken in ipairs(tokensInPlay) do - if returnedToken.getName() == "Cultist" or returnedToken.getName() == "Elder Thing" or returnedToken.getName() == "Tablet" then - returnedToken.UI.setXml("") - end + chaosBagApi.drawChaosToken(mat, true, sigil, _, returnedToken) + local tokensInPlay = chaosBagApi.getTokensInPlay() + for j, returnedToken in ipairs(tokensInPlay) do + if returnedToken.getName() == "Cultist" or returnedToken.getName() == "Elder Thing" or returnedToken.getName() == "Tablet" then + returnedToken.UI.setXml("") end -end \ No newline at end of file + end +end From 42720495c772eb9a1416ee05acd9af7be5174c7c Mon Sep 17 00:00:00 2001 From: Chr1Z93 Date: Thu, 18 Apr 2024 19:27:53 +0200 Subject: [PATCH 010/157] bugfixes for clean up helper --- src/accessories/CleanUpHelper.ttslua | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/accessories/CleanUpHelper.ttslua b/src/accessories/CleanUpHelper.ttslua index 0f5acde6..9c4d2892 100644 --- a/src/accessories/CleanUpHelper.ttslua +++ b/src/accessories/CleanUpHelper.ttslua @@ -288,7 +288,9 @@ function tidyPlayerMatCoroutine() -- only continue for playermat (1-4) if option enabled if options["tidyPlayermats"] or i == 5 then -- delay for animation purpose - for k = 1, 30 do coroutine.yield(0) end + for k = 1, 30 do + coroutine.yield(0) + end -- get respective trash local trash = guidReferenceApi.getObjectByOwnerAndType(COLORS[i], "Trash") @@ -315,7 +317,7 @@ function tidyPlayerMatCoroutine() if obj.hasTag(IGNORE_TAG) == false and obj.getDescription() ~= "Action Token" and obj.hasTag("chaosBag") == false - and obj.locked == false + and (obj.locked == false or obj.hasTag("Investigator")) and obj.interactable == true then coroutine.yield(0) trash.putObject(obj) @@ -326,11 +328,13 @@ function tidyPlayerMatCoroutine() if obj.getScale().x < 0.4 then local pos = playmatApi.transformLocalPosition(Vector(-0.865, 0.1, -0.28), COLORS[i]) obj.setPosition(pos) + coroutine.yield(0) end -- flip action tokens back to ready if obj.is_face_down then obj.flip() + coroutine.yield(0) end -- reset action token state From 5a83749631ab19631dde4633f44ae8dafc524db8 Mon Sep 17 00:00:00 2001 From: Chr1Z93 Date: Thu, 18 Apr 2024 19:42:42 +0200 Subject: [PATCH 011/157] allow changing card state with number typing --- src/core/Global.ttslua | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/core/Global.ttslua b/src/core/Global.ttslua index 889e351f..fd19e82f 100644 --- a/src/core/Global.ttslua +++ b/src/core/Global.ttslua @@ -211,6 +211,16 @@ function onObjectNumberTyped(hoveredObject, playerColor, number) return true end end + + -- check if this is a card with states (and then change state instead of drawing it) + local states = hoveredObject.getStates() + if states ~= nil and #states > 0 then + local stateId = hoveredObject.getStateId() + if stateId ~= number and (#states + 1) >= number then + hoveredObject.setState(number) + return true + end + end end --------------------------------------------------------- From 877ac6ebcd9366001d7bfd03c9da4f37ebd86b87 Mon Sep 17 00:00:00 2001 From: dscarpac Date: Thu, 18 Apr 2024 14:28:29 -0500 Subject: [PATCH 012/157] Global fixes --- src/core/Global.ttslua | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/src/core/Global.ttslua b/src/core/Global.ttslua index 2c82356e..0254ca24 100644 --- a/src/core/Global.ttslua +++ b/src/core/Global.ttslua @@ -319,20 +319,17 @@ function drawChaosToken(params) chaosBag.shuffle() local indexOfReturnedToken - local takeParameters = { - position, - rotation, - index - } + local takeParameters = {} -- add the token to the list, compute new position based on list length if params.returnedToken then trackChaosToken(params.returnedToken.getName(), matGUID, true) indexOfReturnedToken = getTokenIndex(params.returnedToken) takeParameters.position = params.returnedToken.getPosition() - takeParameters.rotation = params.returnedToken.getRotation() if #chaosTokens > indexOfReturnedToken then takeParameters.rotation = params.mat.getRotation() + Vector(0, 0, -8) + else + takeParameters.rotation = params.returnedToken.getRotation() end returnChaosTokenToBag(params.returnedToken) else @@ -1214,8 +1211,7 @@ function contentDownloadCallback(request, params) if pos then spawnTable.position = pos 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 end end @@ -1373,9 +1369,7 @@ function playermatRemovalSelected(player, selectedIndex, id) if mat then -- confirmation dialog about deletion player.pingTable(mat.getPosition()) - player.showConfirmDialog( - "Do you really want to remove " .. matColor .. "'s playermat and related objects? This can't be reversed.", - function() removePlayermat(matColor) end) + player.showConfirmDialog("Do you really want to remove " .. matColor .. "'s playermat and related objects? This can't be reversed.", function() removePlayermat(matColor) end) else -- info dialog that it is already deleted player.showInfoDialog(matColor .. "'s playermat has already been removed.") From dde7c420b7611caeecfc84152592236344783480 Mon Sep 17 00:00:00 2001 From: Chr1Z93 Date: Thu, 18 Apr 2024 23:31:45 +0200 Subject: [PATCH 013/157] Draw encounter cards to the first empty slot from the right --- src/core/MythosArea.ttslua | 32 +++++++++++++++++++++++--------- src/core/MythosAreaApi.ttslua | 8 ++++---- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/core/MythosArea.ttslua b/src/core/MythosArea.ttslua index 34ad046c..a9305672 100644 --- a/src/core/MythosArea.ttslua +++ b/src/core/MythosArea.ttslua @@ -14,6 +14,7 @@ local ENCOUNTER_DISCARD_AREA = { upperLeft = { x = 1.62, z = 0.42 }, lowerRight = { x = 1.58, z = 0.38 }, } +local DRAWN_ENCOUNTER_CARD_OFFSET = {1.365, 0.5, -0.625} -- global position of encounter deck and discard pile local ENCOUNTER_DECK_POS = { x = -3.93, y = 1, z = 5.76 } @@ -174,19 +175,32 @@ function drawEncounterCard(params) end function actualEncounterCardDraw(card, params) + local metadata = JSON.decode(card.getGMNotes()) or {} + local faceUpRotation = 0 - if not params.alwaysFaceUp then - local metadata = JSON.decode(card.getGMNotes()) or {} - if metadata.hidden or DATA_HELPER.call('checkHiddenCard', card.getName()) then - faceUpRotation = 180 + if metadata.hidden or DATA_HELPER.call('checkHiddenCard', card.getName()) then + faceUpRotation = 180 + end + + local pos = params.mat.positionToWorld(DRAWN_ENCOUNTER_CARD_OFFSET) + + -- get first empty slot in threat area (right to left) + if not params.stack then + local searchPos = Vector(-0.91, 0.5, -0.625) + for i = 1, 5 do + local globalSearchPos = params.mat.positionToWorld(searchPos) + local searchResult = searchLib.atPosition(globalSearchPos, "isCardOrDeck") + if #searchResult == 0 then + pos = globalSearchPos + break + else + searchPos.x = searchPos.x + 0.455 + end end end - local DRAWN_ENCOUNTER_CARD_OFFSET = {1.365, 0.5, -0.625} - local pos = params.mat.positionToWorld(DRAWN_ENCOUNTER_CARD_OFFSET) - local rotY = params.mat.getRotation().y - - deckLib.placeOrMergeIntoDeck(card, pos, { 0, rotY, faceUpRotation }) + local rot = { 0, params.mat.getRotation().y, faceUpRotation } + deckLib.placeOrMergeIntoDeck(card, pos, rot) end function reshuffleEncounterDeck() diff --git a/src/core/MythosAreaApi.ttslua b/src/core/MythosAreaApi.ttslua index 9fff46dd..ab951641 100644 --- a/src/core/MythosAreaApi.ttslua +++ b/src/core/MythosAreaApi.ttslua @@ -16,11 +16,11 @@ do return getMythosArea().call("getEncounterDeck") end - -- draw an encounter card for the requesting mat + -- draw an encounter card for the requesting mat to the first empty spot from the right ---@param mat tts__Object Playermat that triggered this - ---@param alwaysFaceUp boolean Whether the card should be drawn face-up - MythosAreaApi.drawEncounterCard = function(mat, alwaysFaceUp) - getMythosArea().call("drawEncounterCard", {mat = mat, alwaysFaceUp = alwaysFaceUp}) + ---@param stack boolean Whether the card should instead be placed right next to the button (and even stack with other cards) + MythosAreaApi.drawEncounterCard = function(mat, stack) + getMythosArea().call("drawEncounterCard", { mat = mat, stack = stack }) end -- reshuffle the encounter deck From 4ca3cb977b57efc98c71a0efa1a340a184b8ec50 Mon Sep 17 00:00:00 2001 From: Chr1Z93 Date: Fri, 19 Apr 2024 10:24:05 +0200 Subject: [PATCH 014/157] introduce new tag for objects that should not be discarded during a scenario (e.g. key tokens) --- src/playermat/Playmat.ttslua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/playermat/Playmat.ttslua b/src/playermat/Playmat.ttslua index 9ddb7269..4fcbff84 100644 --- a/src/playermat/Playmat.ttslua +++ b/src/playermat/Playmat.ttslua @@ -214,8 +214,8 @@ function discardListOfObjects(objList) -- put chaos tokens back into bag (e.g. Unrelenting) elseif tokenChecker.isChaosToken(obj) then chaosBagApi.returnChaosTokenToBag(obj) - -- don't touch locked objects (like the table etc.) - elseif not obj.getLock() then + -- don't touch locked objects (like the table etc.) or specific objects (like key tokens) + elseif not obj.getLock() and not obj.hasTag("DontDiscard") then ownedObjects.Trash.putObject(obj) end end From 5d917dd3d2d95510a42628a242df21fb781679ee Mon Sep 17 00:00:00 2001 From: Chr1Z93 Date: Fri, 19 Apr 2024 11:50:03 +0200 Subject: [PATCH 015/157] added uses to EotE weaknesses --- objects/AllPlayerCards.15bb07/ArmInjury.8f1420.gmnotes | 7 +++++++ objects/AllPlayerCards.15bb07/Frostbitten.8abd77.gmnotes | 7 +++++++ objects/AllPlayerCards.15bb07/LegInjury.46b4a0.gmnotes | 7 +++++++ objects/AllPlayerCards.15bb07/Panic.93e52d.gmnotes | 7 +++++++ objects/AllPlayerCards.15bb07/Possessed.04b3a9.gmnotes | 7 +++++++ objects/AllPlayerCards.15bb07/Stupor.a42bcf.gmnotes | 7 +++++++ 6 files changed, 42 insertions(+) diff --git a/objects/AllPlayerCards.15bb07/ArmInjury.8f1420.gmnotes b/objects/AllPlayerCards.15bb07/ArmInjury.8f1420.gmnotes index 18a56f62..c8ce4131 100644 --- a/objects/AllPlayerCards.15bb07/ArmInjury.8f1420.gmnotes +++ b/objects/AllPlayerCards.15bb07/ArmInjury.8f1420.gmnotes @@ -5,5 +5,12 @@ "traits": "Injury.", "weakness": true, "basicWeaknessCount": 1, + "uses": [ + { + "count": 1, + "type": "Damage", + "token": "damage" + } + ], "cycle": "Edge of the Earth" } diff --git a/objects/AllPlayerCards.15bb07/Frostbitten.8abd77.gmnotes b/objects/AllPlayerCards.15bb07/Frostbitten.8abd77.gmnotes index 2a3b0947..ba2c69b5 100644 --- a/objects/AllPlayerCards.15bb07/Frostbitten.8abd77.gmnotes +++ b/objects/AllPlayerCards.15bb07/Frostbitten.8abd77.gmnotes @@ -4,5 +4,12 @@ "class": "Neutral", "traits": "Injury.", "weakness": true, + "uses": [ + { + "count": 1, + "type": "Damage", + "token": "damage" + } + ], "cycle": "Edge of the Earth" } diff --git a/objects/AllPlayerCards.15bb07/LegInjury.46b4a0.gmnotes b/objects/AllPlayerCards.15bb07/LegInjury.46b4a0.gmnotes index 40090c2a..557d435e 100644 --- a/objects/AllPlayerCards.15bb07/LegInjury.46b4a0.gmnotes +++ b/objects/AllPlayerCards.15bb07/LegInjury.46b4a0.gmnotes @@ -5,5 +5,12 @@ "traits": "Injury.", "weakness": true, "basicWeaknessCount": 1, + "uses": [ + { + "count": 1, + "type": "Damage", + "token": "damage" + } + ], "cycle": "Edge of the Earth" } diff --git a/objects/AllPlayerCards.15bb07/Panic.93e52d.gmnotes b/objects/AllPlayerCards.15bb07/Panic.93e52d.gmnotes index a3f0b64a..ca095ee1 100644 --- a/objects/AllPlayerCards.15bb07/Panic.93e52d.gmnotes +++ b/objects/AllPlayerCards.15bb07/Panic.93e52d.gmnotes @@ -5,5 +5,12 @@ "traits": "Madness.", "weakness": true, "basicWeaknessCount": 1, + "uses": [ + { + "count": 1, + "type": "Horror", + "token": "horror" + } + ], "cycle": "Edge of the Earth" } diff --git a/objects/AllPlayerCards.15bb07/Possessed.04b3a9.gmnotes b/objects/AllPlayerCards.15bb07/Possessed.04b3a9.gmnotes index 7537fa22..07eb574f 100644 --- a/objects/AllPlayerCards.15bb07/Possessed.04b3a9.gmnotes +++ b/objects/AllPlayerCards.15bb07/Possessed.04b3a9.gmnotes @@ -4,5 +4,12 @@ "class": "Neutral", "traits": "Madness.", "weakness": true, + "uses": [ + { + "count": 1, + "type": "Horror", + "token": "horror" + } + ], "cycle": "Edge of the Earth" } diff --git a/objects/AllPlayerCards.15bb07/Stupor.a42bcf.gmnotes b/objects/AllPlayerCards.15bb07/Stupor.a42bcf.gmnotes index 0843d24a..3d29d9cd 100644 --- a/objects/AllPlayerCards.15bb07/Stupor.a42bcf.gmnotes +++ b/objects/AllPlayerCards.15bb07/Stupor.a42bcf.gmnotes @@ -5,5 +5,12 @@ "traits": "Madness.", "weakness": true, "basicWeaknessCount": 1, + "uses": [ + { + "count": 1, + "type": "Horror", + "token": "horror" + } + ], "cycle": "Edge of the Earth" } From c1b76c6021557a45f0cf6bb8446081d783c3cbdd Mon Sep 17 00:00:00 2001 From: Chr1Z93 Date: Fri, 19 Apr 2024 12:13:53 +0200 Subject: [PATCH 016/157] print chaos token stats in order --- src/core/Global.ttslua | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/src/core/Global.ttslua b/src/core/Global.ttslua index bd094c27..72a9aa1b 100644 --- a/src/core/Global.ttslua +++ b/src/core/Global.ttslua @@ -403,16 +403,13 @@ end function trackChaosToken(tokenName, matGUID, subtract) -- initialize tables if not tokenDrawingStats[matGUID] then tokenDrawingStats[matGUID] = {} end - local tokenName = getReadableTokenName(tokenName) - -- increase stats by 1 or decreause if token is returned - if subtract == false or subtract == nil then - tokenDrawingStats["Overall"][tokenName] = (tokenDrawingStats["Overall"][tokenName] or 0) + 1 - tokenDrawingStats[matGUID][tokenName] = (tokenDrawingStats[matGUID][tokenName] or 0) + 1 - else - tokenDrawingStats["Overall"][tokenName] = (tokenDrawingStats["Overall"][tokenName] or 0) - 1 - tokenDrawingStats[matGUID][tokenName] = (tokenDrawingStats[matGUID][tokenName] or 0) - 1 - end + -- increase stats by 1 (or decrease if token is returned) + local modifier = (subtract and -1 or 1) + + local tokenName = getReadableTokenName(tokenName) + tokenDrawingStats["Overall"][tokenName] = (tokenDrawingStats["Overall"][tokenName] or 0) + modifier + tokenDrawingStats[matGUID][tokenName] = (tokenDrawingStats[matGUID][tokenName] or 0) + modifier end -- Left-click: print stats, Right-click: reset stats @@ -445,7 +442,7 @@ function handleStatTrackerClick(_, _, isRightClick) -- get the total count of drawn tokens for the player local totalCount = 0 - for tokenName, value in pairs(personalStats) do + for _, value in pairs(personalStats) do totalCount = totalCount + value end @@ -455,11 +452,22 @@ function handleStatTrackerClick(_, _, isRightClick) printToAll("------------------------------") printToAll(playerName .. " Stats", playerColor) - for tokenName, value in pairs(personalStats) do - if value ~= 0 then + -- print stats in order of the "ID_URL_MAP" + for _, subtable in pairs(ID_URL_MAP) do + local tokenName = subtable.name + local value = personalStats[tokenName] + if value and value ~= 0 then printToAll(tokenName .. ': ' .. tostring(value)) end end + + -- also print stats for custom tokens + local customTokenName = getReadableTokenName("") + local customTokenCount = personalStats[customTokenName] + if customTokenCount and customTokenCount ~= 0 then + printToAll(customTokenName .. ': ' .. tostring(customTokenCount)) + end + printToAll('Total: ' .. tostring(totalCount)) end end From 2c67f609be593360f7a7dcab75177fe4c3c3c9f9 Mon Sep 17 00:00:00 2001 From: dscarpac Date: Wed, 24 Apr 2024 10:59:08 -0500 Subject: [PATCH 017/157] bugfixed --- src/core/MythosArea.ttslua | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/core/MythosArea.ttslua b/src/core/MythosArea.ttslua index 61e07270..f4935df8 100644 --- a/src/core/MythosArea.ttslua +++ b/src/core/MythosArea.ttslua @@ -12,7 +12,7 @@ local ENCOUNTER_DECK_AREA = { } local ENCOUNTER_DISCARD_AREA = { upperLeft = { x = 1.62, z = 0.42 }, - lowerRight = { x = 1.58, z = 0.38 }, + lowerRight = { x = 1.58, z = 0.38 }, } local DRAWN_ENCOUNTER_CARD_OFFSET = {1.365, 0.5, -0.625} @@ -99,12 +99,13 @@ function onCollisionExit(collisionInfo) end end --- Listens for cards entering the encounter deck or encounter discard, and resets the spawn state --- for the cards when they do. +-- Listens for cards entering the encounter deck or encounter discard, discards tokens on them, +-- and resets the spawn state for the cards when they do. function onObjectEnterContainer(container, object) local localPos = self.positionToLocal(container.getPosition()) if inArea(localPos, ENCOUNTER_DECK_AREA) or inArea(localPos, ENCOUNTER_DISCARD_AREA) then tokenSpawnTrackerApi.resetTokensSpawned(object.getGUID()) + removeTokensFromObject(object) end end From 8716347a212b244f9b1c729ce8b2ac0b2c0c6e18 Mon Sep 17 00:00:00 2001 From: dscarpac Date: Wed, 24 Apr 2024 11:04:55 -0500 Subject: [PATCH 018/157] removed stray space --- src/core/MythosArea.ttslua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/MythosArea.ttslua b/src/core/MythosArea.ttslua index f4935df8..c95aca34 100644 --- a/src/core/MythosArea.ttslua +++ b/src/core/MythosArea.ttslua @@ -12,7 +12,7 @@ local ENCOUNTER_DECK_AREA = { } local ENCOUNTER_DISCARD_AREA = { upperLeft = { x = 1.62, z = 0.42 }, - lowerRight = { x = 1.58, z = 0.38 }, + lowerRight = { x = 1.58, z = 0.38 }, } local DRAWN_ENCOUNTER_CARD_OFFSET = {1.365, 0.5, -0.625} From 57d72a899129d59a046ba763fe8e710e6f29f723 Mon Sep 17 00:00:00 2001 From: Chr1Z93 Date: Wed, 24 Apr 2024 19:05:07 +0200 Subject: [PATCH 019/157] code maintenance --- src/core/MythosArea.ttslua | 44 +++++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/src/core/MythosArea.ttslua b/src/core/MythosArea.ttslua index c95aca34..4b2fcdad 100644 --- a/src/core/MythosArea.ttslua +++ b/src/core/MythosArea.ttslua @@ -8,13 +8,13 @@ local tokenSpawnTrackerApi = require("core/token/TokenSpawnTrackerApi") local ENCOUNTER_DECK_AREA = { upperLeft = { x = 0.9, z = 0.42 }, - lowerRight = { x = 0.86, z = 0.38 }, + lowerRight = { x = 0.86, z = 0.38 } } local ENCOUNTER_DISCARD_AREA = { upperLeft = { x = 1.62, z = 0.42 }, - lowerRight = { x = 1.58, z = 0.38 }, + lowerRight = { x = 1.58, z = 0.38 } } -local DRAWN_ENCOUNTER_CARD_OFFSET = {1.365, 0.5, -0.625} +local DRAWN_ENCOUNTER_CARD_OFFSET = { 1.365, 0.5, -0.625 } -- global position of encounter deck and discard pile local ENCOUNTER_DECK_POS = { x = -3.93, y = 1, z = 5.76 } @@ -153,39 +153,44 @@ end -- 'params' contains the position, rotation and a boolean to force a faceup draw function drawEncounterCard(params) local encounterDeck = getEncounterDeck() + local reshuffledAlready if encounterDeck then reshuffledAlready = false - local card if encounterDeck.type == "Deck" then - card = encounterDeck.takeObject() + actualEncounterCardDraw(encounterDeck.takeObject(), params) else - card = encounterDeck + actualEncounterCardDraw(encounterDeck, params) end - actualEncounterCardDraw(card, params) else -- nothing here, time to reshuffle if reshuffledAlready == true then reshuffledAlready = false return end - reshuffleEncounterDeck() -- if there is no discard pile either, reshuffleEncounterDeck will give an error message already + + -- if there is no discard pile either, reshuffleEncounterDeck will give an error message already + reshuffleEncounterDeck() reshuffledAlready = true drawEncounterCard(params) end end +-- draw the provided card to the requesting playmat function actualEncounterCardDraw(card, params) local metadata = JSON.decode(card.getGMNotes()) or {} + -- draw hidden cards facedown local faceUpRotation = 0 if metadata.hidden or DATA_HELPER.call('checkHiddenCard', card.getName()) then faceUpRotation = 180 end + -- get position and rotation for the specific playmat local pos = params.mat.positionToWorld(DRAWN_ENCOUNTER_CARD_OFFSET) + local rot = { 0, params.mat.getRotation().y, faceUpRotation } - -- get first empty slot in threat area (right to left) + -- maybe override position with first empty slot in threat area (right to left) if not params.stack then local searchPos = Vector(-0.91, 0.5, -0.625) for i = 1, 5 do @@ -200,7 +205,6 @@ function actualEncounterCardDraw(card, params) end end - local rot = { 0, params.mat.getRotation().y, faceUpRotation } deckLib.placeOrMergeIntoDeck(card, pos, rot) end @@ -208,21 +212,26 @@ function reshuffleEncounterDeck() -- flag to avoid multiple calls if isReshuffling then return end isReshuffling = true + local encounterDeck = getEncounterDeck() local discardPile = searchLib.atPosition(ENCOUNTER_DISCARD_POSITION, "isCardOrDeck") - + if #discardPile > 0 then local discardDeck = discardPile[1] - if not discardDeck.is_face_down then --flips discard pile - discardDeck.setRotation({0, -90, 180}) - end + + -- flips discard pile + if not discardDeck.is_face_down then + discardDeck.setRotation({ 0, -90, 180 }) + end + + -- make a new encounter deck if encounterDeck == nil then - discardDeck.setPosition(Vector(ENCOUNTER_DECK_POS) + Vector({0, 1, 0})) - discardDeck.shuffle() + discardDeck.setPosition(Vector(ENCOUNTER_DECK_POS) + Vector({ 0, 1, 0 })) + encounterDeck = discardDeck else encounterDeck.putObject(discardDeck) - encounterDeck.shuffle() end + encounterDeck.shuffle() broadcastToAll("Shuffled encounter discard into deck.", "White") else broadcastToAll("Encounter discard pile is already empty.", "Red") @@ -231,6 +240,7 @@ function reshuffleEncounterDeck() -- disable flag Wait.time(function() isReshuffling = false end, 1) end + --------------------------------------------------------- -- helper functions --------------------------------------------------------- From d1ae804266b76666ce5366a32fd1b45c7b7ad816 Mon Sep 17 00:00:00 2001 From: Chr1Z93 Date: Thu, 25 Apr 2024 22:25:37 +0200 Subject: [PATCH 020/157] bugfix for spawning a single damage / horror --- src/core/token/TokenManager.ttslua | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/core/token/TokenManager.ttslua b/src/core/token/TokenManager.ttslua index 91765172..93b92683 100644 --- a/src/core/token/TokenManager.ttslua +++ b/src/core/token/TokenManager.ttslua @@ -172,8 +172,7 @@ do end end - -- Spawns a single counter token and sets the value to tokenValue. Used for damage and horror - -- tokens. + -- Spawns a single counter token and sets the value to tokenValue. Used for damage and horror tokens. ---@param card tts__Object Card to spawn tokens on ---@param tokenType string type of token to spawn, valid values are "damage" and "horror". Other -- types should use spawnMultipleTokens() @@ -183,7 +182,12 @@ do local pos = card.positionToWorld(PLAYER_CARD_TOKEN_OFFSETS[1][1] + Vector(0, 0, shiftDown)) local rot = card.getRotation() - TokenManager.spawnToken(pos, tokenType, rot, function(spawned) spawned.setState(tokenValue) end) + TokenManager.spawnToken(pos, tokenType, rot, function(spawned) + -- token starts in state 1, so don't attempt to change it to avoid error + if tokenValue ~= 1 then + spawned.setState(tokenValue) + end + end) end TokenManager.spawnResourceCounterToken = function(card, tokenCount) From 32bf52d3b466b0de18421e5a1c70b6f398c92604 Mon Sep 17 00:00:00 2001 From: Chr1Z93 Date: Fri, 26 Apr 2024 01:36:58 +0200 Subject: [PATCH 021/157] updated Nkosi and added slot XML --- modsettings/CustomUIAssets.json | 66 +----- objects/Playermat1White.8b081b.json | 146 ++++++------ objects/Playermat2Orange.bd0ff4.json | 146 ++++++------ objects/Playermat3Green.383d8b.json | 146 ++++++------ objects/Playermat4Red.0840d5.json | 146 ++++++------ src/playercards/cards/NkosiMabati3.ttslua | 105 +++++---- src/playermat/Playmat.ttslua | 266 ++++++++++++++++------ 7 files changed, 549 insertions(+), 472 deletions(-) diff --git a/modsettings/CustomUIAssets.json b/modsettings/CustomUIAssets.json index 69bb9dee..1e53c890 100644 --- a/modsettings/CustomUIAssets.json +++ b/modsettings/CustomUIAssets.json @@ -1,34 +1,9 @@ [ - { - "Name": "refresh", - "Type": 0, - "URL": "http://cloud-3.steamusercontent.com/ugc/1695031152736214852/EC3BBEF1A1788381A8F4C5ACB7FB27770CAF03C5/" - }, { "Name": "close", "Type": 0, "URL": "http://cloud-3.steamusercontent.com/ugc/1695031152736214756/2EEB07E453A7ECF4BE5A1030A253185B37A7CDAB/" }, - { - "Name": "cthulhu", - "Type": 0, - "URL": "http://cloud-3.steamusercontent.com/ugc/1782854877010107768/BC6A97F193385D01C1A9149B68923F55A284CB2D/" - }, - { - "Name": "dark-cult", - "Type": 0, - "URL": "http://cloud-3.steamusercontent.com/ugc/1782854877010108105/08594607341D6537C28A08A34CE82159025AB8DB/" - }, - { - "Name": "yog-sothoth", - "Type": 0, - "URL": "http://cloud-3.steamusercontent.com/ugc/1782854877010107124/D8042D1A1B08CFB7E76488B09216B4611D85A2B9/" - }, - { - "Name": "elder-sign", - "Type": 0, - "URL": "http://cloud-3.steamusercontent.com/ugc/1782854877010107442/43BC029410751208A90AE7FDEBCB587A0E9403D7/" - }, { "Name": "devourer", "Type": 0, @@ -55,40 +30,15 @@ "URL": "http://cloud-3.steamusercontent.com/ugc/2026086584372569912/5CB461AEAE2E59D3064D90A776EB86C46081EC78/" }, { - "Name": "font_arkhamslim", + "Name": "font_arkhamicons", "Type": 1, - "URL": "http://cloud-3.steamusercontent.com/ugc/2510267299454546112/8CDF773519FEC8C488569072280AC848BCC293D5/" - }, - { - "Name": "font_birmingham", - "Type": 1, - "URL": "http://cloud-3.steamusercontent.com/ugc/2027213118466443497/3CF9BB9AF968D245961494CC9A151774EB9BA638/" - }, - { - "Name": "font_columbus", - "Type": 1, - "URL": "http://cloud-3.steamusercontent.com/ugc/2027213118466515872/F473E4ACC75ACB6CE07457C45290B4912E0B3286/" - }, - { - "Name": "font_oldremington", - "Type": 1, - "URL": "http://cloud-3.steamusercontent.com/ugc/2027213118466515932/AFCE53F1E1D9580D166F53AD9EB0D77A331D4A26/" + "URL": "http://cloud-3.steamusercontent.com/ugc/2462982115649258367/C20CC4C299A6FE5F1ECAB968E15BE590337CC019/" }, { "Name": "font_teutonic-arkham", "Type": 1, "URL": "http://cloud-3.steamusercontent.com/ugc/2027213118467703445/89328E273B4C5180BF491516CE998DE3C604E162/" }, - { - "Name": "font_uglyqua", - "Type": 1, - "URL": "http://cloud-3.steamusercontent.com/ugc/2027213118466516005/113C19D37CFFA9E554394FD5B11B32967F846A62/" - }, - { - "Name": "font_chinese_fzlibian", - "Type": 1, - "URL": "http://cloud-3.steamusercontent.com/ugc/2028355502896482829/8DAB311590B97586309E66D795AC2C43D4913188/" - }, { "Name": "header_cover", "Type": 0, @@ -124,11 +74,6 @@ "Type": 0, "URL": "https://i.imgur.com/6MReiEO.png" }, - { - "Name": "Inv-Roland", - "Type": 0, - "URL": "https://i.imgur.com/lx6unDY.png" - }, { "Name": "NextArrow", "Type": 0, @@ -139,6 +84,11 @@ "Type": 0, "URL": "https://i.imgur.com/8qmTXwt.png" }, + { + "Name": "Inv-Roland", + "Type": 0, + "URL": "https://i.imgur.com/lx6unDY.png" + }, { "Name": "Inv-Mandy", "Type": 0, @@ -285,7 +235,7 @@ "URL": "http://cloud-3.steamusercontent.com/ugc/2510267932886739653/CB7AA2D73777EF5938A6E6CD664B2ABA52B6E20A/" }, { - "Name": "token-custom", + "Name": "token-custom-token", "Type": 0, "URL": "http://cloud-3.steamusercontent.com/ugc/2380784374792650571/E4C2B2B69282A4EE15FE290FF6B08BEFC8FCA65C/" } diff --git a/objects/Playermat1White.8b081b.json b/objects/Playermat1White.8b081b.json index afb6d149..8a23cb31 100644 --- a/objects/Playermat1White.8b081b.json +++ b/objects/Playermat1White.8b081b.json @@ -57,29 +57,9 @@ }, { "Position": { - "x": -0.631, - "y": 0.1, - "z": 0.551 - }, - "Tags": [ - "Asset" - ] - }, - { - "Position": { - "x": -0.616, - "y": 0.102, - "z": 0.024 - }, - "Tags": [ - "Asset" - ] - }, - { - "Position": { - "x": -0.177, + "x": 1.758, "y": 0.101, - "z": 0.032 + "z": 0.04 }, "Tags": [ "Asset" @@ -87,28 +67,18 @@ }, { "Position": { - "x": -0.174, + "x": 1.371, + "y": 0.1, + "z": 0.038 + }, + "Tags": [ + "Asset" + ] + }, + { + "Position": { + "x": 0.98, "y": 0.099, - "z": 0.551 - }, - "Tags": [ - "Asset" - ] - }, - { - "Position": { - "x": 0.212, - "y": 0.1, - "z": 0.559 - }, - "Tags": [ - "Asset" - ] - }, - { - "Position": { - "x": 0.217, - "y": 0.1, "z": 0.035 }, "Tags": [ @@ -127,28 +97,8 @@ }, { "Position": { - "x": 0.605, + "x": 0.217, "y": 0.1, - "z": 0.555 - }, - "Tags": [ - "Asset" - ] - }, - { - "Position": { - "x": 0.977, - "y": 0.099, - "z": 0.556 - }, - "Tags": [ - "Asset" - ] - }, - { - "Position": { - "x": 0.98, - "y": 0.099, "z": 0.035 }, "Tags": [ @@ -157,9 +107,9 @@ }, { "Position": { - "x": 1.371, - "y": 0.1, - "z": 0.038 + "x": -0.177, + "y": 0.101, + "z": 0.032 }, "Tags": [ "Asset" @@ -167,9 +117,9 @@ }, { "Position": { - "x": 1.371, - "y": 0.099, - "z": 0.558 + "x": -0.616, + "y": 0.102, + "z": 0.024 }, "Tags": [ "Asset" @@ -187,9 +137,59 @@ }, { "Position": { - "x": 1.758, - "y": 0.101, - "z": 0.04 + "x": 1.371, + "y": 0.099, + "z": 0.558 + }, + "Tags": [ + "Asset" + ] + }, + { + "Position": { + "x": 0.977, + "y": 0.099, + "z": 0.556 + }, + "Tags": [ + "Asset" + ] + }, + { + "Position": { + "x": 0.605, + "y": 0.1, + "z": 0.555 + }, + "Tags": [ + "Asset" + ] + }, + { + "Position": { + "x": 0.212, + "y": 0.1, + "z": 0.559 + }, + "Tags": [ + "Asset" + ] + }, + { + "Position": { + "x": -0.174, + "y": 0.099, + "z": 0.551 + }, + "Tags": [ + "Asset" + ] + }, + { + "Position": { + "x": -0.631, + "y": 0.1, + "z": 0.551 }, "Tags": [ "Asset" diff --git a/objects/Playermat2Orange.bd0ff4.json b/objects/Playermat2Orange.bd0ff4.json index a11274e2..e0acf721 100644 --- a/objects/Playermat2Orange.bd0ff4.json +++ b/objects/Playermat2Orange.bd0ff4.json @@ -57,29 +57,9 @@ }, { "Position": { - "x": -0.631, - "y": 0.1, - "z": 0.551 - }, - "Tags": [ - "Asset" - ] - }, - { - "Position": { - "x": -0.616, - "y": 0.102, - "z": 0.024 - }, - "Tags": [ - "Asset" - ] - }, - { - "Position": { - "x": -0.177, + "x": 1.758, "y": 0.101, - "z": 0.032 + "z": 0.04 }, "Tags": [ "Asset" @@ -87,28 +67,18 @@ }, { "Position": { - "x": -0.174, + "x": 1.371, + "y": 0.1, + "z": 0.038 + }, + "Tags": [ + "Asset" + ] + }, + { + "Position": { + "x": 0.98, "y": 0.099, - "z": 0.551 - }, - "Tags": [ - "Asset" - ] - }, - { - "Position": { - "x": 0.212, - "y": 0.1, - "z": 0.559 - }, - "Tags": [ - "Asset" - ] - }, - { - "Position": { - "x": 0.217, - "y": 0.1, "z": 0.035 }, "Tags": [ @@ -127,28 +97,8 @@ }, { "Position": { - "x": 0.605, + "x": 0.217, "y": 0.1, - "z": 0.555 - }, - "Tags": [ - "Asset" - ] - }, - { - "Position": { - "x": 0.977, - "y": 0.099, - "z": 0.556 - }, - "Tags": [ - "Asset" - ] - }, - { - "Position": { - "x": 0.98, - "y": 0.099, "z": 0.035 }, "Tags": [ @@ -157,9 +107,9 @@ }, { "Position": { - "x": 1.371, - "y": 0.1, - "z": 0.038 + "x": -0.177, + "y": 0.101, + "z": 0.032 }, "Tags": [ "Asset" @@ -167,9 +117,9 @@ }, { "Position": { - "x": 1.371, - "y": 0.099, - "z": 0.558 + "x": -0.616, + "y": 0.102, + "z": 0.024 }, "Tags": [ "Asset" @@ -187,9 +137,59 @@ }, { "Position": { - "x": 1.758, - "y": 0.101, - "z": 0.04 + "x": 1.371, + "y": 0.099, + "z": 0.558 + }, + "Tags": [ + "Asset" + ] + }, + { + "Position": { + "x": 0.977, + "y": 0.099, + "z": 0.556 + }, + "Tags": [ + "Asset" + ] + }, + { + "Position": { + "x": 0.605, + "y": 0.1, + "z": 0.555 + }, + "Tags": [ + "Asset" + ] + }, + { + "Position": { + "x": 0.212, + "y": 0.1, + "z": 0.559 + }, + "Tags": [ + "Asset" + ] + }, + { + "Position": { + "x": -0.174, + "y": 0.099, + "z": 0.551 + }, + "Tags": [ + "Asset" + ] + }, + { + "Position": { + "x": -0.631, + "y": 0.1, + "z": 0.551 }, "Tags": [ "Asset" diff --git a/objects/Playermat3Green.383d8b.json b/objects/Playermat3Green.383d8b.json index 1f22c5f7..c9a4af2d 100644 --- a/objects/Playermat3Green.383d8b.json +++ b/objects/Playermat3Green.383d8b.json @@ -57,29 +57,9 @@ }, { "Position": { - "x": -0.631, - "y": 0.1, - "z": 0.551 - }, - "Tags": [ - "Asset" - ] - }, - { - "Position": { - "x": -0.616, - "y": 0.102, - "z": 0.024 - }, - "Tags": [ - "Asset" - ] - }, - { - "Position": { - "x": -0.177, + "x": 1.758, "y": 0.101, - "z": 0.032 + "z": 0.04 }, "Tags": [ "Asset" @@ -87,28 +67,18 @@ }, { "Position": { - "x": -0.174, + "x": 1.371, + "y": 0.1, + "z": 0.038 + }, + "Tags": [ + "Asset" + ] + }, + { + "Position": { + "x": 0.98, "y": 0.099, - "z": 0.551 - }, - "Tags": [ - "Asset" - ] - }, - { - "Position": { - "x": 0.212, - "y": 0.1, - "z": 0.559 - }, - "Tags": [ - "Asset" - ] - }, - { - "Position": { - "x": 0.217, - "y": 0.1, "z": 0.035 }, "Tags": [ @@ -127,28 +97,8 @@ }, { "Position": { - "x": 0.605, + "x": 0.217, "y": 0.1, - "z": 0.555 - }, - "Tags": [ - "Asset" - ] - }, - { - "Position": { - "x": 0.977, - "y": 0.099, - "z": 0.556 - }, - "Tags": [ - "Asset" - ] - }, - { - "Position": { - "x": 0.98, - "y": 0.099, "z": 0.035 }, "Tags": [ @@ -157,9 +107,9 @@ }, { "Position": { - "x": 1.371, - "y": 0.1, - "z": 0.038 + "x": -0.177, + "y": 0.101, + "z": 0.032 }, "Tags": [ "Asset" @@ -167,9 +117,9 @@ }, { "Position": { - "x": 1.371, - "y": 0.099, - "z": 0.558 + "x": -0.616, + "y": 0.102, + "z": 0.024 }, "Tags": [ "Asset" @@ -187,9 +137,59 @@ }, { "Position": { - "x": 1.758, - "y": 0.101, - "z": 0.04 + "x": 1.371, + "y": 0.099, + "z": 0.558 + }, + "Tags": [ + "Asset" + ] + }, + { + "Position": { + "x": 0.977, + "y": 0.099, + "z": 0.556 + }, + "Tags": [ + "Asset" + ] + }, + { + "Position": { + "x": 0.605, + "y": 0.1, + "z": 0.555 + }, + "Tags": [ + "Asset" + ] + }, + { + "Position": { + "x": 0.212, + "y": 0.1, + "z": 0.559 + }, + "Tags": [ + "Asset" + ] + }, + { + "Position": { + "x": -0.174, + "y": 0.099, + "z": 0.551 + }, + "Tags": [ + "Asset" + ] + }, + { + "Position": { + "x": -0.631, + "y": 0.1, + "z": 0.551 }, "Tags": [ "Asset" diff --git a/objects/Playermat4Red.0840d5.json b/objects/Playermat4Red.0840d5.json index fdaeac08..6e3140e0 100644 --- a/objects/Playermat4Red.0840d5.json +++ b/objects/Playermat4Red.0840d5.json @@ -57,29 +57,9 @@ }, { "Position": { - "x": -0.631, - "y": 0.1, - "z": 0.551 - }, - "Tags": [ - "Asset" - ] - }, - { - "Position": { - "x": -0.616, - "y": 0.102, - "z": 0.024 - }, - "Tags": [ - "Asset" - ] - }, - { - "Position": { - "x": -0.177, + "x": 1.758, "y": 0.101, - "z": 0.032 + "z": 0.04 }, "Tags": [ "Asset" @@ -87,28 +67,18 @@ }, { "Position": { - "x": -0.174, + "x": 1.371, + "y": 0.1, + "z": 0.038 + }, + "Tags": [ + "Asset" + ] + }, + { + "Position": { + "x": 0.98, "y": 0.099, - "z": 0.551 - }, - "Tags": [ - "Asset" - ] - }, - { - "Position": { - "x": 0.212, - "y": 0.1, - "z": 0.559 - }, - "Tags": [ - "Asset" - ] - }, - { - "Position": { - "x": 0.217, - "y": 0.1, "z": 0.035 }, "Tags": [ @@ -127,28 +97,8 @@ }, { "Position": { - "x": 0.605, + "x": 0.217, "y": 0.1, - "z": 0.555 - }, - "Tags": [ - "Asset" - ] - }, - { - "Position": { - "x": 0.977, - "y": 0.099, - "z": 0.556 - }, - "Tags": [ - "Asset" - ] - }, - { - "Position": { - "x": 0.98, - "y": 0.099, "z": 0.035 }, "Tags": [ @@ -157,9 +107,9 @@ }, { "Position": { - "x": 1.371, - "y": 0.1, - "z": 0.038 + "x": -0.177, + "y": 0.101, + "z": 0.032 }, "Tags": [ "Asset" @@ -167,9 +117,9 @@ }, { "Position": { - "x": 1.371, - "y": 0.099, - "z": 0.558 + "x": -0.616, + "y": 0.102, + "z": 0.024 }, "Tags": [ "Asset" @@ -187,9 +137,59 @@ }, { "Position": { - "x": 1.758, - "y": 0.101, - "z": 0.04 + "x": 1.371, + "y": 0.099, + "z": 0.558 + }, + "Tags": [ + "Asset" + ] + }, + { + "Position": { + "x": 0.977, + "y": 0.099, + "z": 0.556 + }, + "Tags": [ + "Asset" + ] + }, + { + "Position": { + "x": 0.605, + "y": 0.1, + "z": 0.555 + }, + "Tags": [ + "Asset" + ] + }, + { + "Position": { + "x": 0.212, + "y": 0.1, + "z": 0.559 + }, + "Tags": [ + "Asset" + ] + }, + { + "Position": { + "x": -0.174, + "y": 0.099, + "z": 0.551 + }, + "Tags": [ + "Asset" + ] + }, + { + "Position": { + "x": -0.631, + "y": 0.1, + "z": 0.551 }, "Tags": [ "Asset" diff --git a/src/playercards/cards/NkosiMabati3.ttslua b/src/playercards/cards/NkosiMabati3.ttslua index d003bdd3..a0066c4b 100644 --- a/src/playercards/cards/NkosiMabati3.ttslua +++ b/src/playercards/cards/NkosiMabati3.ttslua @@ -2,28 +2,17 @@ local chaosBagApi = require("chaosbag/ChaosBagApi") local guidReferenceApi = require("core/GUIDReferenceApi") local playmatApi = require("playermat/PlaymatApi") -local tokenNames = { - "Skull", - "Cultist", - "Tablet", - "Elder Thing", - "Auto-fail", - "Bless", - "Curse", - "Frost", - "Custom Token" -} - -local dataForToken = { - ["Skull"] = { color = "#4A0400E6", icon = "token-skull" }, - ["Cultist"] = { color = "#173B0BE6", icon = "token-cultist" }, - ["Tablet"] = { color = "#1D2238E6", icon = "token-tablet" }, - ["Elder Thing"] = { color = "#4D2331E6", icon = "token-elder-thing" }, - ["Auto-fail"] = { color = "#9B0004E6", icon = "token-auto-fail" }, - ["Bless"] = { color = "#9D702CE6", icon = "token-bless" }, - ["Curse"] = { color = "#633A84E6", icon = "token-curse" }, - ["Frost"] = { color = "#404450E6", icon = "token-frost" }, - [""] = { color = "#77674DE6", icon = "token-custom" } +-- XML background color for each token +local tokenColor = { + ["Skull"] = "#4A0400E6", + ["Cultist"] = "#173B0BE6", + ["Tablet"] = "#1D2238E6", + ["Elder Thing"] = "#4D2331E6", + ["Auto-fail"] = "#9B0004E6", + ["Bless"] = "#9D702CE6", + ["Curse"] = "#633A84E6", + ["Frost"] = "#404450E6", + [""] = "#77674DE6" } local sigil @@ -36,13 +25,18 @@ function onLoad(savedData) self.addContextMenuItem("Enable Helper", chooseSigil) sigil = JSON.decode(savedData) if sigil and sigil ~= nil then - makeXMLButton(sigil) + makeXMLButton() self.clearContextMenu() self.addContextMenuItem("Clear Helper", deleteButtons) end end -function makeXMLButton(chosenToken) +function makeXMLButton() + -- get name of the icon for the sigil ("token" + lowercase name without space characters) + local sigilName = Global.call("getReadableTokenName", sigil) + local iconName = "token-" .. string.lower(sigilName) + iconName = iconName:gsub("%s", "-") + self.UI.setXmlTable({ { tag = "Button", @@ -55,15 +49,15 @@ function makeXMLButton(chosenToken) padding = "50 50 50 50", font = "font_teutonic-arkham", fontSize = 300, - iconWidth = 400, + iconWidth = "400", iconAlignment = "Right", onClick = "resolveSigil", id = sigil, - icon = dataForToken[sigil].icon, - color = dataForToken[sigil].color, - textColor = "White", + icon = iconName, + color = tokenColor[sigil], + textColor = "White" }, - value = "Resolve", + value = "Resolve" } } ) @@ -73,10 +67,18 @@ end function chooseSigil(playerColor) self.clearContextMenu() self.addContextMenuItem("Clear Helper", deleteButtons) - Player[playerColor].showOptionsDialog("Choose Sigil", tokenNames, 1, + + -- get list of readable names + local readableNames = {} + for token, _ in pairs(tokenColor) do + table.insert(readableNames, Global.call("getReadableTokenName", token)) + end + + -- prompt player to choose sigil + Player[playerColor].showOptionsDialog("Choose Sigil", readableNames, 1, function(chosenToken) sigil = Global.call("getChaosTokenName", chosenToken) - makeXMLButton(sigil) + makeXMLButton() end ) end @@ -92,14 +94,16 @@ end function resolveSigil() local tokensInPlay = chaosBagApi.getTokensInPlay() local chaosbag = chaosBagApi.findChaosBag() + local match = false - for i, obj in ipairs(chaosbag.getObjects()) do + for _, obj in ipairs(chaosbag.getObjects()) do -- if there are any sigils in the bag if obj.nickname == sigil then match = true break end end + if not match then broadcastToAll(Global.call("getReadableTokenName", sigil) .. " not found in chaos bag", "Red") return @@ -107,8 +111,11 @@ function resolveSigil() local matchingSymbolsInPlay = {} - for j, token in ipairs(tokensInPlay) do - if (token.getName() == "Cultist" or token.getName() == "Elder Thing" or token.getName() == "Tablet") and token.getName() ~= sigil then + for _, token in ipairs(tokensInPlay) do + if (token.getName() == "Cultist" + or token.getName() == "Tablet" + or token.getName() == "Elder Thing") + and token.getName() ~= sigil then matchingSymbolsInPlay[#matchingSymbolsInPlay + 1] = token end end @@ -117,7 +124,7 @@ function resolveSigil() broadcastToAll("No eligible symbol token found in play area", "Red") return elseif #matchingSymbolsInPlay > 1 then - for j, token in ipairs(matchingSymbolsInPlay) do + for _, token in ipairs(matchingSymbolsInPlay) do -- draw XML to return token to bag token.UI.setXmlTable({ { @@ -131,7 +138,7 @@ function resolveSigil() rotation = "0 0 180", position = "0 0 -15", color = "rgba(0,0,0,0.7)", - onClick = self.getGUID() .. "/drawSigil(" .. token.getGUID() .. ")", + onClick = self.getGUID() .. "/drawSigil(" .. token.getGUID() .. ")" }, children = { { @@ -140,18 +147,18 @@ function resolveSigil() fontSize = "100", font = "font_teutonic-arkham", color = "#ffffff", - text = "Nkosi", - }, + text = "Nkosi" + } }, { tag = "Text", attributes = { fontSize = "125", - font = "font_arkhamslim", + font = "font_arkhamicons", color = "#ffffff", - text = "U", - }, - }, + text = "u" + } + } } } }) @@ -162,15 +169,17 @@ function resolveSigil() end function drawSigil(player, tokenGUID) - returnedToken = getObjectFromGUID(tokenGUID) + local returnedToken = getObjectFromGUID(tokenGUID) local matColor = playmatApi.getMatColorByPosition(returnedToken.getPosition()) local mat = guidReferenceApi.getObjectByOwnerAndType(matColor, "Playermat") - chaosBagApi.drawChaosToken(mat, true, sigil, _, returnedToken) - local tokensInPlay = chaosBagApi.getTokensInPlay() - for j, returnedToken in ipairs(tokensInPlay) do - if returnedToken.getName() == "Cultist" or returnedToken.getName() == "Elder Thing" or returnedToken.getName() == "Tablet" then - returnedToken.UI.setXml("") + + -- remove XML from tokens in play + for _, token in ipairs(chaosBagApi.getTokensInPlay()) do + if token.getName() == "Cultist" + or token.getName() == "Tablet" + or token.getName() == "Elder Thing" then + token.UI.setXml("") end end end diff --git a/src/playermat/Playmat.ttslua b/src/playermat/Playmat.ttslua index b7e87488..d3a226cb 100644 --- a/src/playermat/Playmat.ttslua +++ b/src/playermat/Playmat.ttslua @@ -1,22 +1,22 @@ -local chaosBagApi = require("chaosbag/ChaosBagApi") -local deckLib = require("util/DeckLib") -local guidReferenceApi = require("core/GUIDReferenceApi") -local mythosAreaApi = require("core/MythosAreaApi") -local navigationOverlayApi = require("core/NavigationOverlayApi") -local searchLib = require("util/SearchLib") -local tokenChecker = require("core/token/TokenChecker") -local tokenManager = require("core/token/TokenManager") +local chaosBagApi = require("chaosbag/ChaosBagApi") +local deckLib = require("util/DeckLib") +local guidReferenceApi = require("core/GUIDReferenceApi") +local mythosAreaApi = require("core/MythosAreaApi") +local navigationOverlayApi = require("core/NavigationOverlayApi") +local searchLib = require("util/SearchLib") +local tokenChecker = require("core/token/TokenChecker") +local tokenManager = require("core/token/TokenManager") -- we use this to turn off collision handling until onLoad() is complete -local collisionEnabled = false +local collisionEnabled = false -- x-Values for discard buttons -local DISCARD_BUTTON_OFFSETS = {-1.365, -0.91, -0.455, 0, 0.455, 0.91} +local DISCARD_BUTTON_OFFSETS = { -1.365, -0.91, -0.455, 0, 0.455, 0.91 } local SEARCH_AROUND_SELF_X_BUFFER = 8 -- defined areas for object searching -local MAIN_PLAY_AREA = { +local MAIN_PLAY_AREA = { upperLeft = { x = 1.98, z = 0.736 @@ -26,7 +26,7 @@ local MAIN_PLAY_AREA = { z = -0.39 } } -local INVESTIGATOR_AREA = { +local INVESTIGATOR_AREA = { upperLeft = { x = -1.084, z = 0.06517 @@ -36,7 +36,7 @@ local INVESTIGATOR_AREA = { z = -0.0805 } } -local THREAT_AREA = { +local THREAT_AREA = { upperLeft = { x = 1.53, z = -0.34 @@ -46,7 +46,7 @@ local THREAT_AREA = { z = -0.92 } } -local DECK_DISCARD_AREA = { +local DECK_DISCARD_AREA = { upperLeft = { x = -1.62, z = 0.855 @@ -68,24 +68,24 @@ local DECK_DISCARD_AREA = { } -- local position of draw and discard pile -local DRAW_DECK_POSITION = { x = -1.82, y = 0.1, z = 0 } -local DISCARD_PILE_POSITION = { x = -1.82, y = 0.1, z = 0.61 } +local DRAW_DECK_POSITION = { x = -1.82, y = 0.1, z = 0 } +local DISCARD_PILE_POSITION = { x = -1.82, y = 0.1, z = 0.61 } -- global position of encounter discard pile -local ENCOUNTER_DISCARD_POSITION = { x = -3.85, y = 1.5, z = 10.38} +local ENCOUNTER_DISCARD_POSITION = { x = -3.85, y = 1.5, z = 10.38 } -- global variable so it can be reset by the Clean Up Helper -activeInvestigatorId = "00000" +activeInvestigatorId = "00000" -- table of type-object reference pairs of all owned objects -local ownedObjects = {} -local matColor = self.getMemo() +local ownedObjects = {} +local matColor = self.getMemo() -- variable to track the status of the "Show Draw Button" option -local isDrawButtonVisible = false +local isDrawButtonVisible = false -- global variable to report "Dream-Enhancing Serum" status -isDES = false +isDES = false function onSave() return JSON.encode({ @@ -116,8 +116,8 @@ function onLoad(savedData) self.createButton({ click_function = "drawEncounterCard", function_owner = self, - position = {-1.84, 0, -0.65}, - rotation = {0, 80, 0}, + position = { -1.84, 0, -0.65 }, + rotation = { 0, 80, 0 }, width = 265, height = 190 }) @@ -125,8 +125,8 @@ function onLoad(savedData) self.createButton({ click_function = "drawChaosTokenButton", function_owner = self, - position = {1.85, 0, -0.74}, - rotation = {0, -45, 0}, + position = { 1.85, 0, -0.74 }, + rotation = { 0, -45, 0 }, width = 135, height = 135 }) @@ -135,8 +135,19 @@ function onLoad(savedData) label = "Upkeep", click_function = "doUpkeep", function_owner = self, - position = {1.84, 0.1, -0.44}, - scale = {0.12, 0.12, 0.12}, + position = { 1.84, 0.1, -0.44 }, + scale = { 0.12, 0.12, 0.12 }, + width = 800, + height = 280, + font_size = 180 + }) + + self.createButton({ + label = "Edit Slots", + click_function = "editSlots", + function_owner = self, + position = { 1.84, 0.1, 0.84 }, + scale = { 0.12, 0.12, 0.12 }, width = 800, height = 280, font_size = 180 @@ -145,6 +156,7 @@ function onLoad(savedData) showDrawButton(isDrawButtonVisible) math.randomseed(os.time()) Wait.time(function() collisionEnabled = true end, 0.1) + updateSlots() end --------------------------------------------------------- @@ -178,7 +190,7 @@ function searchDeckAndDiscardArea(filter) local scale = self.getScale() local size = { x = DECK_DISCARD_AREA.size.x * scale.x, - y = DECK_DISCARD_AREA.size.y, + y = DECK_DISCARD_AREA.size.y, z = DECK_DISCARD_AREA.size.z * scale.z } return searchArea(pos, size, filter) @@ -192,7 +204,7 @@ end ---@param num number Initial value ---@param numDecimalPlaces number Amount of decimal places function round(num, numDecimalPlaces) - local mult = 10^(numDecimalPlaces or 0) + local mult = 10 ^ (numDecimalPlaces or 0) return math.floor(num * mult + 0.5) / mult end @@ -208,12 +220,12 @@ function discardListOfObjects(objList) if obj.hasTag("PlayerCard") then deckLib.placeOrMergeIntoDeck(obj, returnGlobalDiscardPosition(), self.getRotation()) else - deckLib.placeOrMergeIntoDeck(obj, ENCOUNTER_DISCARD_POSITION, {x = 0, y = -90, z = 0}) + deckLib.placeOrMergeIntoDeck(obj, ENCOUNTER_DISCARD_POSITION, { x = 0, y = -90, z = 0 }) end - -- put chaos tokens back into bag (e.g. Unrelenting) + -- put chaos tokens back into bag (e.g. Unrelenting) elseif tokenChecker.isChaosToken(obj) then chaosBagApi.returnChaosTokenToBag(obj) - -- don't touch locked objects (like the table etc.) or specific objects (like key tokens) + -- don't touch locked objects (like the table etc.) or specific objects (like key tokens) elseif not obj.getLock() and not obj.hasTag("DontDiscard") then ownedObjects.Trash.putObject(obj) end @@ -222,11 +234,11 @@ end -- build a discard button to discard from searchPosition (number must be unique) function makeDiscardButton(xValue, number) - local position = { xValue, 0.1, -0.94} - local searchPosition = {-position[1], position[2], position[3] + 0.32} + local position = { xValue, 0.1, -0.94 } + local searchPosition = { -position[1], position[2], position[3] + 0.32 } local handlerName = 'handler' .. number self.setVar(handlerName, function() - local cardSizeSearch = {2, 1, 3.2} + local cardSizeSearch = { 2, 1, 3.2 } local globalSearchPosition = self.positionToWorld(searchPosition) local searchResult = searchArea(globalSearchPosition, cardSizeSearch) return discardListOfObjects(searchResult) @@ -236,7 +248,7 @@ function makeDiscardButton(xValue, number) click_function = handlerName, function_owner = self, position = position, - scale = {0.12, 0.12, 0.12}, + scale = { 0.12, 0.12, 0.12 }, width = 900, height = 350, font_size = 220 @@ -286,7 +298,7 @@ function doUpkeep(_, clickedByColor, isRightClick) -- set correct rotation for face-down cards rot.z = obj.is_face_down and 180 or 0 - obj.setRotation({rot.x, rot.y + yRotDiff, rot.z}) + obj.setRotation({ rot.x, rot.y + yRotDiff, rot.z }) end if cardMetadata.id == "08031" then forcedLearning = true @@ -294,7 +306,7 @@ function doUpkeep(_, clickedByColor, isRightClick) if cardMetadata.uses ~= nil then tokenManager.maybeReplenishCard(obj, cardMetadata.uses, self) end - -- check decks for forced learning + -- check decks for forced learning elseif obj.type == "Deck" and forcedLearning == false then for _, deepObj in ipairs(obj.getObjects()) do local cardMetadata = JSON.decode(deepObj.gm_notes) or {} @@ -319,16 +331,18 @@ function doUpkeep(_, clickedByColor, isRightClick) -- gain a resource (or two if playing Jenny Barnes) if string.match(activeInvestigatorId, "%d%d%d%d%d") == "02003" then - updateCounter({type = "ResourceCounter", modifier = 2}) + updateCounter({ type = "ResourceCounter", modifier = 2 }) printToColor("Gaining 2 resources (Jenny)", messageColor) else - updateCounter({type = "ResourceCounter", modifier = 1}) + updateCounter({ type = "ResourceCounter", modifier = 1 }) end -- draw a card (with handling for Patrice and Forced Learning) if activeInvestigatorId == "06005" then if forcedLearning then - printToColor("Wow, did you really take 'Versatile' to play Patrice with 'Forced Learning'? Choose which draw replacement effect takes priority and draw cards accordingly.", messageColor) + printToColor( + "Wow, did you really take 'Versatile' to play Patrice with 'Forced Learning'? Choose which draw replacement effect takes priority and draw cards accordingly.", + messageColor) else local handSize = #Player[playerColor].getHandObjects() if handSize < 5 then @@ -421,7 +435,7 @@ function getDeckAreaObjects() for _, object in ipairs(searchDeckAndDiscardArea("isCardOrDeck")) do if self.positionToLocal(object.getPosition()).z > 0.5 then deckAreaObjects.discard = object - -- Norman Withers handling + -- Norman Withers handling elseif object.type == "Card" and not object.is_face_down then deckAreaObjects.topCard = object else @@ -497,6 +511,111 @@ function doDiscardOne() end end +--------------------------------------------------------- +-- playmat slot modifying +--------------------------------------------------------- + +-- translation table for slot names to characters for special font +local slotFontCharacter = { + ["any"] = "", + ["Accessory"] = "C", + ["Ally"] = "E", + ["Arcane"] = "G", + ["Body"] = "K", + ["Hand (right)"] = "M", + ["Hand (left)"] = "M", + ["Hand x2"] = "N", + ["Tarot"] = "A" +} + +-- top left to bottom right +local slotData = { + "any", + "any", + "any", + "Tarot", + "Hand (left)", + "Hand (right)", + "Ally", + + -- 2nd row + "any", + "any", + "any", + "Accessory", + "Arcane", + "Arcane", + "Body" +} + +function updateSlots() + local xml = {} + local snapId = 0 + + for _, snap in ipairs(self.getSnapPoints()) do + if inArea(snap.position, MAIN_PLAY_AREA) then + snapId = snapId + 1 + + local slotName = slotData[snapId] + local slotRotation = "0 0 180" + if slotName == "Hand (left)" then + slotRotation = "0 180 180" + end + + -- increased coordinates to account for scale (0.1) + local x = snap.position.x * 100 + local y = snap.position.z * 100 + local slotXML = { + tag = "Panel", + attributes = { + scale = "0.1 0.1 1", + width="150", + height="150", + rotation = slotRotation, + position = x .. " " .. y .. " -11" + }, + children = { + { + tag = "Text", + attributes = { + id = "slot" .. snapId, + fontSize = "145", + font = "font_arkhamicons", + color = "#414141CB", + text = slotFontCharacter[slotName] + } + } + } + } + table.insert(xml, slotXML) + end + end + + self.UI.setXmlTable(xml) +end + +function editSlots() + for i = 1, #slotData do + self.UI.setAttribute("slot" .. i, "onClick", "slotClickfunction") + end +end + +function slotClickfunction(player, _, id) + local index = id:gsub("slot", "") + local slotNames = {} + for slotName, _ in pairs(slotFontCharacter) do + table.insert(slotNames, slotName) + end + + -- prompt player to choose symbol + player.showOptionsDialog("Choose Slot Symbol", slotNames, slotData[index], + function(chosenSlot, chosenIndex) + self.UI.setAttribute(id, "text", slotFontCharacter[chosenSlot]) + slotData[chosenIndex] = chosenSlot + end + ) +end + --------------------------------------------------------- -- color related functions --------------------------------------------------------- @@ -558,12 +677,12 @@ function syncAllCustomizableCards() end function syncCustomizableMetadata(card) - local cardMetadata = JSON.decode(card.getGMNotes()) or { } + local cardMetadata = JSON.decode(card.getGMNotes()) or {} if cardMetadata == nil or cardMetadata.customizations == nil then return end for _, upgradeSheet in ipairs(searchAroundSelf("isCard")) do - local upgradeSheetMetadata = JSON.decode(upgradeSheet.getGMNotes()) or { } + local upgradeSheetMetadata = JSON.decode(upgradeSheet.getGMNotes()) or {} if upgradeSheetMetadata.id == (cardMetadata.id .. "-c") then for i, customization in ipairs(cardMetadata.customizations) do if customization.replaces ~= nil and customization.replaces.uses ~= nil then @@ -584,7 +703,7 @@ function syncCustomizableMetadata(card) end function spawnTokensFor(object) - local extraUses = { } + local extraUses = {} if activeInvestigatorId == "03004" then extraUses["Charge"] = 1 end @@ -638,15 +757,15 @@ function shouldSpawnTokens(card) -- Spawn tokens for assets and events on the main area if inArea(localCardPos, MAIN_PLAY_AREA) and (metadata.type == "Asset" - or metadata.type == "Event") then + or metadata.type == "Event") then return true end -- Spawn tokens for all encounter types in the threat area if inArea(localCardPos, THREAT_AREA) and (metadata.type == "Treachery" - or metadata.type == "Enemy" - or metadata.weakness) then + or metadata.type == "Enemy" + or metadata.weakness) then return true end @@ -710,13 +829,13 @@ function maybeUpdateActiveInvestigator(card) elseif activeInvestigatorId ~= "00000" then class = "Neutral" activeInvestigatorId = "00000" - ownedObjects.InvestigatorSkillTracker.call("updateStats", {1, 1, 1, 1}) + ownedObjects.InvestigatorSkillTracker.call("updateStats", { 1, 1, 1, 1 }) else return end -- change state of action tokens - local search = searchArea(self.positionToWorld({-1.1, 0.05, -0.27}), {4, 1, 1}) + local search = searchArea(self.positionToWorld({ -1.1, 0.05, -0.27 }), { 4, 1, 1 }) local smallToken = nil local STATE_TABLE = { ["Guardian"] = 1, @@ -783,12 +902,12 @@ end -- set investigator skill tracker to "1, 1, 1, 1" function resetSkillTracker() - local obj = ownedObjects.InvestigatorSkillTracker - if obj ~= nil then - obj.call("updateStats", { 1, 1, 1, 1 }) - else - printToAll("Skill tracker for " .. matColor .. " playmat could not be found.", "Yellow") - end + local obj = ownedObjects.InvestigatorSkillTracker + if obj ~= nil then + obj.call("updateStats", { 1, 1, 1, 1 }) + else + printToAll("Skill tracker for " .. matColor .. " playmat could not be found.", "Yellow") + end end --------------------------------------------------------- @@ -819,17 +938,17 @@ function showDrawButton(visible) -- create the "Draw 1" button if isDrawButtonVisible then self.createButton({ - label = "Draw 1", - click_function = "doDrawOne", - function_owner = self, - position = { 1.84, 0.1, -0.36 }, - scale = { 0.12, 0.12, 0.12 }, - width = 800, - height = 280, - font_size = 180 + label = "Draw 1", + click_function = "doDrawOne", + function_owner = self, + position = { 1.84, 0.1, -0.36 }, + scale = { 0.12, 0.12, 0.12 }, + width = 800, + height = 280, + font_size = 180 }) - -- remove the "Draw 1" button + -- remove the "Draw 1" button else local buttons = self.getButtons() for i = 1, #buttons do @@ -845,7 +964,7 @@ end function clickableClues(showCounter) local clickerPos = ownedObjects.ClickableClueCounter.getPosition() local clueCount = 0 - + -- move clue counters local modY = showCounter and 0.525 or -0.525 ownedObjects.ClickableClueCounter.setPosition(clickerPos + Vector(0, modY, 0)) @@ -864,7 +983,7 @@ function clickableClues(showCounter) clueCount = ownedObjects.ClickableClueCounter.getVar("val") -- spawn clues - local pos = self.positionToWorld({x = -1.12, y = 0.05, z = 0.7}) + local pos = self.positionToWorld({ x = -1.12, y = 0.05, z = 0.7 }) for i = 1, clueCount do pos.y = pos.y + 0.045 * i tokenManager.spawnToken(pos, "clue", self.getRotation()) @@ -895,8 +1014,7 @@ end function setLimitSnapsByType(matchTypes) local snaps = self.getSnapPoints() for i, snap in ipairs(snaps) do - local snapPos = snap.position - if inArea(snapPos, MAIN_PLAY_AREA) then + if inArea(snap.position, MAIN_PLAY_AREA) then local snapTags = snaps[i].tags if matchTypes then if snapTags == nil then @@ -908,7 +1026,7 @@ function setLimitSnapsByType(matchTypes) snaps[i].tags = nil end end - if inArea(snapPos, INVESTIGATOR_AREA) then + if inArea(snap.position, INVESTIGATOR_AREA) then local snapTags = snaps[i].tags if matchTypes then if snapTags == nil then @@ -931,9 +1049,9 @@ end ---@return boolean: True if the point is in the area defined by bounds function inArea(point, bounds) return (point.x < bounds.upperLeft.x - and point.x > bounds.lowerRight.x - and point.z < bounds.upperLeft.z - and point.z > bounds.lowerRight.z) + and point.x > bounds.lowerRight.x + and point.z < bounds.upperLeft.z + and point.z > bounds.lowerRight.z) end -- called by custom data helpers to add player card data From bff9dee13078d2c040073369cbede6715b0795fd Mon Sep 17 00:00:00 2001 From: Chr1Z93 Date: Fri, 26 Apr 2024 11:14:13 +0200 Subject: [PATCH 022/157] updated playermat --- src/core/GameKeyHandler.ttslua | 2 +- src/playermat/Playmat.ttslua | 308 ++++++++++++++++++--------------- 2 files changed, 169 insertions(+), 141 deletions(-) diff --git a/src/core/GameKeyHandler.ttslua b/src/core/GameKeyHandler.ttslua index 049dd7cb..cd77b04f 100644 --- a/src/core/GameKeyHandler.ttslua +++ b/src/core/GameKeyHandler.ttslua @@ -37,7 +37,7 @@ function triggerUpkeep(playerColor) end -- triggers the "Upkeep" function of the calling player's playmat AND --- for all playmats that don't have a seated player, but a investigator card +-- for all playmats that don't have a seated player, but an investigator card function triggerUpkeepMultihanded(playerColor) if playerColor ~= "Black" then triggerUpkeep(playerColor) diff --git a/src/playermat/Playmat.ttslua b/src/playermat/Playmat.ttslua index d3a226cb..6741857c 100644 --- a/src/playermat/Playmat.ttslua +++ b/src/playermat/Playmat.ttslua @@ -9,6 +9,7 @@ local tokenManager = require("core/token/TokenManager") -- we use this to turn off collision handling until onLoad() is complete local collisionEnabled = false +local currentlyEditingSlots = false -- x-Values for discard buttons local DISCARD_BUTTON_OFFSETS = { -1.365, -0.91, -0.455, 0, 0.455, 0.91 } @@ -17,54 +18,22 @@ local SEARCH_AROUND_SELF_X_BUFFER = 8 -- defined areas for object searching local MAIN_PLAY_AREA = { - upperLeft = { - x = 1.98, - z = 0.736 - }, - lowerRight = { - x = -0.79, - z = -0.39 - } + upperLeft = { x = 1.98, z = 0.736 }, + lowerRight = { x = -0.79, z = -0.39 } } local INVESTIGATOR_AREA = { - upperLeft = { - x = -1.084, - z = 0.06517 - }, - lowerRight = { - x = -1.258, - z = -0.0805 - } + upperLeft = { x = -1.084, z = 0.06517 }, + lowerRight = { x = -1.258, z = -0.0805 } } local THREAT_AREA = { - upperLeft = { - x = 1.53, - z = -0.34 - }, - lowerRight = { - x = -1.13, - z = -0.92 - } + upperLeft = { x = 1.53, z = -0.34 }, + lowerRight = { x = -1.13, z = -0.92 } } local DECK_DISCARD_AREA = { - upperLeft = { - x = -1.62, - z = 0.855 - }, - lowerRight = { - x = -2.02, - z = -0.245 - }, - center = { - x = -1.82, - y = 0.5, - z = 0.305 - }, - size = { - x = 0.4, - y = 3, - z = 1.1 - } + upperLeft = { x = -1.62, z = 0.855 }, + lowerRight = { x = -2.02, z = -0.245 }, + center = { x = -1.82, y = 0.5, z = 0.305 }, + size = { x = 0.4, y = 3, z = 1.1 } } -- local position of draw and discard pile @@ -74,24 +43,46 @@ local DISCARD_PILE_POSITION = { x = -1.82, y = 0.1, z = 0.61 } -- global position of encounter discard pile local ENCOUNTER_DISCARD_POSITION = { x = -3.85, y = 1.5, z = 10.38 } +-- translation table for slot names to characters for special font +local slotNameToChar = { + ["any"] = "", + ["Accessory"] = "C", + ["Ally"] = "E", + ["Arcane"] = "G", + ["Body"] = "K", + ["Hand (right)"] = "M", + ["Hand (left)"] = "M", + ["Hand x2"] = "N", + ["Tarot"] = "A" +} + +-- slot symbol for the respective slot (from top left to bottom right) +local slotData +local defaultSlotData = { + -- 1st row + "any", "any", "any", "Tarot", "Hand (left)", "Hand (right)", "Ally", + + -- 2nd row + "any", "any", "any", "Accessory", "Arcane", "Arcane", "Body" +} + -- global variable so it can be reset by the Clean Up Helper activeInvestigatorId = "00000" - --- table of type-object reference pairs of all owned objects -local ownedObjects = {} -local matColor = self.getMemo() - --- variable to track the status of the "Show Draw Button" option local isDrawButtonVisible = false -- global variable to report "Dream-Enhancing Serum" status isDES = false +-- table of type-object reference pairs of all owned objects +local ownedObjects = {} +local matColor = self.getMemo() + function onSave() return JSON.encode({ playerColor = playerColor, activeInvestigatorId = activeInvestigatorId, - isDrawButtonVisible = isDrawButtonVisible + isDrawButtonVisible = isDrawButtonVisible, + slotData = slotData }) end @@ -101,6 +92,17 @@ function onLoad(savedData) playerColor = loadedData.playerColor activeInvestigatorId = loadedData.activeInvestigatorId isDrawButtonVisible = loadedData.isDrawButtonVisible + + -- To-Do: remove this once the save state is properly populated + if loadedData.slotData then + slotData = loadedData.slotData + else + -- make a deep copy of the default table + slotData = {} + for _, slotName in ipairs(defaultSlotData) do + table.insert(slotData, slotName) + end + end end self.interactable = false @@ -108,7 +110,7 @@ function onLoad(savedData) -- get object references to owned objects ownedObjects = guidReferenceApi.getObjectsByOwner(matColor) - -- button creation + -- discard button creation for i = 1, 6 do makeDiscardButton(DISCARD_BUTTON_OFFSETS[i], i) end @@ -134,29 +136,31 @@ function onLoad(savedData) self.createButton({ label = "Upkeep", click_function = "doUpkeep", + tooltip = "Right-click to change color", function_owner = self, position = { 1.84, 0.1, -0.44 }, scale = { 0.12, 0.12, 0.12 }, - width = 800, + width = 1000, height = 280, font_size = 180 }) self.createButton({ label = "Edit Slots", - click_function = "editSlots", + click_function = "toggleSlotEditing", + tooltip = "Right-click to reset slot symbols", function_owner = self, - position = { 1.84, 0.1, 0.84 }, + position = { 1.84, 0.1, 0.94 }, scale = { 0.12, 0.12, 0.12 }, - width = 800, + width = 1000, height = 280, font_size = 180 }) showDrawButton(isDrawButtonVisible) + redrawSlotXML() math.randomseed(os.time()) Wait.time(function() collisionEnabled = true end, 0.1) - updateSlots() end --------------------------------------------------------- @@ -196,18 +200,33 @@ function searchDeckAndDiscardArea(filter) return searchArea(pos, size, filter) end -function doNotReady(card) - return card.getVar("do_not_ready") or false -end - -- rounds a number to the specified amount of decimal places ---@param num number Initial value ---@param numDecimalPlaces number Amount of decimal places +---@return number: rounded number function round(num, numDecimalPlaces) local mult = 10 ^ (numDecimalPlaces or 0) return math.floor(num * mult + 0.5) / mult end +-- edits the label of a button +---@param oldLabel string Old label of the button +---@param newLabel string New label of the button +function editButtonLabel(oldLabel, newLabel) + local buttons = self.getButtons() + for i = 1, #buttons do + if buttons[i].label == oldLabel then + self.editButton({ index = buttons[i].index, label = newLabel }) + end + end +end + +-- updates the internal "messageColor" which is used for print/broadcast statements if no player is seated +---@param clickedByColor string Colorstring of player who clicked a button +function updateMessageColor(clickedByColor) + messageColor = Player[playerColor].seated and playerColor or clickedByColor +end + --------------------------------------------------------- -- Discard buttons --------------------------------------------------------- @@ -260,8 +279,8 @@ end --------------------------------------------------------- -- calls the Upkeep function with correct parameter -function doUpkeepFromHotkey(color) - doUpkeep(_, color) +function doUpkeepFromHotkey(clickedByColor) + doUpkeep(_, clickedByColor) end function doUpkeep(_, clickedByColor, isRightClick) @@ -270,8 +289,7 @@ function doUpkeep(_, clickedByColor, isRightClick) return end - -- send messages to player who clicked button if no seated player found - messageColor = Player[playerColor].seated and playerColor or clickedByColor + updateMessageColor(clickedByColor) -- unexhaust cards in play zone, flip action tokens and find forcedLearning local forcedLearning = false @@ -281,7 +299,7 @@ function doUpkeep(_, clickedByColor, isRightClick) obj.flip() elseif obj.type == "Card" and not inArea(self.positionToLocal(obj.getPosition()), INVESTIGATOR_AREA) then local cardMetadata = JSON.decode(obj.getGMNotes()) or {} - if not doNotReady(obj) then + if not (obj.getVar("do_not_ready") or false) then local cardRotation = round(obj.getRotation().y, 0) - rot.y local yRotDiff = 0 @@ -300,14 +318,18 @@ function doUpkeep(_, clickedByColor, isRightClick) rot.z = obj.is_face_down and 180 or 0 obj.setRotation({ rot.x, rot.y + yRotDiff, rot.z }) end + + -- detect forced learning to handle card drawing accordingly if cardMetadata.id == "08031" then forcedLearning = true end + + -- maybe replenish uses on certain cards if cardMetadata.uses ~= nil then tokenManager.maybeReplenishCard(obj, cardMetadata.uses, self) end - -- check decks for forced learning elseif obj.type == "Deck" and forcedLearning == false then + -- check decks for forced learning for _, deepObj in ipairs(obj.getObjects()) do local cardMetadata = JSON.decode(deepObj.gm_notes) or {} if cardMetadata.id == "08031" then @@ -340,9 +362,8 @@ function doUpkeep(_, clickedByColor, isRightClick) -- draw a card (with handling for Patrice and Forced Learning) if activeInvestigatorId == "06005" then if forcedLearning then - printToColor( - "Wow, did you really take 'Versatile' to play Patrice with 'Forced Learning'? Choose which draw replacement effect takes priority and draw cards accordingly.", - messageColor) + printToColor("Wow, did you really take 'Versatile' to play Patrice with 'Forced Learning'?" + .. " Choose which draw replacement effect takes priority and draw cards accordingly.", messageColor) else local handSize = #Player[playerColor].getHandObjects() if handSize < 5 then @@ -362,14 +383,14 @@ function doUpkeep(_, clickedByColor, isRightClick) end end --- function for "draw 1 button" (that can be added via option panel) -function doDrawOne(_, color) - -- send messages to player who clicked button if no seated player found - messageColor = Player[playerColor].seated and playerColor or color +-- click function for "draw 1 button" (that can be added via option panel) +function doDrawOne(_, clickedByColor) + updateMessageColor(clickedByColor) drawCardsWithReshuffle(1) end --- draw X cards (shuffle discards if necessary) +-- draws the specified amount of cards (and shuffles the discard if necessary) +---@param numCards num Number of cards to draw function drawCardsWithReshuffle(numCards) local deckAreaObjects = getDeckAreaObjects() @@ -430,6 +451,7 @@ function drawCardsWithReshuffle(numCards) end -- get the draw deck and discard pile objects and returns the references +---@return table: string-indexed table with references to the found objects function getDeckAreaObjects() local deckAreaObjects = {} for _, object in ipairs(searchDeckAndDiscardArea("isCardOrDeck")) do @@ -483,7 +505,7 @@ end function doDiscardOne() local hand = Player[playerColor].getHandObjects() if #hand == 0 then - broadcastToAll("Cannot discard from empty hand!", "Red") + broadcastToColor("Cannot discard from empty hand!", messageColor, "Red") else local choices = {} for i = 1, #hand do @@ -498,7 +520,7 @@ function doDiscardOne() end if #choices == 0 then - broadcastToAll("Hidden cards can't be randomly discarded.", "Orange") + broadcastToColor("Hidden cards can't be randomly discarded.", messageColor, "Orange") return end @@ -512,55 +534,19 @@ function doDiscardOne() end --------------------------------------------------------- --- playmat slot modifying +-- slot modifying --------------------------------------------------------- --- translation table for slot names to characters for special font -local slotFontCharacter = { - ["any"] = "", - ["Accessory"] = "C", - ["Ally"] = "E", - ["Arcane"] = "G", - ["Body"] = "K", - ["Hand (right)"] = "M", - ["Hand (left)"] = "M", - ["Hand x2"] = "N", - ["Tarot"] = "A" -} - --- top left to bottom right -local slotData = { - "any", - "any", - "any", - "Tarot", - "Hand (left)", - "Hand (right)", - "Ally", - - -- 2nd row - "any", - "any", - "any", - "Accessory", - "Arcane", - "Arcane", - "Body" -} - -function updateSlots() +-- this will redraw the XML for the slot symbols based on the slotData table +function redrawSlotXML() local xml = {} local snapId = 0 + -- use the snap point positions in the main play area for positions for _, snap in ipairs(self.getSnapPoints()) do if inArea(snap.position, MAIN_PLAY_AREA) then snapId = snapId + 1 - local slotName = slotData[snapId] - local slotRotation = "0 0 180" - if slotName == "Hand (left)" then - slotRotation = "0 180 180" - end -- increased coordinates to account for scale (0.1) local x = snap.position.x * 100 @@ -568,10 +554,11 @@ function updateSlots() local slotXML = { tag = "Panel", attributes = { + id = "slotPanel" .. snapId, scale = "0.1 0.1 1", - width="150", - height="150", - rotation = slotRotation, + width = "150", + height = "150", + rotation = getSlotRotation(slotName), position = x .. " " .. y .. " -11" }, children = { @@ -582,7 +569,7 @@ function updateSlots() fontSize = "145", font = "font_arkhamicons", color = "#414141CB", - text = slotFontCharacter[slotName] + text = slotNameToChar[slotName] } } } @@ -594,28 +581,72 @@ function updateSlots() self.UI.setXmlTable(xml) end -function editSlots() +-- toggle the "slot editing mode" +function toggleSlotEditing(_, clickedByColor, isRightClick) + if isRightClick then + resetSlotSymbols() + return + end + + updateMessageColor(clickedByColor) + + -- toggle internal variable + currentlyEditingSlots = not currentlyEditingSlots + + if currentlyEditingSlots then + editButtonLabel("Edit Slots", "Stop editing") + broadcastToColor("Click on a slot symbol (or an empty slot) to edit it.", messageColor, "Orange") + else + editButtonLabel("Stop editing", "Edit Slots") + end + + -- set click function (or maybe disable it) + local clickFunc = currentlyEditingSlots and "slotClickfunction" or "" for i = 1, #slotData do - self.UI.setAttribute("slot" .. i, "onClick", "slotClickfunction") + self.UI.setAttribute("slot" .. i, "onClick", clickFunc) end end -function slotClickfunction(player, _, id) +-- click function for slot symbols during the "slot editing mode" +function slotClickfunction(player, clickType, id) local index = id:gsub("slot", "") local slotNames = {} - for slotName, _ in pairs(slotFontCharacter) do + for slotName, _ in pairs(slotNameToChar) do table.insert(slotNames, slotName) end -- prompt player to choose symbol player.showOptionsDialog("Choose Slot Symbol", slotNames, slotData[index], function(chosenSlot, chosenIndex) - self.UI.setAttribute(id, "text", slotFontCharacter[chosenSlot]) slotData[chosenIndex] = chosenSlot + + -- update slot symbol + self.UI.setAttribute(id, "text", slotNameToChar[chosenSlot]) + + -- update slot rotation + self.UI.setAttribute("slotPanel" .. chosenIndex, "rotation", getSlotRotation(chosenSlot)) end ) end +-- helper function to rotate the left hand +function getSlotRotation(slotName) + if slotName == "Hand (left)" then + return "0 180 180" + else + return "0 0 180" + end +end + +-- reset the slot symbols by making a deep copy of the default data and redrawing +function resetSlotSymbols() + slotData = {} + for _, slotName in ipairs(defaultSlotData) do + table.insert(slotData, slotName) + end + redrawSlotXML() +end + --------------------------------------------------------- -- color related functions --------------------------------------------------------- @@ -678,15 +709,13 @@ end function syncCustomizableMetadata(card) local cardMetadata = JSON.decode(card.getGMNotes()) or {} - if cardMetadata == nil or cardMetadata.customizations == nil then - return - end + if cardMetadata == nil or cardMetadata.customizations == nil then return end + for _, upgradeSheet in ipairs(searchAroundSelf("isCard")) do local upgradeSheetMetadata = JSON.decode(upgradeSheet.getGMNotes()) or {} if upgradeSheetMetadata.id == (cardMetadata.id .. "-c") then for i, customization in ipairs(cardMetadata.customizations) do if customization.replaces ~= nil and customization.replaces.uses ~= nil then - -- Allowed use of call(), no APIs for individual cards if upgradeSheet.call("isUpgradeActive", i) then cardMetadata.uses = customization.replaces.uses card.setGMNotes(JSON.encode(cardMetadata)) @@ -810,6 +839,8 @@ end -- investigator ID grabbing and skill tracker --------------------------------------------------------- +-- updates the internal investigator id and action tokens if an investigator card is detected +---@param card tts__Object Card that might be an investigator function maybeUpdateActiveInvestigator(card) if not inArea(self.positionToLocal(card.getPosition()), INVESTIGATOR_AREA) then return end @@ -880,7 +911,7 @@ end -- manipulation of owned objects --------------------------------------------------------- --- updates the specific owned counter +-- updates the specified owned counter ---@param param table Contains the information to update: --- type: String Counter to target --- newValue: Number Value to set the counter to @@ -894,8 +925,9 @@ function updateCounter(param) end end --- returns the resource counter amount +-- get the value the specified owned counter ---@param type string Counter to target +---@return number: Counter value function getCounterValue(type) return ownedObjects[type].getVar("val") end @@ -930,12 +962,11 @@ function returnGlobalDrawPosition() return self.positionToWorld(DRAW_DECK_POSITION) end --- Sets this playermat's draw 1 button to visible +-- creates / removes the draw 1 button ---@param visible boolean Whether the draw 1 button should be visible function showDrawButton(visible) isDrawButtonVisible = visible - -- create the "Draw 1" button if isDrawButtonVisible then self.createButton({ label = "Draw 1", @@ -943,12 +974,10 @@ function showDrawButton(visible) function_owner = self, position = { 1.84, 0.1, -0.36 }, scale = { 0.12, 0.12, 0.12 }, - width = 800, + width = 1000, height = 280, font_size = 180 }) - - -- remove the "Draw 1" button else local buttons = self.getButtons() for i = 1, #buttons do @@ -970,7 +999,7 @@ function clickableClues(showCounter) ownedObjects.ClickableClueCounter.setPosition(clickerPos + Vector(0, modY, 0)) if showCounter then - -- current clue count + -- get current clue count clueCount = ownedObjects.ClueCounter.getVar("exposedValue") -- remove clues @@ -979,7 +1008,7 @@ function clickableClues(showCounter) -- set value for clue clickers ownedObjects.ClickableClueCounter.call("updateVal", clueCount) else - -- current clue count + -- get current clue count clueCount = ownedObjects.ClickableClueCounter.getVar("val") -- spawn clues @@ -1042,10 +1071,9 @@ function setLimitSnapsByType(matchTypes) self.setSnapPoints(snaps) end --- Simple method to check if the given point is in a specified area. Local use only, +-- Simple method to check if the given point is in a specified area. Local use only ---@param point tts__Vector Point to check, only x and z values are relevant ----@param bounds table Defined area to see if the point is within. See MAIN_PLAY_AREA for sample --- bounds definition. +---@param bounds table Defined area to see if the point is within. See MAIN_PLAY_AREA for sample bounds definition. ---@return boolean: True if the point is in the area defined by bounds function inArea(point, bounds) return (point.x < bounds.upperLeft.x From 7aadd2adf0f53a27aa35e1640e88ba027cad1898 Mon Sep 17 00:00:00 2001 From: Chr1Z93 Date: Sat, 27 Apr 2024 19:15:22 +0200 Subject: [PATCH 023/157] added upper limit for bonded cards --- .../BiancaDieKatz.897a94.gmnotes | 1 + .../BrokenDiadem5.b6d35d.gmnotes | 1 + .../CrystallizerofDreams.6692de.gmnotes | 1 + .../DreamDiary.b81dcf.gmnotes | 1 + .../DreamDiary3.5f9a10.gmnotes | 1 + .../DreamDiary3.e5f9cb.gmnotes | 1 + .../DreamDiary3.ea40f6.gmnotes | 1 + .../EmptyVessel4.c0d236.gmnotes | 1 + .../EyesofValusia4.e7bfbe.gmnotes | 1 + .../FluxStabilizer.55990a.gmnotes | 2 ++ .../AllPlayerCards.15bb07/GateBox.b8c891.gmnotes | 1 + .../HallowedMirror.312d38.gmnotes | 1 + .../HallowedMirror3.78858f.gmnotes | 1 + .../HankSamson.3764cd.gmnotes | 2 ++ .../MiracleWish5.d78d4a.gmnotes | 1 + .../MissDoyle1.e1aedf.gmnotes | 3 +++ .../NightmareBauble3.d6f6f1.gmnotes | 1 + .../OccultLexicon.5d6728.gmnotes | 1 + .../OccultLexicon3.71d99c.gmnotes | 1 + .../RavenousMyconid.0aa967.gmnotes | 1 + .../RavenousMyconid4.ab2752.gmnotes | 1 + .../RavenousMyconid4.baa926.gmnotes | 1 + .../RavenousMyconid4.df93ca.gmnotes | 1 + .../RodofCarnamagos.66ec64.gmnotes | 5 +++++ .../RodofCarnamagos2.d8ef99.gmnotes | 5 +++++ .../SealoftheElders5.d2b649.gmnotes | 2 ++ .../SegmentofOnyx1.ff9f23.gmnotes | 1 + .../Stargazing1.968a26.gmnotes | 1 + .../SummonedHound1.ab4fb3.gmnotes | 1 + .../TheHungeringBlade1.2d94ed.gmnotes | 1 + src/arkhamdb/ArkhamDb.ttslua | 16 +++++++++------- 31 files changed, 52 insertions(+), 7 deletions(-) diff --git a/objects/AllPlayerCards.15bb07/BiancaDieKatz.897a94.gmnotes b/objects/AllPlayerCards.15bb07/BiancaDieKatz.897a94.gmnotes index 07410f89..a3f20337 100644 --- a/objects/AllPlayerCards.15bb07/BiancaDieKatz.897a94.gmnotes +++ b/objects/AllPlayerCards.15bb07/BiancaDieKatz.897a94.gmnotes @@ -9,6 +9,7 @@ "bonded": [ { "count": 1, + "maxCount": 1, "id": "10063" } ], diff --git a/objects/AllPlayerCards.15bb07/BrokenDiadem5.b6d35d.gmnotes b/objects/AllPlayerCards.15bb07/BrokenDiadem5.b6d35d.gmnotes index 172af1e1..46b30afc 100644 --- a/objects/AllPlayerCards.15bb07/BrokenDiadem5.b6d35d.gmnotes +++ b/objects/AllPlayerCards.15bb07/BrokenDiadem5.b6d35d.gmnotes @@ -8,6 +8,7 @@ "bonded": [ { "count": 1, + "maxCount": 1, "id": "10134" } ], diff --git a/objects/AllPlayerCards.15bb07/CrystallizerofDreams.6692de.gmnotes b/objects/AllPlayerCards.15bb07/CrystallizerofDreams.6692de.gmnotes index e05f6e73..bd1747fd 100644 --- a/objects/AllPlayerCards.15bb07/CrystallizerofDreams.6692de.gmnotes +++ b/objects/AllPlayerCards.15bb07/CrystallizerofDreams.6692de.gmnotes @@ -9,6 +9,7 @@ "bonded": [ { "count": 1, + "maxCount": 2, "id": "06025" } ], diff --git a/objects/AllPlayerCards.15bb07/DreamDiary.b81dcf.gmnotes b/objects/AllPlayerCards.15bb07/DreamDiary.b81dcf.gmnotes index 21378696..34fca57a 100644 --- a/objects/AllPlayerCards.15bb07/DreamDiary.b81dcf.gmnotes +++ b/objects/AllPlayerCards.15bb07/DreamDiary.b81dcf.gmnotes @@ -9,6 +9,7 @@ "bonded": [ { "count": 1, + "maxCount": 1, "id": "06113" } ], diff --git a/objects/AllPlayerCards.15bb07/DreamDiary3.5f9a10.gmnotes b/objects/AllPlayerCards.15bb07/DreamDiary3.5f9a10.gmnotes index 8e85f21a..4a0e1b16 100644 --- a/objects/AllPlayerCards.15bb07/DreamDiary3.5f9a10.gmnotes +++ b/objects/AllPlayerCards.15bb07/DreamDiary3.5f9a10.gmnotes @@ -9,6 +9,7 @@ "bonded": [ { "count": 1, + "maxCount": 1, "id": "06113" } ], diff --git a/objects/AllPlayerCards.15bb07/DreamDiary3.e5f9cb.gmnotes b/objects/AllPlayerCards.15bb07/DreamDiary3.e5f9cb.gmnotes index 021f5a4f..fb970d0c 100644 --- a/objects/AllPlayerCards.15bb07/DreamDiary3.e5f9cb.gmnotes +++ b/objects/AllPlayerCards.15bb07/DreamDiary3.e5f9cb.gmnotes @@ -9,6 +9,7 @@ "bonded": [ { "count": 1, + "maxCount": 1, "id": "06113" } ], diff --git a/objects/AllPlayerCards.15bb07/DreamDiary3.ea40f6.gmnotes b/objects/AllPlayerCards.15bb07/DreamDiary3.ea40f6.gmnotes index 4630e594..ca601cb3 100644 --- a/objects/AllPlayerCards.15bb07/DreamDiary3.ea40f6.gmnotes +++ b/objects/AllPlayerCards.15bb07/DreamDiary3.ea40f6.gmnotes @@ -9,6 +9,7 @@ "bonded": [ { "count": 1, + "maxCount": 1, "id": "06113" } ], diff --git a/objects/AllPlayerCards.15bb07/EmptyVessel4.c0d236.gmnotes b/objects/AllPlayerCards.15bb07/EmptyVessel4.c0d236.gmnotes index 90a66661..ff308a4a 100644 --- a/objects/AllPlayerCards.15bb07/EmptyVessel4.c0d236.gmnotes +++ b/objects/AllPlayerCards.15bb07/EmptyVessel4.c0d236.gmnotes @@ -9,6 +9,7 @@ "bonded": [ { "count": 1, + "maxCount": 1, "id": "06277" } ], diff --git a/objects/AllPlayerCards.15bb07/EyesofValusia4.e7bfbe.gmnotes b/objects/AllPlayerCards.15bb07/EyesofValusia4.e7bfbe.gmnotes index cf378f8c..61218b56 100644 --- a/objects/AllPlayerCards.15bb07/EyesofValusia4.e7bfbe.gmnotes +++ b/objects/AllPlayerCards.15bb07/EyesofValusia4.e7bfbe.gmnotes @@ -9,6 +9,7 @@ "bonded": [ { "count": 1, + "maxCount": 2, "id": "10036" } ], diff --git a/objects/AllPlayerCards.15bb07/FluxStabilizer.55990a.gmnotes b/objects/AllPlayerCards.15bb07/FluxStabilizer.55990a.gmnotes index e1b92f49..75dd4ff1 100644 --- a/objects/AllPlayerCards.15bb07/FluxStabilizer.55990a.gmnotes +++ b/objects/AllPlayerCards.15bb07/FluxStabilizer.55990a.gmnotes @@ -7,10 +7,12 @@ "bonded": [ { "count": 1, + "maxCount": 1, "id": "10006" }, { "count": 1, + "maxCount": 1, "id": "10007" } ], diff --git a/objects/AllPlayerCards.15bb07/GateBox.b8c891.gmnotes b/objects/AllPlayerCards.15bb07/GateBox.b8c891.gmnotes index fc1a1aa9..01cf00fb 100644 --- a/objects/AllPlayerCards.15bb07/GateBox.b8c891.gmnotes +++ b/objects/AllPlayerCards.15bb07/GateBox.b8c891.gmnotes @@ -8,6 +8,7 @@ "bonded": [ { "count": 1, + "maxCount": 1, "id": "06015a" } ], diff --git a/objects/AllPlayerCards.15bb07/HallowedMirror.312d38.gmnotes b/objects/AllPlayerCards.15bb07/HallowedMirror.312d38.gmnotes index fc3ec4d4..8d61f5b7 100644 --- a/objects/AllPlayerCards.15bb07/HallowedMirror.312d38.gmnotes +++ b/objects/AllPlayerCards.15bb07/HallowedMirror.312d38.gmnotes @@ -9,6 +9,7 @@ "bonded": [ { "count": 3, + "maxCount": 3, "id": "05314" } ], diff --git a/objects/AllPlayerCards.15bb07/HallowedMirror3.78858f.gmnotes b/objects/AllPlayerCards.15bb07/HallowedMirror3.78858f.gmnotes index 8970dc01..3f67a1c5 100644 --- a/objects/AllPlayerCards.15bb07/HallowedMirror3.78858f.gmnotes +++ b/objects/AllPlayerCards.15bb07/HallowedMirror3.78858f.gmnotes @@ -9,6 +9,7 @@ "bonded": [ { "count": 3, + "maxCount": 3, "id": "05314" } ], diff --git a/objects/AllPlayerCards.15bb07/HankSamson.3764cd.gmnotes b/objects/AllPlayerCards.15bb07/HankSamson.3764cd.gmnotes index 5c1b68da..86ae7de8 100644 --- a/objects/AllPlayerCards.15bb07/HankSamson.3764cd.gmnotes +++ b/objects/AllPlayerCards.15bb07/HankSamson.3764cd.gmnotes @@ -6,10 +6,12 @@ "bonded": [ { "count": 1, + "maxCount": 1, "id": "10015-b1" }, { "count": 1, + "maxCount": 1, "id": "10015-b2" } ], diff --git a/objects/AllPlayerCards.15bb07/MiracleWish5.d78d4a.gmnotes b/objects/AllPlayerCards.15bb07/MiracleWish5.d78d4a.gmnotes index c60af47d..d3dc1fb8 100644 --- a/objects/AllPlayerCards.15bb07/MiracleWish5.d78d4a.gmnotes +++ b/objects/AllPlayerCards.15bb07/MiracleWish5.d78d4a.gmnotes @@ -7,6 +7,7 @@ "bonded": [ { "count": 1, + "maxCount": 2, "id": "10039" } ], diff --git a/objects/AllPlayerCards.15bb07/MissDoyle1.e1aedf.gmnotes b/objects/AllPlayerCards.15bb07/MissDoyle1.e1aedf.gmnotes index c6e9cd85..026d1bd9 100644 --- a/objects/AllPlayerCards.15bb07/MissDoyle1.e1aedf.gmnotes +++ b/objects/AllPlayerCards.15bb07/MissDoyle1.e1aedf.gmnotes @@ -9,14 +9,17 @@ "bonded": [ { "count": 1, + "maxCount": 1, "id": "06031" }, { "count": 1, + "maxCount": 1, "id": "06032" }, { "count": 1, + "maxCount": 1, "id": "06033" } ], diff --git a/objects/AllPlayerCards.15bb07/NightmareBauble3.d6f6f1.gmnotes b/objects/AllPlayerCards.15bb07/NightmareBauble3.d6f6f1.gmnotes index 331e787f..b5fea3b2 100644 --- a/objects/AllPlayerCards.15bb07/NightmareBauble3.d6f6f1.gmnotes +++ b/objects/AllPlayerCards.15bb07/NightmareBauble3.d6f6f1.gmnotes @@ -9,6 +9,7 @@ "bonded": [ { "count": 3, + "maxCount": 3, "id": "06331" } ], diff --git a/objects/AllPlayerCards.15bb07/OccultLexicon.5d6728.gmnotes b/objects/AllPlayerCards.15bb07/OccultLexicon.5d6728.gmnotes index c37d3cc0..c8b28e1a 100644 --- a/objects/AllPlayerCards.15bb07/OccultLexicon.5d6728.gmnotes +++ b/objects/AllPlayerCards.15bb07/OccultLexicon.5d6728.gmnotes @@ -9,6 +9,7 @@ "bonded": [ { "count": 3, + "maxCount": 3, "id": "05317" } ], diff --git a/objects/AllPlayerCards.15bb07/OccultLexicon3.71d99c.gmnotes b/objects/AllPlayerCards.15bb07/OccultLexicon3.71d99c.gmnotes index 3f83c51d..658d18db 100644 --- a/objects/AllPlayerCards.15bb07/OccultLexicon3.71d99c.gmnotes +++ b/objects/AllPlayerCards.15bb07/OccultLexicon3.71d99c.gmnotes @@ -9,6 +9,7 @@ "bonded": [ { "count": 3, + "maxCount": 3, "id": "05317" } ], diff --git a/objects/AllPlayerCards.15bb07/RavenousMyconid.0aa967.gmnotes b/objects/AllPlayerCards.15bb07/RavenousMyconid.0aa967.gmnotes index 5b34d4cb..4b840991 100644 --- a/objects/AllPlayerCards.15bb07/RavenousMyconid.0aa967.gmnotes +++ b/objects/AllPlayerCards.15bb07/RavenousMyconid.0aa967.gmnotes @@ -8,6 +8,7 @@ "bonded": [ { "count": 1, + "maxCount": 1, "id": "10045" } ], diff --git a/objects/AllPlayerCards.15bb07/RavenousMyconid4.ab2752.gmnotes b/objects/AllPlayerCards.15bb07/RavenousMyconid4.ab2752.gmnotes index 1e620c22..b3c51dc6 100644 --- a/objects/AllPlayerCards.15bb07/RavenousMyconid4.ab2752.gmnotes +++ b/objects/AllPlayerCards.15bb07/RavenousMyconid4.ab2752.gmnotes @@ -9,6 +9,7 @@ "bonded": [ { "count": 1, + "maxCount": 1, "id": "10045" } ], diff --git a/objects/AllPlayerCards.15bb07/RavenousMyconid4.baa926.gmnotes b/objects/AllPlayerCards.15bb07/RavenousMyconid4.baa926.gmnotes index 3b8fe730..58b8e87c 100644 --- a/objects/AllPlayerCards.15bb07/RavenousMyconid4.baa926.gmnotes +++ b/objects/AllPlayerCards.15bb07/RavenousMyconid4.baa926.gmnotes @@ -9,6 +9,7 @@ "bonded": [ { "count": 1, + "maxCount": 1, "id": "10045" } ], diff --git a/objects/AllPlayerCards.15bb07/RavenousMyconid4.df93ca.gmnotes b/objects/AllPlayerCards.15bb07/RavenousMyconid4.df93ca.gmnotes index 1aadcba8..4bb6dded 100644 --- a/objects/AllPlayerCards.15bb07/RavenousMyconid4.df93ca.gmnotes +++ b/objects/AllPlayerCards.15bb07/RavenousMyconid4.df93ca.gmnotes @@ -9,6 +9,7 @@ "bonded": [ { "count": 1, + "maxCount": 1, "id": "10045" } ], diff --git a/objects/AllPlayerCards.15bb07/RodofCarnamagos.66ec64.gmnotes b/objects/AllPlayerCards.15bb07/RodofCarnamagos.66ec64.gmnotes index 865c9581..eb0442a9 100644 --- a/objects/AllPlayerCards.15bb07/RodofCarnamagos.66ec64.gmnotes +++ b/objects/AllPlayerCards.15bb07/RodofCarnamagos.66ec64.gmnotes @@ -9,22 +9,27 @@ "bonded": [ { "count": 1, + "maxCount": 1, "id": "10086" }, { "count": 1, + "maxCount": 1, "id": "10087" }, { "count": 1, + "maxCount": 1, "id": "10088" }, { "count": 1, + "maxCount": 1, "id": "10089" }, { "count": 1, + "maxCount": 1, "id": "10090" } ], diff --git a/objects/AllPlayerCards.15bb07/RodofCarnamagos2.d8ef99.gmnotes b/objects/AllPlayerCards.15bb07/RodofCarnamagos2.d8ef99.gmnotes index bd68aa74..56025aeb 100644 --- a/objects/AllPlayerCards.15bb07/RodofCarnamagos2.d8ef99.gmnotes +++ b/objects/AllPlayerCards.15bb07/RodofCarnamagos2.d8ef99.gmnotes @@ -9,22 +9,27 @@ "bonded": [ { "count": 1, + "maxCount": 1, "id": "10086" }, { "count": 1, + "maxCount": 1, "id": "10087" }, { "count": 1, + "maxCount": 1, "id": "10088" }, { "count": 1, + "maxCount": 1, "id": "10089" }, { "count": 1, + "maxCount": 1, "id": "10090" } ], diff --git a/objects/AllPlayerCards.15bb07/SealoftheElders5.d2b649.gmnotes b/objects/AllPlayerCards.15bb07/SealoftheElders5.d2b649.gmnotes index 445449b2..e0fd4059 100644 --- a/objects/AllPlayerCards.15bb07/SealoftheElders5.d2b649.gmnotes +++ b/objects/AllPlayerCards.15bb07/SealoftheElders5.d2b649.gmnotes @@ -8,10 +8,12 @@ "bonded": [ { "count": 1, + "maxCount": 1, "id": "10106" }, { "count": 1, + "maxCount": 1, "id": "10107" } ], diff --git a/objects/AllPlayerCards.15bb07/SegmentofOnyx1.ff9f23.gmnotes b/objects/AllPlayerCards.15bb07/SegmentofOnyx1.ff9f23.gmnotes index 8840efae..94331a55 100644 --- a/objects/AllPlayerCards.15bb07/SegmentofOnyx1.ff9f23.gmnotes +++ b/objects/AllPlayerCards.15bb07/SegmentofOnyx1.ff9f23.gmnotes @@ -8,6 +8,7 @@ "bonded": [ { "count": 1, + "maxCount": 1, "id": "06022" } ], diff --git a/objects/AllPlayerCards.15bb07/Stargazing1.968a26.gmnotes b/objects/AllPlayerCards.15bb07/Stargazing1.968a26.gmnotes index 7d1ee5b3..be65c26a 100644 --- a/objects/AllPlayerCards.15bb07/Stargazing1.968a26.gmnotes +++ b/objects/AllPlayerCards.15bb07/Stargazing1.968a26.gmnotes @@ -8,6 +8,7 @@ "bonded": [ { "count": 1, + "maxCount": 2, "id": "06028" } ], diff --git a/objects/AllPlayerCards.15bb07/SummonedHound1.ab4fb3.gmnotes b/objects/AllPlayerCards.15bb07/SummonedHound1.ab4fb3.gmnotes index 133c02c2..a854fec2 100644 --- a/objects/AllPlayerCards.15bb07/SummonedHound1.ab4fb3.gmnotes +++ b/objects/AllPlayerCards.15bb07/SummonedHound1.ab4fb3.gmnotes @@ -9,6 +9,7 @@ "bonded": [ { "count": 1, + "maxCount": 2, "id": "06283" } ], diff --git a/objects/AllPlayerCards.15bb07/TheHungeringBlade1.2d94ed.gmnotes b/objects/AllPlayerCards.15bb07/TheHungeringBlade1.2d94ed.gmnotes index 5f5d23b6..df8f9bb7 100644 --- a/objects/AllPlayerCards.15bb07/TheHungeringBlade1.2d94ed.gmnotes +++ b/objects/AllPlayerCards.15bb07/TheHungeringBlade1.2d94ed.gmnotes @@ -9,6 +9,7 @@ "bonded": [ { "count": 3, + "maxCount": 3, "id": "06019" } ], diff --git a/src/arkhamdb/ArkhamDb.ttslua b/src/arkhamdb/ArkhamDb.ttslua index 07d2185b..fe89293e 100644 --- a/src/arkhamdb/ArkhamDb.ttslua +++ b/src/arkhamdb/ArkhamDb.ttslua @@ -363,21 +363,23 @@ do local bondedList = { } for cardId, cardCount in pairs(slots) do local card = allCardsBagApi.getCardById(cardId) - if (card ~= nil and card.metadata.bonded ~= nil) then + if card ~= nil and card.metadata.bonded ~= nil then for _, bond in ipairs(card.metadata.bonded) do - -- add a bonded card for each copy of the parent card (except for Pendant of the Queen) - if bond.id == "06022" then - bondedCards[bond.id] = bond.count - else - bondedCards[bond.id] = bond.count * cardCount - end + -- 'unlimited' upper limit for cards without this data + local maxCount = bond.maxCount or 99 + + -- add a bonded card for each copy of the parent card (until the max value is reached) + bondedCards[bond.id] = math.min(bond.count * cardCount, maxCount) + -- We need to know which cards are bonded to determine their position, remember them bondedList[bond.id] = true + -- Also adding taboo versions of bonded cards to the list bondedList[bond.id .. "-t"] = true end end end + -- Add any bonded cards to the main slots list for bondedId, bondedCount in pairs(bondedCards) do slots[bondedId] = bondedCount From 11d4820093dea2ad17e331a73b9e9b538f7da0a6 Mon Sep 17 00:00:00 2001 From: Chr1Z93 Date: Sat, 27 Apr 2024 20:02:34 +0200 Subject: [PATCH 024/157] fixed hand slot issues --- objects/Playermat1White.8b081b.json | 16 ++++++------- objects/Playermat2Orange.bd0ff4.json | 16 ++++++------- objects/Playermat3Green.383d8b.json | 16 ++++++------- objects/Playermat4Red.0840d5.json | 16 ++++++------- src/playermat/Playmat.ttslua | 35 ++++++++++++++-------------- 5 files changed, 50 insertions(+), 49 deletions(-) diff --git a/objects/Playermat1White.8b081b.json b/objects/Playermat1White.8b081b.json index 8a23cb31..0e5b1d78 100644 --- a/objects/Playermat1White.8b081b.json +++ b/objects/Playermat1White.8b081b.json @@ -58,7 +58,7 @@ { "Position": { "x": 1.758, - "y": 0.101, + "y": 0.1, "z": 0.04 }, "Tags": [ @@ -78,7 +78,7 @@ { "Position": { "x": 0.98, - "y": 0.099, + "y": 0.1, "z": 0.035 }, "Tags": [ @@ -108,7 +108,7 @@ { "Position": { "x": -0.177, - "y": 0.101, + "y": 0.1, "z": 0.032 }, "Tags": [ @@ -118,7 +118,7 @@ { "Position": { "x": -0.616, - "y": 0.102, + "y": 0.1, "z": 0.024 }, "Tags": [ @@ -138,7 +138,7 @@ { "Position": { "x": 1.371, - "y": 0.099, + "y": 0.1, "z": 0.558 }, "Tags": [ @@ -148,7 +148,7 @@ { "Position": { "x": 0.977, - "y": 0.099, + "y": 0.1, "z": 0.556 }, "Tags": [ @@ -178,7 +178,7 @@ { "Position": { "x": -0.174, - "y": 0.099, + "y": 0.1, "z": 0.551 }, "Tags": [ @@ -329,7 +329,7 @@ }, "ImageScalar": 1, "ImageSecondaryURL": "", - "ImageURL": "http://cloud-3.steamusercontent.com/ugc/2037357630681963618/E7271737B19CE0BFAAA382BEEEF497FE3E06ECC1/", + "ImageURL": "http://cloud-3.steamusercontent.com/ugc/2462982115659543571/5D778EA4BC682DAE97E8F59A991BCF8CB3979B04/", "WidthScale": 0 }, "Description": "", diff --git a/objects/Playermat2Orange.bd0ff4.json b/objects/Playermat2Orange.bd0ff4.json index e0acf721..7e61a822 100644 --- a/objects/Playermat2Orange.bd0ff4.json +++ b/objects/Playermat2Orange.bd0ff4.json @@ -58,7 +58,7 @@ { "Position": { "x": 1.758, - "y": 0.101, + "y": 0.1, "z": 0.04 }, "Tags": [ @@ -78,7 +78,7 @@ { "Position": { "x": 0.98, - "y": 0.099, + "y": 0.1, "z": 0.035 }, "Tags": [ @@ -108,7 +108,7 @@ { "Position": { "x": -0.177, - "y": 0.101, + "y": 0.1, "z": 0.032 }, "Tags": [ @@ -118,7 +118,7 @@ { "Position": { "x": -0.616, - "y": 0.102, + "y": 0.1, "z": 0.024 }, "Tags": [ @@ -138,7 +138,7 @@ { "Position": { "x": 1.371, - "y": 0.099, + "y": 0.1, "z": 0.558 }, "Tags": [ @@ -148,7 +148,7 @@ { "Position": { "x": 0.977, - "y": 0.099, + "y": 0.1, "z": 0.556 }, "Tags": [ @@ -178,7 +178,7 @@ { "Position": { "x": -0.174, - "y": 0.099, + "y": 0.1, "z": 0.551 }, "Tags": [ @@ -329,7 +329,7 @@ }, "ImageScalar": 1, "ImageSecondaryURL": "", - "ImageURL": "http://cloud-3.steamusercontent.com/ugc/2037357630681963618/E7271737B19CE0BFAAA382BEEEF497FE3E06ECC1/", + "ImageURL": "http://cloud-3.steamusercontent.com/ugc/2462982115659543571/5D778EA4BC682DAE97E8F59A991BCF8CB3979B04/", "WidthScale": 0 }, "Description": "", diff --git a/objects/Playermat3Green.383d8b.json b/objects/Playermat3Green.383d8b.json index c9a4af2d..57698e72 100644 --- a/objects/Playermat3Green.383d8b.json +++ b/objects/Playermat3Green.383d8b.json @@ -58,7 +58,7 @@ { "Position": { "x": 1.758, - "y": 0.101, + "y": 0.1, "z": 0.04 }, "Tags": [ @@ -78,7 +78,7 @@ { "Position": { "x": 0.98, - "y": 0.099, + "y": 0.1, "z": 0.035 }, "Tags": [ @@ -108,7 +108,7 @@ { "Position": { "x": -0.177, - "y": 0.101, + "y": 0.1, "z": 0.032 }, "Tags": [ @@ -118,7 +118,7 @@ { "Position": { "x": -0.616, - "y": 0.102, + "y": 0.1, "z": 0.024 }, "Tags": [ @@ -138,7 +138,7 @@ { "Position": { "x": 1.371, - "y": 0.099, + "y": 0.1, "z": 0.558 }, "Tags": [ @@ -148,7 +148,7 @@ { "Position": { "x": 0.977, - "y": 0.099, + "y": 0.1, "z": 0.556 }, "Tags": [ @@ -178,7 +178,7 @@ { "Position": { "x": -0.174, - "y": 0.099, + "y": 0.1, "z": 0.551 }, "Tags": [ @@ -329,7 +329,7 @@ }, "ImageScalar": 1, "ImageSecondaryURL": "", - "ImageURL": "http://cloud-3.steamusercontent.com/ugc/2037357630681963618/E7271737B19CE0BFAAA382BEEEF497FE3E06ECC1/", + "ImageURL": "http://cloud-3.steamusercontent.com/ugc/2462982115659543571/5D778EA4BC682DAE97E8F59A991BCF8CB3979B04/", "WidthScale": 0 }, "Description": "", diff --git a/objects/Playermat4Red.0840d5.json b/objects/Playermat4Red.0840d5.json index 6e3140e0..e3df326c 100644 --- a/objects/Playermat4Red.0840d5.json +++ b/objects/Playermat4Red.0840d5.json @@ -58,7 +58,7 @@ { "Position": { "x": 1.758, - "y": 0.101, + "y": 0.1, "z": 0.04 }, "Tags": [ @@ -78,7 +78,7 @@ { "Position": { "x": 0.98, - "y": 0.099, + "y": 0.1, "z": 0.035 }, "Tags": [ @@ -108,7 +108,7 @@ { "Position": { "x": -0.177, - "y": 0.101, + "y": 0.1, "z": 0.032 }, "Tags": [ @@ -118,7 +118,7 @@ { "Position": { "x": -0.616, - "y": 0.102, + "y": 0.1, "z": 0.024 }, "Tags": [ @@ -138,7 +138,7 @@ { "Position": { "x": 1.371, - "y": 0.099, + "y": 0.1, "z": 0.558 }, "Tags": [ @@ -148,7 +148,7 @@ { "Position": { "x": 0.977, - "y": 0.099, + "y": 0.1, "z": 0.556 }, "Tags": [ @@ -178,7 +178,7 @@ { "Position": { "x": -0.174, - "y": 0.099, + "y": 0.1, "z": 0.551 }, "Tags": [ @@ -329,7 +329,7 @@ }, "ImageScalar": 1, "ImageSecondaryURL": "", - "ImageURL": "http://cloud-3.steamusercontent.com/ugc/2037357630681963618/E7271737B19CE0BFAAA382BEEEF497FE3E06ECC1/", + "ImageURL": "http://cloud-3.steamusercontent.com/ugc/2462982115659543571/5D778EA4BC682DAE97E8F59A991BCF8CB3979B04/", "WidthScale": 0 }, "Description": "", diff --git a/src/playermat/Playmat.ttslua b/src/playermat/Playmat.ttslua index 6741857c..dceeed65 100644 --- a/src/playermat/Playmat.ttslua +++ b/src/playermat/Playmat.ttslua @@ -57,7 +57,7 @@ local slotNameToChar = { } -- slot symbol for the respective slot (from top left to bottom right) -local slotData +local slotData = {} local defaultSlotData = { -- 1st row "any", "any", "any", "Tarot", "Hand (left)", "Hand (right)", "Ally", @@ -390,7 +390,7 @@ function doDrawOne(_, clickedByColor) end -- draws the specified amount of cards (and shuffles the discard if necessary) ----@param numCards num Number of cards to draw +---@param numCards number Number of cards to draw function drawCardsWithReshuffle(numCards) local deckAreaObjects = getDeckAreaObjects() @@ -556,9 +556,8 @@ function redrawSlotXML() attributes = { id = "slotPanel" .. snapId, scale = "0.1 0.1 1", - width = "150", - height = "150", - rotation = getSlotRotation(slotName), + width = "175", + height = "175", position = x .. " " .. y .. " -11" }, children = { @@ -566,6 +565,7 @@ function redrawSlotXML() tag = "Text", attributes = { id = "slot" .. snapId, + rotation = getSlotRotation(slotName), fontSize = "145", font = "font_arkhamicons", color = "#414141CB", @@ -596,35 +596,36 @@ function toggleSlotEditing(_, clickedByColor, isRightClick) if currentlyEditingSlots then editButtonLabel("Edit Slots", "Stop editing") broadcastToColor("Click on a slot symbol (or an empty slot) to edit it.", messageColor, "Orange") + for i = 1, #slotData do + self.UI.setAttribute("slotPanel" .. i, "onClick", "slotClickfunction") + end else editButtonLabel("Stop editing", "Edit Slots") - end - - -- set click function (or maybe disable it) - local clickFunc = currentlyEditingSlots and "slotClickfunction" or "" - for i = 1, #slotData do - self.UI.setAttribute("slot" .. i, "onClick", clickFunc) + redrawSlotXML() end end -- click function for slot symbols during the "slot editing mode" function slotClickfunction(player, clickType, id) - local index = id:gsub("slot", "") + local slotIndex = id:gsub("slotPanel", "") + slotIndex = tonumber(slotIndex) + + -- make a list of the table keys as options for the dialog box local slotNames = {} for slotName, _ in pairs(slotNameToChar) do table.insert(slotNames, slotName) end -- prompt player to choose symbol - player.showOptionsDialog("Choose Slot Symbol", slotNames, slotData[index], - function(chosenSlot, chosenIndex) - slotData[chosenIndex] = chosenSlot + player.showOptionsDialog("Choose Slot Symbol", slotNames, slotData[slotIndex], + function(chosenSlotName) + slotData[slotIndex] = chosenSlotName -- update slot symbol - self.UI.setAttribute(id, "text", slotNameToChar[chosenSlot]) + self.UI.setAttribute("slot" .. slotIndex, "text", slotNameToChar[chosenSlotName]) -- update slot rotation - self.UI.setAttribute("slotPanel" .. chosenIndex, "rotation", getSlotRotation(chosenSlot)) + self.UI.setAttribute("slot" .. slotIndex, "rotation", getSlotRotation(chosenSlotName)) end ) end From d5ef1d93cc059ebc201c47e572370ad1e1baa11a Mon Sep 17 00:00:00 2001 From: Chr1Z93 Date: Sat, 27 Apr 2024 20:04:42 +0200 Subject: [PATCH 025/157] update scriptstate --- objects/Playermat1White.8b081b.luascriptstate | 2 +- objects/Playermat2Orange.bd0ff4.luascriptstate | 2 +- objects/Playermat3Green.383d8b.luascriptstate | 2 +- objects/Playermat4Red.0840d5.json | 2 +- objects/Playermat4Red.0840d5.luascriptstate | 1 + src/playermat/Playmat.ttslua | 18 ++++-------------- 6 files changed, 9 insertions(+), 18 deletions(-) create mode 100644 objects/Playermat4Red.0840d5.luascriptstate diff --git a/objects/Playermat1White.8b081b.luascriptstate b/objects/Playermat1White.8b081b.luascriptstate index e25057b1..b2667c4d 100644 --- a/objects/Playermat1White.8b081b.luascriptstate +++ b/objects/Playermat1White.8b081b.luascriptstate @@ -1 +1 @@ -{"activeInvestigatorId":"00000","isDrawButtonVisible":false,"playerColor":"White"} +{"activeInvestigatorId":"00000","isDrawButtonVisible":false,"playerColor":"White","slotData":["any","any","any","Tarot","Hand (left)","Hand (right)","Ally","any","any","any","Accessory","Arcane","Arcane","Body"]} diff --git a/objects/Playermat2Orange.bd0ff4.luascriptstate b/objects/Playermat2Orange.bd0ff4.luascriptstate index b4311e09..06136886 100644 --- a/objects/Playermat2Orange.bd0ff4.luascriptstate +++ b/objects/Playermat2Orange.bd0ff4.luascriptstate @@ -1 +1 @@ -{"activeInvestigatorId":"00000","isDrawButtonVisible":false,"playerColor":"Orange"} +{"activeInvestigatorId":"00000","isDrawButtonVisible":false,"playerColor":"Orange","slotData":["any","any","any","Tarot","Hand (left)","Hand (right)","Ally","any","any","any","Accessory","Arcane","Arcane","Body"]} diff --git a/objects/Playermat3Green.383d8b.luascriptstate b/objects/Playermat3Green.383d8b.luascriptstate index f71b33c5..cda2f6f7 100644 --- a/objects/Playermat3Green.383d8b.luascriptstate +++ b/objects/Playermat3Green.383d8b.luascriptstate @@ -1 +1 @@ -{"activeInvestigatorId":"00000","isDrawButtonVisible":false,"playerColor":"Green"} +{"activeInvestigatorId":"00000","isDrawButtonVisible":false,"playerColor":"Green","slotData":["any","any","any","Tarot","Hand (left)","Hand (right)","Ally","any","any","any","Accessory","Arcane","Arcane","Body"]} diff --git a/objects/Playermat4Red.0840d5.json b/objects/Playermat4Red.0840d5.json index e3df326c..edb3e19d 100644 --- a/objects/Playermat4Red.0840d5.json +++ b/objects/Playermat4Red.0840d5.json @@ -344,7 +344,7 @@ "LayoutGroupSortIndex": 0, "Locked": true, "LuaScript": "require(\"playermat/Playmat\")", - "LuaScriptState": "{\"activeInvestigatorId\":\"00000\",\"isDrawButtonVisible\":false,\"playerColor\":\"Red\"}", + "LuaScriptState_path": "Playermat4Red.0840d5.luascriptstate", "MeasureMovement": false, "Memo": "Red", "Name": "Custom_Tile", diff --git a/objects/Playermat4Red.0840d5.luascriptstate b/objects/Playermat4Red.0840d5.luascriptstate new file mode 100644 index 00000000..52dbc6b1 --- /dev/null +++ b/objects/Playermat4Red.0840d5.luascriptstate @@ -0,0 +1 @@ +{"activeInvestigatorId":"00000","isDrawButtonVisible":false,"playerColor":"Red","slotData":["any","any","any","Tarot","Hand (left)","Hand (right)","Ally","any","any","any","Accessory","Arcane","Arcane","Body"]} diff --git a/src/playermat/Playmat.ttslua b/src/playermat/Playmat.ttslua index dceeed65..6ee80885 100644 --- a/src/playermat/Playmat.ttslua +++ b/src/playermat/Playmat.ttslua @@ -88,21 +88,11 @@ end function onLoad(savedData) if savedData and savedData ~= "" then - local loadedData = JSON.decode(savedData) - playerColor = loadedData.playerColor + local loadedData = JSON.decode(savedData) + playerColor = loadedData.playerColor activeInvestigatorId = loadedData.activeInvestigatorId - isDrawButtonVisible = loadedData.isDrawButtonVisible - - -- To-Do: remove this once the save state is properly populated - if loadedData.slotData then - slotData = loadedData.slotData - else - -- make a deep copy of the default table - slotData = {} - for _, slotName in ipairs(defaultSlotData) do - table.insert(slotData, slotName) - end - end + isDrawButtonVisible = loadedData.isDrawButtonVisible + slotData = loadedData.slotData end self.interactable = false From 452fbeefb362cffd6a47370295c94d090a305b04 Mon Sep 17 00:00:00 2001 From: Chr1Z93 Date: Sun, 28 Apr 2024 00:54:19 +0200 Subject: [PATCH 026/157] some cleanup --- src/playermat/Playmat.ttslua | 125 ++++++++++++++++++----------------- 1 file changed, 65 insertions(+), 60 deletions(-) diff --git a/src/playermat/Playmat.ttslua b/src/playermat/Playmat.ttslua index 6ee80885..fe387f1e 100644 --- a/src/playermat/Playmat.ttslua +++ b/src/playermat/Playmat.ttslua @@ -12,7 +12,8 @@ local collisionEnabled = false local currentlyEditingSlots = false -- x-Values for discard buttons -local DISCARD_BUTTON_OFFSETS = { -1.365, -0.91, -0.455, 0, 0.455, 0.91 } +local DISCARD_BUTTON_X_START = -1.365 +local DISCARD_BUTTON_X_OFFSET = 0.455 local SEARCH_AROUND_SELF_X_BUFFER = 8 @@ -43,6 +44,20 @@ local DISCARD_PILE_POSITION = { x = -1.82, y = 0.1, z = 0.61 } -- global position of encounter discard pile local ENCOUNTER_DISCARD_POSITION = { x = -3.85, y = 1.5, z = 10.38 } +-- used for the buttons on the right side of the playmat +-- starts off with the data for the "Upkeep" button and will then be changed +local buttonParameters = { + label = "Upkeep", + click_function = "doUpkeep", + tooltip = "Right-click to change color", + function_owner = self, + position = { x = 1.82, y = 0.1, z = -0.45 }, + scale = { 0.12, 0.12, 0.12 }, + width = 1000, + height = 280, + font_size = 180 +} + -- translation table for slot names to characters for special font local slotNameToChar = { ["any"] = "", @@ -102,7 +117,7 @@ function onLoad(savedData) -- discard button creation for i = 1, 6 do - makeDiscardButton(DISCARD_BUTTON_OFFSETS[i], i) + makeDiscardButton(i) end self.createButton({ @@ -123,32 +138,18 @@ function onLoad(savedData) height = 135 }) - self.createButton({ - label = "Upkeep", - click_function = "doUpkeep", - tooltip = "Right-click to change color", - function_owner = self, - position = { 1.84, 0.1, -0.44 }, - scale = { 0.12, 0.12, 0.12 }, - width = 1000, - height = 280, - font_size = 180 - }) + -- Upkeep button: can use the default parameters for this + self.createButton(buttonParameters) - self.createButton({ - label = "Edit Slots", - click_function = "toggleSlotEditing", - tooltip = "Right-click to reset slot symbols", - function_owner = self, - position = { 1.84, 0.1, 0.94 }, - scale = { 0.12, 0.12, 0.12 }, - width = 1000, - height = 280, - font_size = 180 - }) + -- Slot editing button: modified default data + buttonParameters.label = "Edit Slots" + buttonParameters.click_function = "toggleSlotEditing" + buttonParameters.tooltip = "Right-click to reset slot symbols" + buttonParameters.position.z = 0.92 + self.createButton(buttonParameters) showDrawButton(isDrawButtonVisible) - redrawSlotXML() + redrawSlotSymbols() math.randomseed(os.time()) Wait.time(function() collisionEnabled = true end, 0.1) end @@ -231,9 +232,11 @@ function discardListOfObjects(objList) else deckLib.placeOrMergeIntoDeck(obj, ENCOUNTER_DISCARD_POSITION, { x = 0, y = -90, z = 0 }) end + -- put chaos tokens back into bag (e.g. Unrelenting) elseif tokenChecker.isChaosToken(obj) then chaosBagApi.returnChaosTokenToBag(obj) + -- don't touch locked objects (like the table etc.) or specific objects (like key tokens) elseif not obj.getLock() and not obj.hasTag("DontDiscard") then ownedObjects.Trash.putObject(obj) @@ -241,11 +244,13 @@ function discardListOfObjects(objList) end end --- build a discard button to discard from searchPosition (number must be unique) -function makeDiscardButton(xValue, number) +-- build a discard button to discard from searchPosition +---@param id number Index of the discard button (from left to right, must be unique) +function makeDiscardButton(id) + local xValue = DISCARD_BUTTON_X_START + (id - 1) * DISCARD_BUTTON_X_OFFSET local position = { xValue, 0.1, -0.94 } local searchPosition = { -position[1], position[2], position[3] + 0.32 } - local handlerName = 'handler' .. number + local handlerName = 'handler' .. id self.setVar(handlerName, function() local cardSizeSearch = { 2, 1, 3.2 } local globalSearchPosition = self.positionToWorld(searchPosition) @@ -457,6 +462,8 @@ function getDeckAreaObjects() return deckAreaObjects end +-- draws the specified number of cards (reshuffling of discard pile is handled separately) +---@param numCards number Number of cards to draw function drawCards(numCards) local deckAreaObjects = getDeckAreaObjects() if deckAreaObjects.draw then @@ -524,11 +531,11 @@ function doDiscardOne() end --------------------------------------------------------- --- slot modifying +-- slot symbol displaying --------------------------------------------------------- -- this will redraw the XML for the slot symbols based on the slotData table -function redrawSlotXML() +function redrawSlotSymbols() local xml = {} local snapId = 0 @@ -538,9 +545,11 @@ function redrawSlotXML() snapId = snapId + 1 local slotName = slotData[snapId] - -- increased coordinates to account for scale (0.1) + -- conversion from regular coordinates to XML local x = snap.position.x * 100 local y = snap.position.z * 100 + + -- XML for a single slot (panel with text in the special font) local slotXML = { tag = "Panel", attributes = { @@ -586,17 +595,15 @@ function toggleSlotEditing(_, clickedByColor, isRightClick) if currentlyEditingSlots then editButtonLabel("Edit Slots", "Stop editing") broadcastToColor("Click on a slot symbol (or an empty slot) to edit it.", messageColor, "Orange") - for i = 1, #slotData do - self.UI.setAttribute("slotPanel" .. i, "onClick", "slotClickfunction") - end + addClickFunctionToSlots() else editButtonLabel("Stop editing", "Edit Slots") - redrawSlotXML() + redrawSlotSymbols() end end -- click function for slot symbols during the "slot editing mode" -function slotClickfunction(player, clickType, id) +function slotClickfunction(player, _, id) local slotIndex = id:gsub("slotPanel", "") slotIndex = tonumber(slotIndex) @@ -635,7 +642,20 @@ function resetSlotSymbols() for _, slotName in ipairs(defaultSlotData) do table.insert(slotData, slotName) end - redrawSlotXML() + + redrawSlotSymbols() + + -- need to re-add the click functions if currently in edit mode + if currentlyEditingSlots then + addClickFunctionToSlots() + end +end + +-- enables the click functions for editing +function addClickFunctionToSlots() + for i = 1, #slotData do + self.UI.setAttribute("slotPanel" .. i, "onClick", "slotClickfunction") + end end --------------------------------------------------------- @@ -644,23 +664,12 @@ end -- changes the player color function changeColor(clickedByColor) - local colorList = { - "White", - "Brown", - "Red", - "Orange", - "Yellow", - "Green", - "Teal", - "Blue", - "Purple", - "Pink" - } + local colorList = Player.getColors() -- remove existing colors from the list of choices for _, existingColor in ipairs(Player.getAvailableColors()) do for i, newColor in ipairs(colorList) do - if existingColor == newColor then + if existingColor == newColor or newColor == "Black" or newColor == "Grey" then table.remove(colorList, i) end end @@ -959,16 +968,12 @@ function showDrawButton(visible) isDrawButtonVisible = visible if isDrawButtonVisible then - self.createButton({ - label = "Draw 1", - click_function = "doDrawOne", - function_owner = self, - position = { 1.84, 0.1, -0.36 }, - scale = { 0.12, 0.12, 0.12 }, - width = 1000, - height = 280, - font_size = 180 - }) + -- Draw 1 button: modified default data + buttonParameters.label = "Draw 1" + buttonParameters.click_function = "doDrawOne" + buttonParameters.tooltip = "" + buttonParameters.position.z = -0.35 + self.createButton(buttonParameters) else local buttons = self.getButtons() for i = 1, #buttons do From b857119f1a835fd838dca0e961a93716fddf4b3e Mon Sep 17 00:00:00 2001 From: Chr1Z93 Date: Sun, 28 Apr 2024 11:48:20 +0200 Subject: [PATCH 027/157] version bump to 3.8.0 --- config.json | 2 +- src/core/Global.ttslua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config.json b/config.json index 1502b6a4..cee2ca52 100644 --- a/config.json +++ b/config.json @@ -236,7 +236,7 @@ 0, 0 ], - "SaveName": "Arkham SCE - 3.7.0", + "SaveName": "Arkham SCE - 3.8.0", "Sky": "Sky_Museum", "SkyURL": "https://i.imgur.com/GkQqaOF.jpg", "SnapPoints_path": "SnapPoints.json", diff --git a/src/core/Global.ttslua b/src/core/Global.ttslua index 226d9779..09a84dd4 100644 --- a/src/core/Global.ttslua +++ b/src/core/Global.ttslua @@ -40,7 +40,7 @@ local bagSearchers = {} local hideTitleSplashWaitFunctionId = nil -- online functionality related variables -local MOD_VERSION = "3.7.0" +local MOD_VERSION = "3.8.0" local SOURCE_REPO = 'https://raw.githubusercontent.com/chr1z93/loadable-objects/main' local library, requestObj, modMeta local acknowledgedUpgradeVersions = {} From 8e3c0563b5521cf8265b6cab8a76d870e20dbffb Mon Sep 17 00:00:00 2001 From: Chr1Z93 Date: Mon, 29 Apr 2024 09:45:44 +0200 Subject: [PATCH 028/157] bugfix for action tokens --- src/accessories/CleanUpHelper.ttslua | 29 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/src/accessories/CleanUpHelper.ttslua b/src/accessories/CleanUpHelper.ttslua index 9c4d2892..50683eb4 100644 --- a/src/accessories/CleanUpHelper.ttslua +++ b/src/accessories/CleanUpHelper.ttslua @@ -3,14 +3,14 @@ -- puts everything on playmats and hands into respective trashcans -- use the IGNORE_TAG to exclude objects from tidying (default: "CleanUpHelper_Ignore") -local blessCurseManagerApi = require("chaosbag/BlessCurseManagerApi") -local chaosBagApi = require("chaosbag/ChaosBagApi") -local guidReferenceApi = require("core/GUIDReferenceApi") -local playAreaApi = require("core/PlayAreaApi") -local playmatApi = require("playermat/PlaymatApi") -local searchLib = require("util/SearchLib") -local soundCubeApi = require("core/SoundCubeApi") -local tokenSpawnTrackerApi = require("core/token/TokenSpawnTrackerApi") +local blessCurseManagerApi = require("chaosbag/BlessCurseManagerApi") +local chaosBagApi = require("chaosbag/ChaosBagApi") +local guidReferenceApi = require("core/GUIDReferenceApi") +local playAreaApi = require("core/PlayAreaApi") +local playmatApi = require("playermat/PlaymatApi") +local searchLib = require("util/SearchLib") +local soundCubeApi = require("core/SoundCubeApi") +local tokenSpawnTrackerApi = require("core/token/TokenSpawnTrackerApi") -- objects with this tag will be ignored local IGNORE_TAG = "CleanUpHelper_ignore" @@ -133,8 +133,8 @@ end --------------------------------------------------------- function updateCounters() - playmatApi.updateCounter("All", "ResourceCounter" , 5) - playmatApi.updateCounter("All", "ClickableClueCounter" , 0) + playmatApi.updateCounter("All", "ResourceCounter", 5) + playmatApi.updateCounter("All", "ClickableClueCounter", 0) playmatApi.resetSkillTracker("All") for i = 1, 4 do @@ -196,7 +196,7 @@ function loadTrauma() if i < 5 then RESET_VALUES.Damage[i] = trauma[i] else - RESET_VALUES.Horror[i-4] = trauma[i] + RESET_VALUES.Horror[i - 4] = trauma[i] end end loadingFailedBefore = false @@ -319,7 +319,6 @@ function tidyPlayerMatCoroutine() and obj.hasTag("chaosBag") == false and (obj.locked == false or obj.hasTag("Investigator")) and obj.interactable == true then - coroutine.yield(0) trash.putObject(obj) -- action token handling @@ -328,18 +327,18 @@ function tidyPlayerMatCoroutine() if obj.getScale().x < 0.4 then local pos = playmatApi.transformLocalPosition(Vector(-0.865, 0.1, -0.28), COLORS[i]) obj.setPosition(pos) - coroutine.yield(0) end -- flip action tokens back to ready if obj.is_face_down then - obj.flip() - coroutine.yield(0) + local rot = playmatApi.returnRotation(COLORS[i]) + obj.setRotation(rot) end -- reset action token state local stateId = obj.getStateId() if stateId ~= -1 and stateId ~= 6 then + coroutine.yield(0) obj.setState(6) end end From e1428547b5d4e039f1bf0b3a90cea0575c06894e Mon Sep 17 00:00:00 2001 From: Chr1Z93 Date: Mon, 29 Apr 2024 11:25:41 +0200 Subject: [PATCH 029/157] Updated campaign exporter and option panel --- .../CampaignImporterExporter.ttslua | 183 +++++++++--------- src/core/Global.ttslua | 62 ++---- 2 files changed, 112 insertions(+), 133 deletions(-) diff --git a/src/accessories/CampaignImporterExporter.ttslua b/src/accessories/CampaignImporterExporter.ttslua index f610626c..380974a6 100644 --- a/src/accessories/CampaignImporterExporter.ttslua +++ b/src/accessories/CampaignImporterExporter.ttslua @@ -56,13 +56,13 @@ function onLoad() }) end -function onObjectLeaveContainer(container, _) +function onObjectLeaveContainer(container) if container.hasTag("ImporterToken") then broadcastToAll("Removing objects from the Save Coin bag will break functionality. Please return the removed objects.", "Yellow") end end -function onObjectEnterContainer(container, _) +function onObjectEnterContainer(container) if container.hasTag("ImporterToken") then broadcastToAll("Adding objects to the Save Coin bag will break functionality. Please remove the objects.", "Yellow") end @@ -78,7 +78,7 @@ function onCollisionEnter(info) end end --- Identifies import token, determines campaign box and downloads it (if needed) +-- identifies import token, determines campaign box and downloads it (if needed) function importFromToken(coin) broadcastToAll("Campaign Import Initiated") local importData = JSON.decode(coin.getGMNotes()) @@ -115,7 +115,7 @@ function importFromToken(coin) ) end --- After box has been downloaded, places content on table +-- after box has been downloaded, places content on table function placeCampaignFromToken(importData, coin) getObjectFromGUID(importData["box"]).call("buttonClick_place") Wait.condition( @@ -126,31 +126,28 @@ function placeCampaignFromToken(importData, coin) ) end --- After content is placed on table, conducts all the other import operations +-- after content is placed on table, conducts all the other import operations function restoreCampaignData(importData, coin) - -- destroy existing campaign log - findUniqueObjectWithTag("CampaignLog").destruct() + -- go over internal items and respawn them (only storing campaign log and additional player cards) + for _, objData in ipairs(coin.getData().ContainedObjects) do + objData.Locked = true + local spawnData = { data = objData } - -- destroy existing "additional player cards" bag - if importData["additionalIndex"] then - guidReferenceApi.getObjectByOwnerAndType("Mythos", "AdditionalPlayerCardsBag").destruct() - end - - if coin.type == "Bag" then - -- go over internal items and spawn them at the original position - for _, objData in ipairs(coin.getData().ContainedObjects) do - objData["Locked"] = true - spawnObjectData({data = objData}) + -- maybe restore position of item and destroy duplicate + if objData.Nickname == "Additional Player Cards" then + local additionalIndex = guidReferenceApi.getObjectByOwnerAndType("Mythos", "AdditionalPlayerCardsBag") + spawnData.position = additionalIndex.getPosition() + additionalIndex.destruct() + else + local campaignLog = findUniqueObjectWithTag("CampaignLog") + if campaignLog then + spawnData.position = campaignLog.getPosition() + campaignLog.destruct() + end end - else - -- support for older save coins that stored the data serialized - if importData["additionalIndex"] then - spawnObjectJSON({json = importData["additionalIndex"]}) - end - spawnObjectData({data = importData["log"]}) - end - coin.destruct() + spawnObjectData(spawnData) + end chaosBagApi.setChaosBagState(importData["bag"]) @@ -164,21 +161,21 @@ function restoreCampaignData(importData, coin) deckImporterApi.setUiState(importData["decks"]) end - playAreaApi.setInvestigatorCount(importData["clueCount"]) - - -- set campaign guide page - local guide = findUniqueObjectWithTag("CampaignGuide") - if guide then - Wait.condition( - -- Called after the condition function returns true - function() printToAll("Campaign Guide import successful!") end, - -- Condition function that is called continuously until it returns true or timeout is reached - function() return guide.Book.setPage(importData["guide"]) end, - -- Amount of time in seconds until the Wait times out - 2, - -- Called if the Wait times out - function() printToAll("Campaign Guide import failed!") end - ) + -- maybe set campaign guide page + if importData["guide"] then + local campaignGuide = findUniqueObjectWithTag("CampaignGuide") + if campaignGuide then + Wait.condition( + -- Called after the condition function returns true + function() printToAll("Campaign Guide import successful!") end, + -- Condition function that is called continuously until it returns true or timeout is reached + function() return campaignGuide.Book.setPage(importData["guide"]) end, + -- Amount of time in seconds until the Wait times out + 2, + -- Called if the Wait times out + function() printToAll("Campaign Guide import failed!") end + ) + end end Wait.time(function() optionPanelApi.loadSettings(importData["options"]) end, 0.5) @@ -189,14 +186,21 @@ function restoreCampaignData(importData, coin) tourStarter.destruct() end - -- restore PlayArea image + -- restore PlayArea image and player count playAreaApi.updateSurface(importData["playarea"]) + playAreaApi.setInvestigatorCount(importData["clueCount"]) + coin.destruct() broadcastToAll("Campaign successfully imported!", "Green") end --- Creates a campaign token with save data encoded into GM Notes based on the current state of the table +-- creates a campaign token with save data encoded into GM Notes based on the current state of the table function createCampaignToken(_, playerColor, _) + local campaignData = {} + + -- need to reset the contained objects to support multiple exports + campaignTokenData.ContainedObjects = {} + -- find active campaign local campaignBox for _, obj in ipairs(getObjectsWithTag("CampaignBox")) do @@ -204,7 +208,7 @@ function createCampaignToken(_, playerColor, _) if not campaignBox then campaignBox = obj else - broadcastToAll("Multiple empty campaign box detected; delete all but one.", "Red") + broadcastToAll("Multiple empty campaign boxes detected; delete all but one.", "Red") return end end @@ -215,60 +219,55 @@ function createCampaignToken(_, playerColor, _) return end - local campaignLog = findUniqueObjectWithTag("CampaignLog") - if campaignLog == nil then - broadcastToAll("Campaign log not found!", "Red") - return - end - - local additionalIndex = guidReferenceApi.getObjectByOwnerAndType("Mythos", "AdditionalPlayerCardsBag") - local traumaValues = { } - local trauma = campaignLog.getVar("returnTrauma") - - if trauma ~= nil then - printToAll("Trauma values found in campaign log!", "Green") - trauma = campaignLog.call("returnTrauma") - for _, val in ipairs(trauma) do - table.insert(traumaValues, val) - end - else - traumaValues = nil - printToAll("Trauma values could not be found in campaign log!", "Yellow") - end - - local campaignGuide = findUniqueObjectWithTag("CampaignGuide") - if campaignGuide == nil then - broadcastToAll("Campaign guide not found!", "Red") - return - end - - -- clean up chaos tokens + -- clean up chaos tokens (needs to happen before saving chaos bag state) blessCurseApi.removeAll(playerColor) chaosBagApi.releaseAllSealedTokens(playerColor) - local campaignData = { - box = campaignBox.getGUID(), - log = campaignLog.getPosition(), - bag = chaosBagApi.getChaosBagState(), - trauma = traumaValues, - decks = deckImporterApi.getUiState(), - clueCount = playAreaApi.getInvestigatorCount(), - playarea = playAreaApi.getSurface(), - options = optionPanelApi.getOptions(), - guide = campaignGuide.Book.getPage(), - additionalIndex = additionalIndex.getPosition() - } + -- main data collection + campaignData.box = campaignBox.getGUID() + campaignData.bag = chaosBagApi.getChaosBagState() + campaignData.decks = deckImporterApi.getUiState() + campaignData.clueCount = playAreaApi.getInvestigatorCount() + campaignData.playarea = playAreaApi.getSurface() + campaignData.options = optionPanelApi.getOptions() + + -- save campaign log if present + local campaignLog = findUniqueObjectWithTag("CampaignLog") + if campaignLog then + local logData = campaignLog.getData() + logData.Locked = false + table.insert(campaignTokenData.ContainedObjects, logData) + + -- maybe also extract the trauma values + local trauma = campaignLog.getVar("returnTrauma") + if trauma then + printToAll("Trauma values found in campaign log!", "Green") + campaignData.trauma = {} + for _, val in ipairs(campaignLog.call("returnTrauma")) do + table.insert(campaignData.trauma, val) + end + else + printToAll("Trauma values could not be found in campaign log!", "Yellow") + end + end + + -- store campaign guide page if present + local campaignGuide = findUniqueObjectWithTag("CampaignGuide") + if campaignGuide then + campaignData.guide = campaignGuide.Book.getPage() + end + + -- store the additional index if there are any cards in it + local additionalIndex = guidReferenceApi.getObjectByOwnerAndType("Mythos", "AdditionalPlayerCardsBag") + if additionalIndex and #additionalIndex.getObjects() > 0 then + local indexData = additionalIndex.getData() + indexData.Locked = false + table.insert(campaignTokenData.ContainedObjects, indexData) + end + + -- finish the data for the campaign token campaignTokenData.GMNotes = JSON.encode(campaignData) campaignTokenData.Nickname = campaignBox.getName() .. os.date(" %b %d") .. " Save" - campaignTokenData.ContainedObjects = { } - - local indexData = additionalIndex.getData() - indexData.Locked = false - table.insert(campaignTokenData.ContainedObjects, indexData) - - local logData = campaignLog.getData() - logData.Locked = false - table.insert(campaignTokenData.ContainedObjects, logData) spawnObjectData({ data = campaignTokenData }) broadcastToAll("Campaign successfully exported! Save coin object to import on a different save.", "Green") diff --git a/src/core/Global.ttslua b/src/core/Global.ttslua index 226d9779..eff6a3e4 100644 --- a/src/core/Global.ttslua +++ b/src/core/Global.ttslua @@ -54,7 +54,7 @@ local tabIdTable = { tab5 = "fanmadePlayerCards" } --- optionPanel data +-- optionPanel data (intentionally not local!) optionPanel = {} local LANGUAGES = { { code = "zh_CN", name = "简体中文" }, @@ -762,7 +762,6 @@ end -- returns all sealed tokens on cards to the chaos bag function releaseAllSealedTokens(playerColor) - local chaosBag = findChaosBag() for _, obj in ipairs(getObjectsWithTag("CardThatSeals")) do obj.call("releaseAllTokens", playerColor) end @@ -1331,17 +1330,16 @@ end -- called by toggling an option function onClick_toggleOption(_, id) - local state = self.UI.getAttribute(id, "isOn") + local toggleState = self.UI.getAttribute(id, "isOn") - -- flip state (and handle stupid "False" value) - if state == "False" then - state = true + -- flip state (and handle stupid "False" values) + if toggleState == "False" then + self.UI.setAttribute(id, "isOn", true) + applyOptionPanelChange(id, true) else - state = false + self.UI.setAttribute(id, "isOn", "False") + applyOptionPanelChange(id, false) end - - self.UI.setAttribute(id, "isOn", state) - applyOptionPanelChange(id, state) end -- color selection for playArea @@ -1439,24 +1437,23 @@ function updateOptionPanelState() end end --- handles the applying of option selections and calls the respective functions based +-- handles the applying of option selections and calls the respective functions based on the id ---@param id string ID of the option that was selected or deselected ---@param state boolean|any State of the option (true = enabled) function applyOptionPanelChange(id, state) + optionPanel[id] = state + -- option: Snap tags if id == "useSnapTags" then playmatApi.setLimitSnapsByType(state, "All") - optionPanel[id] = state -- option: Draw 1 button elseif id == "showDrawButton" then playmatApi.showDrawButton(state, "All") - optionPanel[id] = state -- option: Clickable clue counters elseif id == "useClueClickers" then playmatApi.clickableClues(state, "All") - optionPanel[id] = state -- update master clue counter local counter = guidReferenceApi.getObjectByOwnerAndType("Mythos", "MasterClueCounter") @@ -1465,52 +1462,39 @@ function applyOptionPanelChange(id, state) -- option: Play area snap tags elseif id == "playAreaConnections" then playAreaApi.setConnectionDrawState(state) - optionPanel[id] = state -- option: Play area connection color elseif id == "playAreaConnectionColor" then playAreaApi.setConnectionColor(state) UI.setAttribute(id, "color", "#" .. Color.new(state):toHex()) - optionPanel[id] = state -- option: Play area snap tags elseif id == "playAreaSnapTags" then playAreaApi.setLimitSnapsByType(state) - optionPanel[id] = state - - -- option: Show Title on placing scenarios - elseif id == "showTitleSplash" then - optionPanel[id] = state - - -- option: Change custom playarea image on setup - elseif id == "changePlayAreaImage" then - optionPanel[id] = state -- option: Show clean up helper elseif id == "showCleanUpHelper" then - optionPanel[id] = spawnOrRemoveHelper(state, "Clean Up Helper", { -66, 1.6, 46 }) + spawnOrRemoveHelper(state, "Clean Up Helper", { -66, 1.6, 46 }) -- option: Show hand helper for each player elseif id == "showHandHelper" then spawnOrRemoveHelperForPlayermats("Hand Helper", state) - optionPanel[id] = state -- option: Show search assistant for each player elseif id == "showSearchAssistant" then spawnOrRemoveHelperForPlayermats("Search Assistant", state) - optionPanel[id] = state -- option: Show attachment helper elseif id == "showAttachmentHelper" then - optionPanel[id] = spawnOrRemoveHelper(state, "Attachment Helper", { -62, 1.4, 0 }) + spawnOrRemoveHelper(state, "Attachment Helper", { -62, 1.4, 0 }) -- option: Show CYOA campaign guides elseif id == "showCYOA" then - optionPanel[id] = spawnOrRemoveHelper(state, "CYOA Campaign Guides", { 39, 1.3, -20 }) + spawnOrRemoveHelper(state, "CYOA Campaign Guides", { 39, 1.3, -20 }) -- option: Show displacement tool elseif id == "showDisplacementTool" then - optionPanel[id] = spawnOrRemoveHelper(state, "Displacement Tool", { -57, 1.6, 46 }) + spawnOrRemoveHelper(state, "Displacement Tool", { -57, 1.6, 46 }) end end @@ -1537,7 +1521,7 @@ function spawnOrRemoveHelper(state, name, position, rotation, owner) local cleanName = name:gsub("%s+", "") guidReferenceApi.editIndex(owner or "Mythos", cleanName, spawnedGUID) else - return removeHelperObject(name) + removeHelperObject(name) end end @@ -1597,15 +1581,6 @@ end -- loads the default options function onClick_defaultSettings() - for id, _ in pairs(optionPanel) do - local state = false - -- override for settings that are enabled by default - if id == "useSnapTags" or id == "showTitleSplash" then - state = true - end - applyOptionPanelChange(id, state) - end - -- clean reset of variables optionPanel = { cardLanguage = "en", @@ -1626,6 +1601,11 @@ function onClick_defaultSettings() useSnapTags = true } + -- applying changes + for id, state in pairs(optionPanel) do + applyOptionPanelChange(id, state) + end + -- update UI updateOptionPanelState() end From aa49fdae943642e6157b2d19f730f9d4115c150e Mon Sep 17 00:00:00 2001 From: Chr1Z93 Date: Mon, 29 Apr 2024 12:23:49 +0200 Subject: [PATCH 030/157] updated option panel buttons --- modsettings/CustomUIAssets.json | 10 ++++ src/core/Global.ttslua | 22 +++----- xml/Global/OptionPanel.xml | 92 ++++++++++++++++++++------------- 3 files changed, 72 insertions(+), 52 deletions(-) diff --git a/modsettings/CustomUIAssets.json b/modsettings/CustomUIAssets.json index 1e53c890..37fe7bd3 100644 --- a/modsettings/CustomUIAssets.json +++ b/modsettings/CustomUIAssets.json @@ -29,6 +29,16 @@ "Type": 0, "URL": "http://cloud-3.steamusercontent.com/ugc/2026086584372569912/5CB461AEAE2E59D3064D90A776EB86C46081EC78/" }, + { + "Name": "option-on", + "Type": 0, + "URL": "http://cloud-3.steamusercontent.com/ugc/2462982115668997008/2178787B67B3C96F3419EDBAB8420E39893756BC/" + }, + { + "Name": "option-off", + "Type": 0, + "URL": "http://cloud-3.steamusercontent.com/ugc/2462982115668996901/D6438ECBB11DECC6DB9987589FF526FBAD4D2368/" + }, { "Name": "font_arkhamicons", "Type": 1, diff --git a/src/core/Global.ttslua b/src/core/Global.ttslua index eff6a3e4..2bd4bd9b 100644 --- a/src/core/Global.ttslua +++ b/src/core/Global.ttslua @@ -1328,18 +1328,12 @@ end -- Option Panel related functionality --------------------------------------------------------- --- called by toggling an option -function onClick_toggleOption(_, id) - local toggleState = self.UI.getAttribute(id, "isOn") - - -- flip state (and handle stupid "False" values) - if toggleState == "False" then - self.UI.setAttribute(id, "isOn", true) - applyOptionPanelChange(id, true) - else - self.UI.setAttribute(id, "isOn", "False") - applyOptionPanelChange(id, false) - end +-- changes the UI state and the internal variable for the togglebuttons +function onClick_toggleOption(_, _, id) + local currentState = optionPanel[id] + local newState = not currentState + applyOptionPanelChange(id, newState) + self.UI.setAttribute(id, "image", newState and "option-on" or "option-off") end -- color selection for playArea @@ -1430,9 +1424,7 @@ function updateOptionPanelState() elseif (type(optionValue) == "boolean" and optionValue) or (type(optionValue) == "string" and optionValue) or (type(optionValue) == "table" and #optionValue ~= 0) then - UI.setAttribute(id, "isOn", true) - else - UI.setAttribute(id, "isOn", "False") + UI.setAttribute(id, "image", "option-on") end end end diff --git a/xml/Global/OptionPanel.xml b/xml/Global/OptionPanel.xml index 19cdcaa7..d6b0b6dc 100644 --- a/xml/Global/OptionPanel.xml +++ b/xml/Global/OptionPanel.xml @@ -1,16 +1,13 @@ + alignment="MiddleLeft"/> - - - + + outline="grey"/> + animationDuration="0.2"/> + preferredHeight="44"/> + color="#222222"/> + padding="5 0 0 0"/> + font="font_teutonic-arkham"/> +