From 1420a6c8aec27344aac88289ab21b0b5d6f6f782 Mon Sep 17 00:00:00 2001 From: Chr1Z93 Date: Sat, 3 Aug 2024 13:19:08 +0200 Subject: [PATCH 1/2] Added Card Enhancer // Updated Image for Instruction Generator --- config.json | 5 +- objects/CardBackEnhancer.87450c.json | 70 ++++++++++++++++ ...n => DeckInstructionGenerator.240522.json} | 32 ++++---- src/accessories/CardBackEnhancer.ttslua | 80 +++++++++++++++++++ ...ttslua => DeckInstructionGenerator.ttslua} | 20 ++--- 5 files changed, 180 insertions(+), 27 deletions(-) create mode 100644 objects/CardBackEnhancer.87450c.json rename objects/{InstructionGenerator.240522.json => DeckInstructionGenerator.240522.json} (66%) create mode 100644 src/accessories/CardBackEnhancer.ttslua rename src/arkhamdb/{InstructionGenerator.ttslua => DeckInstructionGenerator.ttslua} (78%) diff --git a/config.json b/config.json index 0195d695..7cc559a3 100644 --- a/config.json +++ b/config.json @@ -157,7 +157,7 @@ "TokenSource.124381", "GameData.3dbe47", "SCEDTour.0e5aa8", - "InstructionGenerator.240522", + "DeckInstructionGenerator.240522", "PlayerCards.2d30ee", "TokenRemover.39b175", "TokenRemover.2ba7a5", @@ -218,7 +218,8 @@ "Neutral.06ee01", "Neutral.88d9ff", "Neutral.42ec66", - "Neutral.f94579" + "Neutral.f94579", + "CardBackEnhancer.87450c" ], "PlayArea": 1, "PlayerCounts": [ diff --git a/objects/CardBackEnhancer.87450c.json b/objects/CardBackEnhancer.87450c.json new file mode 100644 index 00000000..05a43a51 --- /dev/null +++ b/objects/CardBackEnhancer.87450c.json @@ -0,0 +1,70 @@ +{ + "AltLookAngle": { + "x": 0, + "y": 0, + "z": 0 + }, + "AttachedSnapPoints": [ + { + "Position": { + "x": 0, + "y": 0.1, + "z": 0.2 + } + } + ], + "Autoraise": true, + "ColorDiffuse": { + "b": 0, + "g": 0, + "r": 0 + }, + "CustomImage": { + "CustomTile": { + "Stackable": false, + "Stretch": true, + "Thickness": 0.1, + "Type": 3 + }, + "ImageScalar": 1, + "ImageSecondaryURL": "", + "ImageURL": "https://steamusercontent-a.akamaihd.net/ugc/2466368617700253137/69CF42FB33A6CDDD8A84191FBCB27637E1A7699D/", + "WidthScale": 0 + }, + "Description": "This tool applies the correct (high resolution) PlayerCard or ScenarioCard back to cards / decks that are dropped on it. It requires the respective tag on each card.\n\nWhy would you need this?\na) You're creating custom content and some cards have the wrong back for some reason.\nb) You're playing custom content and noticed that a card uses an old (low resolution) PlayerCard or ScenarioCard back.", + "DragSelectable": true, + "GMNotes": "", + "GUID": "87450c", + "Grid": true, + "GridProjection": false, + "Hands": false, + "HideWhenFaceDown": false, + "IgnoreFoW": false, + "LayoutGroupSortIndex": 0, + "Locked": true, + "LuaScriptState": "", + "LuaScript": "require(\"accessories/CardBackEnhancer\")", + "MeasureMovement": false, + "Name": "Custom_Tile", + "Nickname": "Card Back Enhancer", + "Snap": true, + "Sticky": true, + "Tags": [ + "PlayerCard", + "ScenarioCard" + ], + "Tooltip": true, + "Transform": { + "posX": -17.5, + "posY": 1.481, + "posZ": 89, + "rotX": 0, + "rotY": 270, + "rotZ": 0, + "scaleX": 2.667, + "scaleY": 1, + "scaleZ": 2.667 + }, + "Value": 0, + "XmlUI": "" +} \ No newline at end of file diff --git a/objects/InstructionGenerator.240522.json b/objects/DeckInstructionGenerator.240522.json similarity index 66% rename from objects/InstructionGenerator.240522.json rename to objects/DeckInstructionGenerator.240522.json index 1954303d..eeffbb5f 100644 --- a/objects/InstructionGenerator.240522.json +++ b/objects/DeckInstructionGenerator.240522.json @@ -15,23 +15,23 @@ ], "Autoraise": true, "ColorDiffuse": { - "b": 1, - "g": 1, - "r": 1 + "b": 0, + "g": 0, + "r": 0 }, "CustomImage": { - "CustomToken": { - "MergeDistancePixels": 15, + "CustomTile": { "Stackable": false, - "StandUp": false, - "Thickness": 0.1 + "Stretch": true, + "Thickness": 0.1, + "Type": 3 }, "ImageScalar": 1, "ImageSecondaryURL": "", - "ImageURL": "https://steamusercontent-a.akamaihd.net/ugc/2280574378890547614/63FE6CDF23322B6C4001514E2B8891BA998FAD71/", + "ImageURL": "https://steamusercontent-a.akamaihd.net/ugc/2466368617700119071/AB8294EEBA3A219CDCE287323B764D13E2A43822/", "WidthScale": 0 }, - "Description": "This tool can generate a description for your deck on ArkhamDB that will instruct the deck importer to add the specified cards.\nThe cards need to be available (either from the AllCardsBag or the 'Additional Playercards Bag'.", + "Description": "This tool can generate a description for your deck on ArkhamDB that will instruct the Deck Importer to add the specified cards.\nThe cards need to be available (either from the AllCardsBag or the 'Additional Playercards Bag'.", "DragSelectable": true, "GMNotes": "", "GUID": "240522", @@ -42,25 +42,25 @@ "IgnoreFoW": false, "LayoutGroupSortIndex": 0, "Locked": true, - "LuaScript": "require(\"arkhamdb/InstructionGenerator\")", + "LuaScript": "require(\"arkhamdb/DeckInstructionGenerator\")", "LuaScriptState": "", "MeasureMovement": false, - "Name": "Custom_Token", - "Nickname": "Instruction Generator", + "Name": "Custom_Tile", + "Nickname": "Deck Instruction Generator", "Snap": true, "Sticky": true, "Tooltip": true, "Transform": { "posX": -17.5, - "posY": 1.531, + "posY": 1.481, "posZ": 83, "rotX": 0, "rotY": 270, "rotZ": 0, - "scaleX": 1.25, + "scaleX": 3, "scaleY": 1, - "scaleZ": 1.35 + "scaleZ": 3 }, "Value": 0, "XmlUI": "" -} +} \ No newline at end of file diff --git a/src/accessories/CardBackEnhancer.ttslua b/src/accessories/CardBackEnhancer.ttslua new file mode 100644 index 00000000..ae288f62 --- /dev/null +++ b/src/accessories/CardBackEnhancer.ttslua @@ -0,0 +1,80 @@ +local backUrl = { + ScenarioCard = + "https://steamusercontent-a.akamaihd.net/ugc/2342503777940351785/F64D8EFB75A9E15446D24343DA0A6EEF5B3E43DB/", + PlayerCard = + "https://steamusercontent-a.akamaihd.net/ugc/2342503777940352139/A2D42E7E5C43D045D72CE5CFC907E4F886C8C690/" +} + +local deckChanges = {} +local lastObjGuid + +function onCollisionEnter(collisionInfo) + local obj = collisionInfo.collision_object + if obj.guid == lastObjGuid then return end + lastObjGuid = obj.guid + Wait.time(function() lastObjGuid = nil end, 0.5) + + if obj.type ~= "Card" and obj.type ~= "Deck" then return end + + local data = obj.getData() + local count = 0 + if obj.type == "Card" then + local result = processCard(data) + if result then count = count + 1 end + elseif obj.type == "Deck" then + for _, cardData in ipairs(data["ContainedObjects"]) do + local result = processCard(cardData) + if result then count = count + 1 end + end + + -- update top-level custom deck data + for customDeckId, customDeckData in pairs(data["CustomDeck"]) do + if deckChanges[customDeckId] then + customDeckData["BackURL"] = deckChanges[customDeckId] + end + end + end + + if count == 1 then + broadcastToAll("Enhanced the back of 1 card.") + else + broadcastToAll("Enhanced the back of " .. count .. " cards.") + end + + obj.destruct() + spawnObjectData({ data = data }) +end + +function processCard(cardData) + -- determine card type + local tags = {} + for _, tag in ipairs(cardData["Tags"] or {}) do + tags[tag] = true + end + + -- has both or neither tag, can't work out back + if tags.PlayerCard == tags.ScenarioCard then + printToAll("Missing or double tag for '" .. cardData["Nickname"] .. "'.") + return false + end + + local newBack + if tags.PlayerCard then + newBack = backUrl.PlayerCard + elseif tags.ScenarioCard then + newBack = backUrl.ScenarioCard + end + + local customDeckId, customDeckData = next(cardData["CustomDeck"]) + + -- if this card already has the correct back + if customDeckData["BackURL"] == newBack then return false end + + -- skip cards with decksheets as back + if (customDeckData["NumHeight"] == 1 and customDeckData["NumWidth"] == 1) + or customDeckData["UniqueBack"] == false then + customDeckData["BackURL"] = newBack + deckChanges[customDeckId] = newBack + end + return true +end diff --git a/src/arkhamdb/InstructionGenerator.ttslua b/src/arkhamdb/DeckInstructionGenerator.ttslua similarity index 78% rename from src/arkhamdb/InstructionGenerator.ttslua rename to src/arkhamdb/DeckInstructionGenerator.ttslua index 8aa520b2..ac751ea6 100644 --- a/src/arkhamdb/InstructionGenerator.ttslua +++ b/src/arkhamdb/DeckInstructionGenerator.ttslua @@ -7,11 +7,11 @@ function onLoad() local buttonParameters = {} buttonParameters.function_owner = self buttonParameters.height = 200 - buttonParameters.width = 1200 - buttonParameters.font_size = 75 + buttonParameters.width = 800 buttonParameters.click_function = "generate" - buttonParameters.label = "Generate instructions!" - buttonParameters.position = { 0, 0.06, 1.55 } + buttonParameters.color = { 0, 0, 0, 0 } + buttonParameters.position = { 0, 0.11, 0.74 } + buttonParameters.scale = { 0.5, 1, 0.5 } self.createButton(buttonParameters) -- "output" text field @@ -19,14 +19,15 @@ function onLoad() inputParameters.label = "Click button above" inputParameters.input_function = "none" inputParameters.function_owner = self - inputParameters.position = { 0, 0.05, 1.95 } + inputParameters.position = { 0, 0.11, 1.1 } inputParameters.width = 1200 inputParameters.height = 130 inputParameters.font_size = 107 + inputParameters.scale = { 0.4, 1, 0.4 } self.createInput(inputParameters) end --- generates a string for the ArkhamDB deck notes that will instruct the deck import to add the specified cards +-- generates a string for the deck notes that will instruct the Deck Importer to add the specified cards function generate(_, playerColor) idList = {} for _, obj in ipairs(searchLib.onObject(self, "isCardOrDeck")) do @@ -43,7 +44,8 @@ function generate(_, playerColor) broadcastToColor("Didn't find any valid cards.", playerColor, "Red") return else - broadcastToColor("Created deck instruction for " .. #idList .. " card(s). Copy it from the input field.", playerColor, "Green") + broadcastToColor("Created deck instruction for " .. #idList .. " card(s). Copy it from the input field.", playerColor, + "Green") end -- sort the idList @@ -55,7 +57,7 @@ function generate(_, playerColor) description = description .. "\n- add: " .. entry.id .. " (**" .. entry.name .. "**)" end - self.editInput({index = 0, value = description}) + self.editInput({ index = 0, value = description }) end -- use the ZoopGuid as fallback if no id present @@ -70,7 +72,7 @@ end function processCard(notes, name, playerColor) local id = getIdFromData(JSON.decode(notes) or {}) if id then - table.insert(idList, {id = id, name = name}) + table.insert(idList, { id = id, name = name }) else broadcastToColor("Couldn't get ID for " .. name .. ".", playerColor, "Red") end From 90c41c746f9857e822397fa8217b2af1c2040251 Mon Sep 17 00:00:00 2001 From: Chr1Z93 Date: Sat, 3 Aug 2024 14:04:57 +0200 Subject: [PATCH 2/2] Added better detection for scenario reference cards --- src/core/MythosArea.ttslua | 59 ++++++++++++++++++++++++-------------- 1 file changed, 37 insertions(+), 22 deletions(-) diff --git a/src/core/MythosArea.ttslua b/src/core/MythosArea.ttslua index 83a10cf6..25f451d8 100644 --- a/src/core/MythosArea.ttslua +++ b/src/core/MythosArea.ttslua @@ -54,33 +54,48 @@ function onCollisionEnter(collisionInfo) -- early exit for better performance if object.type ~= "Card" then return end - -- get scenario name and maybe fire followup event - if object.getName() == "Scenario" then - local description = object.getDescription() - - -- detect if a new scenario card is placed down - if currentScenario ~= description then - currentScenario = description - fireScenarioChangedEvent() - end - - local metadata = JSON.decode(object.getGMNotes()) or {} - if not metadata["tokens"] then - tokenData = {} - return - end - - -- detect orientation of scenario card (for difficulty) - useFrontData = not object.is_face_down - tokenData = metadata["tokens"][(useFrontData and "front" or "back")] - fireTokenDataChangedEvent() - end - + -- reset spawned tokens and remove tokens from cards in encounter deck / discard area local localPos = self.positionToLocal(object.getPosition()) if inArea(localPos, ENCOUNTER_DECK_AREA) or inArea(localPos, ENCOUNTER_DISCARD_AREA) then Wait.frames(function() tokenSpawnTrackerApi.resetTokensSpawned(object) end, 1) removeTokensFromObject(object) + return end + + -- get metadata + local md = JSON.decode(object.getGMNotes()) or {} + + -- get scenario name and maybe fire followup event + local cardName = object.getName() + if object.getName() == "Scenario" or md.type == "ScenarioReference" then + getDataFromReferenceCard(object, cardName, md) + end +end + +-- maybe load data from reference card +function getDataFromReferenceCard(card, cardName, md) + local newScenarioName + if cardName == "Scenario" then + newScenarioName = card.getDescription() + else + newScenarioName = cardName + end + + -- detect if a new scenario card is placed down + if currentScenario ~= newScenarioName then + currentScenario = newScenarioName + fireScenarioChangedEvent() + end + + if not md["tokens"] then + tokenData = {} + return + end + + -- detect orientation of scenario card (for difficulty) + useFrontData = not card.is_face_down + tokenData = md["tokens"][(useFrontData and "front" or "back")] + fireTokenDataChangedEvent() end -- TTS event handler. Handles scenario name event triggering