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