diff --git a/repo/js/OCR切换武器/assets/combat_avatar.json b/repo/js/OCR切换武器/assets/combat_avatar.json index b85c26d2c..26610089d 100644 --- a/repo/js/OCR切换武器/assets/combat_avatar.json +++ b/repo/js/OCR切换武器/assets/combat_avatar.json @@ -1874,7 +1874,6 @@ "丝柯克", "Skirk", "丝柯可", - "skk", "斯柯克" ], "burstCD": 15, @@ -1899,5 +1898,56 @@ "nameEn": "Dahlia", "skillCD": 9, "weapon": "1" + }, + { + "alias": [ + "伊涅芙", + "Ineffa", + "机器人", + "机娘" + ], + "burstCD": 15, + "id": "10000116", + "name": "伊涅芙", + "nameEn": "Ineffa", + "skillCD": 16, + "weapon": "13" + }, + { + "alias": [ + "菈乌玛", + "Lauma" + ], + "burstCD": 15, + "id": "10000119", + "name": "菈乌玛", + "nameEn": "Lauma", + "skillCD": 12, + "weapon": "10" + }, + { + "alias": [ + "菲林斯", + "Flins" + ], + "burstCD": 20, + "id": "10000120", + "name": "菲林斯", + "nameEn": "Flins", + "skillCD": 6, + "skillHoldCD": 16, + "weapon": "13" + }, + { + "alias": [ + "爱诺", + "Aino" + ], + "burstCD": 13.5, + "id": "10000121", + "name": "爱诺", + "nameEn": "Aino", + "skillCD": 10, + "weapon": "11" } ] \ No newline at end of file diff --git a/repo/js/OCR切换武器/main.js b/repo/js/OCR切换武器/main.js index e896c6cd5..542949afc 100644 --- a/repo/js/OCR切换武器/main.js +++ b/repo/js/OCR切换武器/main.js @@ -85,16 +85,17 @@ } // OCR识别文本 - async function recognizeText(targetText, ocrRegion, aliasToNameMap, timeout = 10000, retryInterval = 20, maxAttempts = 5) { + async function recognizeText(targetText, ocrRegion, aliasToNameMap, timeout = 100, retryInterval = 20, maxAttempts = 5, captureRegion = null) { let startTime = Date.now(); let retryCount = 0; const targetFormalName = aliasToNameMap ? aliasToNameMap[targetText] || targetText : targetText; + captureRegion?.dispose(); + captureRegion = captureGameRegion(); + const ocrObject = RecognitionObject.Ocr(ocrRegion.x, ocrRegion.y, ocrRegion.width, ocrRegion.height); + ocrObject.threshold = 0.8; while (Date.now() - startTime < timeout && retryCount < maxAttempts) { try { - let captureRegion = captureGameRegion(); - let ocrObject = RecognitionObject.Ocr(ocrRegion.x, ocrRegion.y, ocrRegion.width, ocrRegion.height); - ocrObject.threshold = 0.8; let resList = captureRegion.findMulti(ocrObject); for (let res of resList) { @@ -108,7 +109,7 @@ recognizedFormalName = fuzzyMatch(correctedText, Object.values(aliasToNameMap)) || recognizedFormalName; if (recognizedFormalName === targetFormalName) { - return { success: true, text: recognizedFormalName, x: res.x, y: res.y }; + return { text: recognizedFormalName, x: res.x, y: res.y }; } } } catch (error) { @@ -117,7 +118,8 @@ } await sleep(retryInterval); } - return { success: false }; + captureRegion?.dispose(); + return false; } // 模糊匹配文本 @@ -205,8 +207,8 @@ async function selectCharacter(characterName) { const SwitchingSteps = 99; // 最大切换次数 for (let i = 0; i < SwitchingSteps; i++) { - let result = await recognizeText(characterName, ocrRegion, aliasToNameMap, 200); - if (result.success) { + let result = await recognizeText(characterName, ocrRegion, aliasToNameMap, 100); + if (result) { // log.info(`找到 ${characterName},识别结果: ${result.text},坐标: x=${result.x}, y=${result.y}`); return true; } @@ -240,13 +242,14 @@ } // 识别并组合武器名称 - async function recognizeAndCombineWeaponName(ocrRegion, maxAttempts = 5) { + async function recognizeAndCombineWeaponName(ocrRegion, maxAttempts = 5, captureRegion = null) { const allResults = []; + captureRegion?.dispose(); + captureRegion = captureGameRegion(); + const ocrObject = RecognitionObject.Ocr(ocrRegion.x, ocrRegion.y, ocrRegion.width, ocrRegion.height); + ocrObject.threshold = 0.9; for (let i = 0; i < maxAttempts; i++) { try { - let captureRegion = captureGameRegion(); - let ocrObject = RecognitionObject.Ocr(ocrRegion.x, ocrRegion.y, ocrRegion.width, ocrRegion.height); - ocrObject.threshold = 0.8; let resList = captureRegion.findMulti(ocrObject); for (let res of resList) { let correctedText = res.text; @@ -262,6 +265,7 @@ await sleep(20); } + captureRegion?.dispose(); const combinedResult = combineResults(allResults); // log.info(`组合后的识别结果: ${combinedResult}`); return combinedResult; @@ -310,6 +314,41 @@ const maxColumns = 4; for (let scroll = 0; scroll <= pageScrollCount; scroll++) { + // ====================================== + // 【新增】前置武器识别:行列循环前先识别一次 + // ====================================== + log.info(`第 ${scroll + 1} 页 - 开始前置武器识别`); + const preRecognized = await recognizeAndCombineWeaponName(ocrRegion); + let isPreMatched = false; + + if (preRecognized) { + // 前置识别结果匹配目标武器 + let preWeaponName2 = fuzzyMatch(preRecognized, weaponNames, 1); + if (!preWeaponName2) { + log.warn(`前置识别:未匹配已知武器,使用原始识别结果 ${preRecognized} 匹配`); + preWeaponName2 = preRecognized; + } + + // 计算匹配占比(排除干扰词) + const preMatchRatio = calculateMatchRatio(weaponName1, preWeaponName2); + if (preMatchRatio >= 0.8) { + log.info(`✅ 前置识别成功!目标武器(${weaponName1}) 与 当前武器(${preWeaponName2}) 匹配,占比 ${preMatchRatio.toFixed(2)}`); + // 执行确认逻辑 + await click(1600, 1005); // 点击确认 + await sleep(1000); + await click(1320, 755); // 点击确认 + await sleep(1000); + return true; // 匹配成功,直接返回,跳过后续行列循环 + } else { + log.info(`❌ 前置识别不匹配:目标(${weaponName1}) vs 当前(${preWeaponName2}),占比 ${preMatchRatio.toFixed(2)}`); + } + } else { + log.info(`❌ 前置识别未读取到任何武器名称`); + } + + // ====================================== + // 前置识别失败:执行原有的行列循环(逐个格子检查) + // ====================================== for (let row = 0; row < maxRows; row++) { for (let column = 0; column < maxColumns; column++) { const clickX = Math.round(startX + column * columnWidth); @@ -320,7 +359,7 @@ const combinedWeaponName2 = await recognizeAndCombineWeaponName(ocrRegion); if (!combinedWeaponName2) { - log.warn("OCR 识别失败,未找到任何武器名"); + log.warn(`格子(${row},${column}):未识别到武器名称`); continue; } @@ -336,7 +375,7 @@ // 计算匹配占比,排除干扰词 const matchRatio = calculateMatchRatio(weaponName1, weaponName2); if (matchRatio >= 0.8) { // 如果匹配占比大于等于 80%,则认为匹配成功 - log.info(`成功匹配武器:${weaponName1},匹配占比 ${matchRatio.toFixed(2)}`); + log.info(`✅ 格子(${row},${column}) 匹配成功:目标(${weaponName1}) vs 当前(${weaponName2}),占比 ${matchRatio.toFixed(2)}`); await click(1600, 1005); // 点击确认 await sleep(1000); await click(1320, 755); // 点击确认 diff --git a/repo/js/食材加工/assets/Picture/Rye-Flour.png b/repo/js/食材加工/assets/Picture/Rye-Flour.png new file mode 100644 index 000000000..b1a586ebb Binary files /dev/null and b/repo/js/食材加工/assets/Picture/Rye-Flour.png differ diff --git a/repo/js/食材加工/assets/Picture/Sour-Cream.png b/repo/js/食材加工/assets/Picture/Sour-Cream.png new file mode 100644 index 000000000..8977f8234 Binary files /dev/null and b/repo/js/食材加工/assets/Picture/Sour-Cream.png differ diff --git a/repo/js/食材加工/main.js b/repo/js/食材加工/main.js index 8863a7d28..27cb7e4d1 100644 --- a/repo/js/食材加工/main.js +++ b/repo/js/食材加工/main.js @@ -13,17 +13,19 @@ "Processing12": "assets/Picture/Raw-Meat.png", "Processing13": "assets/Picture/Fish.png", "Processing14": "assets/Picture/Mysterious-Meat.png", - "Processing15": "assets/Picture/Butter.png", - "Processing16": "assets/Picture/Smoked-Poultry.png", - "Processing17": "assets/Picture/Lard.png", - "Processing18": "assets/Picture/Ham.png", - "Processing21": "assets/Picture/Sugar.png", - "Processing22": "assets/Picture/Spices.png", - "Processing23": "assets/Picture/Crab-Roe.png", - "Processing24": "assets/Picture/Jam.png", - "Processing25": "assets/Picture/Cheese.png", - "Processing26": "assets/Picture/Bacon.png", - "Processing27": "assets/Picture/Sausage.png", + "Processing15": "assets/Picture/Rye-Flour.png", + "Processing16": "assets/Picture/Butter.png", + "Processing17": "assets/Picture/Smoked-Poultry.png", + "Processing18": "assets/Picture/Lard.png", + "Processing21": "assets/Picture/Ham.png", + "Processing22": "assets/Picture/Sugar.png", + "Processing23": "assets/Picture/Spices.png", + "Processing24": "assets/Picture/Sour-Cream.png", + "Processing25": "assets/Picture/Crab-Roe.png", + "Processing26": "assets/Picture/Jam.png", + "Processing27": "assets/Picture/Cheese.png", + "Processing28": "assets/Picture/Bacon.png", + "Processing31": "assets/Picture/Sausage.png", // 添加其他食材的图像映射 }; @@ -33,17 +35,19 @@ const processingKeyChineseMap = { "Processing12": "兽肉", "Processing13": "鱼", "Processing14": "神秘的肉", - "Processing15": "黄油", - "Processing16": "熏禽肉", - "Processing17": "黄油", - "Processing18": "火腿", - "Processing21": "糖", - "Processing22": "辛香料", - "Processing23": "蟹黄", - "Processing24": "果酱", - "Processing25": "奶酪", - "Processing26": "培根", - "Processing27": "香肠", + "Processing15": "黑麦粉", + "Processing16": "奶油", + "Processing17": "熏禽肉", + "Processing18": "黄油", + "Processing21": "火腿", + "Processing22": "糖", + "Processing23": "香辛料", + "Processing24": "酸奶油", + "Processing25": "蟹黄", + "Processing26": "果酱", + "Processing27": "奶酪", + "Processing28": "培根", + "Processing31": "香肠" // 添加其他加工设置的中文映射 }; @@ -78,7 +82,7 @@ const processingKeyChineseMap = { } // 行列数的排列组合 - const rows = [1, 2];// [1, 2, 3, 4];三、四行 暂时用不上 + const rows = [1, 2, 3];// [1, 2, 3, 4];三、四行 暂时用不上 const cols = [1, 2, 3, 4, 5, 6, 7, 8]; const gridCoordinates = []; @@ -99,10 +103,12 @@ const processingKeyChineseMap = { let template = file.ReadImageMatSync(imagePath); let recognitionObject = RecognitionObject.TemplateMatch(template, x, y, searchWidth, searchHeight); // 设置识别阈值和通道 - recognitionObject.threshold = 0.90; // 设置识别阈值为 0.85 + recognitionObject.threshold = 0.9; // 设置识别阈值为 0.9 recognitionObject.Use3Channels = true; // 使用三通道匹配 - let result = captureGameRegion().find(recognitionObject); + ra?.dispose(); + ra = captureGameRegion(); + let result = ra.find(recognitionObject); return result.isExist() ? result : null; } catch (error) { log.error(`图像识别失败,路径: ${imagePath}, 错误: ${error.message}`); @@ -144,9 +150,9 @@ const processingKeyChineseMap = { /**烹饪区**/ // 检查 CookingTimes 是否为正整数 const CookingTimes = Math.max(0, Number(settings.CookingTimes) || 0); - const Cooking = settings.Cooking - const rightOffset = 0; // 右偏移 - const downOffset = 0; // 下偏移 + const pageScrollCount = Math.max(0, Number(settings.pageScrollCount) || 0); // 滑页次数 + const rightOffset = Math.max(0, Number(settings.rightOffset) - 1 || 2); // 右偏移 + const downOffset = Math.max(0, Number(settings.downOffset) - 1 || 0); // 下偏移 if (CookingTimes > 0 && Number.isInteger(CookingTimes)) { CookingClickX = 910; // 设置 CookingClickX @@ -156,23 +162,32 @@ const processingKeyChineseMap = { } // 烹饪操作函数 - async function performCookingOperations(CookingClickX, CookingClickY, rightOffset, downOffset, CookingTimes) { + async function performCookingOperations(CookingClickX, CookingClickY, pageScrollCount, rightOffset, downOffset, CookingTimes) { log.info("执行烹饪操作..."); click(CookingClickX, CookingClickY); await sleep(500); click(CookingClickX, CookingClickY); // 点击菜单 await sleep(500); - click(145, 1015); // 点击筛选 - await sleep(500); - click(79, 1020); // 重置输入框 - await sleep(500); - click(160, 115); // 点击输入框 - await sleep(500); - inputText(`${Cooking}`); // 输入 Cooking 的值 - await sleep(500); - click(375, 1020); // 确认筛选 - await sleep(500); + for (let i = 0; i < pageScrollCount; ++i) { + click(1200, 920); + await sleep(500); + leftButtonDown(); + await sleep(100); + + // 根据条件选择运行的 JSON 文件 + let filePath; + if (pageScrollCount >= 10 && (i + 1) % 10 === 0) { + filePath = `assets/pageScroll2.json`; // 每 10 次运行一次 pageScroll2.json + } else { + filePath = `assets/pageScroll.json`; // 其他情况下运行 pageScroll.json + } + + await keyMouseScript.runFile(filePath); // 平滑移动鼠标 + await sleep(600); + leftButtonUp(); + await sleep(100); + } // 点击动态坐标 const rightClickX = Math.round(178.5 + rightOffset * 147); @@ -223,7 +238,8 @@ async function recognizeFIcon() { 400 ); - let ra = captureGameRegion(); + ra?.dispose(); + ra = captureGameRegion(); let fRes = ra.find(fDialogueRo); if (!fRes.isExist()) { @@ -237,7 +253,7 @@ async function recognizeFIcon() { await simulateKeyOperations("S", 200); // 后退 200 毫秒 log.info("执行后退操作"); await sleep(200); - await simulateKeyOperations("W", 600); // 前进 600 毫秒 + await simulateKeyOperations("W", 800); // 前进 800 毫秒 log.info("执行前进操作"); } else if (f_attempts === 3) { // 第二次未找到 F 图标 @@ -249,6 +265,7 @@ async function recognizeFIcon() { } // 重新获取游戏区域截图 + ra?.dispose(); ra = captureGameRegion(); fRes = ra.find(fDialogueRo); @@ -284,7 +301,8 @@ async function recognizeCookingIcon(centerYF) { 36 // 高度范围 ); - let ra = captureGameRegion(); + ra?.dispose(); + ra = captureGameRegion(); let cookingRes = ra.find(cookingRo); if (cookingRes.isExist()) { @@ -380,6 +398,7 @@ async function AutoPath() { await sleep(1000); click(150, 1020); await sleep(500); click(150, 1020); await sleep(500); + click(960, 1020); await sleep(500); // 如果 PrepCountArray 和 enabledProcessingKeys 的长度不匹配,使用第一个 PrepCount 值 const minLen = Math.min(PrepCountArray.length, enabledProcessingKeys.length); @@ -388,7 +407,7 @@ async function AutoPath() { // 遍历启用的 Processing 设置,进行图像识别 for (const processingKey of enabledProcessingKeys) { // 获取 processingKey 的中文描述 - const chineseDescription = processingKeyChineseMap[processingKey] || "未知食材"; + const chineseDescription = processingKeyChineseMap[processingKey] || "未知食材"; const imagePath = ingredientImageMap[processingKey]; if (!imagePath) { @@ -412,60 +431,45 @@ async function AutoPath() { // log.info(`通过图像识别找到食材: ${chineseDescription} 在坐标 X=${scanX}, Y=${scanY}`); log.info(`通过图像识别找到食材: ${chineseDescription}`); imageResult.click(); + await sleep(300); // 等待1秒以确保点击生效 + imageResult.click(); await sleep(1000); // 等待1秒以确保点击生效 foundIngredient = true; + // 执行额外的点击操作(如果需要) + await performExtraClicks(processingKey); + + // 点击确认按钮 + click(1600, 1020); await sleep(2000); + + // 执行 PrepCount 操作 + const PrepCount = PrepCountArray.length > 0 ? PrepCountArray.shift() : defaultPrepCount; + if (PrepCount > 0) { + await performPrepCountActions(PrepCount); + } + break; // 找到食材后跳出循环 } } + if (!foundIngredient) { - // 图像识别未成功,可能是因为该食材正在被加工,通过OCR识别 - const ocrResult = captureGameRegion().findMulti(RecognitionObject.ocr(112, 118, 1161, 345)); - for (var i = 0; i < ocrResult.count; ++i) { - if (ocrResult[i].text.endsWith("分钟") || ocrResult[i].text.endsWith("秒")) { - // 选中该食材 - click(ocrResult[i].x, ocrResult[i].y); - await sleep(500); - // OCR食材名称 - const ocrResult2 = captureGameRegion().findMulti(RecognitionObject.ocr(1308, 122, 492, 52)); - const ingredientName = ocrResult2.count > 0 ? ocrResult2[0].text : null; - if (ingredientName === chineseDescription) { - log.info(`通过OCR识别找到食材: ${chineseDescription}`); - foundIngredient = true; - break; - } - } - } - } - - if (foundIngredient) { - // 执行额外的点击操作(如果需要) - await performExtraClicks(processingKey); - - // 点击确认按钮 - click(1600, 1020); await sleep(2000); - - // 执行 PrepCount 操作 - const PrepCount = PrepCountArray.length > 0 ? PrepCountArray.shift() : defaultPrepCount; - if (PrepCount > 0) { - await performPrepCountActions(PrepCount); - } - } else { log.error(`未能识别到食材: ${chineseDescription}`); } } // 如果 CookingClickX 被设置,执行烹饪操作 if (CookingClickX === 910) { - await performCookingOperations(CookingClickX, CookingClickY, rightOffset, downOffset, CookingTimes); + await performCookingOperations(CookingClickX, CookingClickY, pageScrollCount, rightOffset, downOffset, CookingTimes); } await genshin.returnMainUi(); keyDown("S"); await sleep(1000); keyUp("S"); await sleep(1000); + ra?.dispose(); } catch (error) { log.error(`执行按键或鼠标操作时发生错误:${error.message}`); } } + let ra = null // 调用 AutoPath 函数 await AutoPath(); })(); diff --git a/repo/js/食材加工/manifest.json b/repo/js/食材加工/manifest.json index be93807b8..20cb78f2c 100644 --- a/repo/js/食材加工/manifest.json +++ b/repo/js/食材加工/manifest.json @@ -1,19 +1,13 @@ { "manifest_version": 1, - "name": "选择加工食材", + "name": "选择加工 食材", "version": "2.2", - "description": "食材加工 识图 复选框。", + "description": "食材加工 识图 复选框。适配黑麦粉、酸奶油", "authors": [ { - "name": "吉吉喵", - "links": "https://github.com/JJMdzh" + "name": "吉吉喵" } ], - "tags": [ - "食材", - "料理", - "模板匹配" - ], "settings_ui": "settings.json", "main": "main.js" -} +} \ No newline at end of file diff --git a/repo/js/食材加工/settings.json b/repo/js/食材加工/settings.json index f71078760..669a3324b 100644 --- a/repo/js/食材加工/settings.json +++ b/repo/js/食材加工/settings.json @@ -1,92 +1,102 @@ -[ - { - "name": "CookingTimes", - "type": "input-text", - "label": "【料理制作】:\n\n烹饪次数(默认0,即跳过)" - }, - { - "name": "Cooking", - "type": "input-text", - "label": "输入料理名" - }, - { - "name": "PrepCount", - "type": "input-text", - "label": "\n====================\n\n【食材加工】:\n\n加工数量(不填默认99)" - }, - { - "name": "Processing11", - "type": "checkbox", - "label": "如勾选:面粉,黄油,糖\n上方填入88,66\n则加工面粉88,黄油66,糖88\n-----------------\n\n1小麦=面粉" - }, - { - "name": "Processing15", - "type": "checkbox", - "label": "-----------------\n\n1牛奶=奶油" - }, - { - "name": "Processing17", - "type": "checkbox", - "label": "-----------------\n\n2牛奶=黄油" - }, - { - "name": "Processing25", - "type": "checkbox", - "label": "-----------------\n\n3牛奶=奶酪" - }, - { - "name": "Processing18", - "type": "checkbox", - "label": "-----------------\n\n2兽肉+1盐=火腿" - }, - { - "name": "Processing27", - "type": "checkbox", - "label": "-----------------\n\n3兽肉=香肠" - }, - { - "name": "Processing16", - "type": "checkbox", - "label": "--------------------\n\n3禽肉+1盐=熏禽肉" - }, - { - "name": "Processing26", - "type": "checkbox", - "label": "-----------------\n\n4兽肉+2盐=培根" - }, - { - "name": "Processing21", - "type": "checkbox", - "label": "-----------------\n\n2甜甜花=糖" - }, - { - "name": "Processing22", - "type": "checkbox", - "label": "-----------------\n\n2香辛果=香辛料" - }, - { - "name": "Processing24", - "type": "checkbox", - "label": "----------------------------\n\n3日落果+2树莓+1糖=果酱" - }, - { - "name": "Processing23", - "type": "checkbox", - "label": "-----------------\n\n4螃蟹=蟹黄" - }, - { - "name": "Processing12", - "type": "checkbox", - "label": "--------------------\n\n冷鲜肉 转化成 兽肉" - }, - { - "name": "Processing14", - "type": "checkbox", - "label": "-----------------------------\n\n神秘的肉 转化成 肉加工产物" - }, - { - "name": "Processing13", - "type": "checkbox", - "label": "--------------------------------\n\n鱼 转化成 鱼肉,排除 红色花鳉" - } +[ + { + "name": "CookingTimes", + "type": "input-text", + "label": "【料理制作】:\n\n烹饪次数(默认0,即跳过)", + }, + { + "name": "Cooking", + "type": "input-text", + "label": "输入料理名", + }, + { + "name": "PrepCount", + "type": "input-text", + "label": "\n====================\n\n【食材加工】:\n\n加工数量(不填默认99)" + }, + { + "name": "Processing11", + "type": "checkbox", + "label": "如勾选:面粉,黄油,糖\n上方填入88,66\n则加工面粉88,黄油66,糖88\n-----------------\n\n1小麦=面粉" + }, + { + "name": "Processing15", + "type": "checkbox", + "label": "-----------------\n\n1黑麦=黑麦粉" + }, + { + "name": "Processing24", + "type": "checkbox", + "label": "-----------------\n\n1牛奶=酸奶油" + }, + { + "name": "Processing16", + "type": "checkbox", + "label": "-----------------\n\n1牛奶=奶油" + }, + { + "name": "Processing18", + "type": "checkbox", + "label": "-----------------\n\n2牛奶=黄油" + }, + { + "name": "Processing27", + "type": "checkbox", + "label": "-----------------\n\n3牛奶=奶酪" + }, + { + "name": "Processing21", + "type": "checkbox", + "label": "-----------------\n\n2兽肉+1盐=火腿" + }, + { + "name": "Processing31", + "type": "checkbox", + "label": "-----------------\n\n3兽肉=香肠" + }, + { + "name": "Processing17", + "type": "checkbox", + "label": "--------------------\n\n3兽肉+1盐=熏禽肉" + }, + { + "name": "Processing28", + "type": "checkbox", + "label": "-----------------\n\n4兽肉+2盐=培根" + }, + { + "name": "Processing22", + "type": "checkbox", + "label": "-----------------\n\n2甜甜花=糖" + }, + { + "name": "Processing23", + "type": "checkbox", + "label": "-----------------\n\n2香辛果=香辛料" + }, + { + "name": "Processing26", + "type": "checkbox", + "label": "----------------------------\n\n3日落果+2树莓+1糖=果酱" + }, + { + "name": "Processing25", + "type": "checkbox", + "label": "-----------------\n\n4螃蟹=蟹黄" + }, + { + "name": "Processing12", + "type": "checkbox", + "label": "--------------------\n\n冷鲜肉 转化成 兽肉" + }, + { + "name": "Processing14", + "type": "checkbox", + "label": "-----------------------------\n\n神秘的肉 转化成 肉加工产物" + }, + { + "name": "Processing13", + "type": "checkbox", + "label": "--------------------------------\n\n鱼 转化成 鱼肉,排除 红色花鳉" + } ] \ No newline at end of file