diff --git a/repo/js/食材加工(模拟点击)/README.md b/repo/js/食材加工(模拟点击)/README.md new file mode 100644 index 000000000..3f73b0c63 --- /dev/null +++ b/repo/js/食材加工(模拟点击)/README.md @@ -0,0 +1,74 @@ +# 食材加工脚本 + +本脚本用于食材加工。可根据配置自动选择各类食材进行批量制作。加工的时候会直接拉满加工数量。 + +- 🎯 自动导航至指定灶台 +- 🧾 智能识别并批量加工多种食材(支持面粉、奶油、火腿等) +- 📦 加工数量自动最大化 +- 🔔 完成后自动返回主界面并发送通知 + +## 🚀 使用方法 + +1. 通过 BetterGI 脚本设置界面勾选需要加工的食材参数 +2. 启动脚本即可自动运行 + +## ⚙️ 参数配置 + +通过 `settings` 对象配置需要加工的食材(布尔值开关): + +### 食材开关参数 + +以下参数控制是否加工对应食材(布尔值): + +- `flour` - 面粉 +- `rawmeat` - 兽肉 +- `fish` - 鱼肉 +- `mysteriousmeat` - 神秘肉 +- `ryeflour` - 黑麦粉 +- `cream` - 奶油 +- `smokedPoultry` - 熏禽肉 +- `butter` - 黄油 +- `ham` - 火腿 +- `sugar` - 糖 +- `spice` - 香辛料 +- `smetana` - 酸奶油 +- `crabRoe` - 蟹黄 +- `jam` - 果酱 +- `cheese` - 奶酪 +- `bacon` - 培根 +- `sausage` - 香肠 + +## 📋 注意事项 + +> ⚠️ 使用前请仔细阅读 + +- 🖥️ 确保游戏窗口分辨率为 **16:9**,否则可能导致点击异常 +- 🚫 脚本运行期间请勿手动操作,以免干扰自动化流程 +- 📦 请保证材料的充足,避免造成加工物品位置偏移,导致加工错误的问题 +- 🐟 鱼肉加工使用默认材料配置 + +## 🎉 完成提示 + +脚本执行完毕后将: + +- 🔄 自动返回游戏主界面 +- 📢 发送"**烹饪脚本结束**"通知 + +--- + +## 📜 更新日志 + +### v1.0 `(2025-09-21)` + +- 初始版本发布 + +--- + +**最后更新**:2025 年 9 月 21 日 +**维护者**:@呱呱 z + +> 💡 提示:建议定期检查更新以获取最佳体验和最新功能 + +--- + +如有问题或建议,欢迎反馈交流! 🐛📧@QQ:1765137214 diff --git a/repo/js/食材加工(模拟点击)/assets/Cooking.png b/repo/js/食材加工(模拟点击)/assets/Cooking.png new file mode 100644 index 000000000..94bf83d15 Binary files /dev/null and b/repo/js/食材加工(模拟点击)/assets/Cooking.png differ diff --git a/repo/js/食材加工(模拟点击)/assets/E_Dialogue.png b/repo/js/食材加工(模拟点击)/assets/E_Dialogue.png new file mode 100644 index 000000000..9114ff5bf Binary files /dev/null and b/repo/js/食材加工(模拟点击)/assets/E_Dialogue.png differ diff --git a/repo/js/食材加工(模拟点击)/assets/F_Dialogue.png b/repo/js/食材加工(模拟点击)/assets/F_Dialogue.png new file mode 100644 index 000000000..314a85f13 Binary files /dev/null and b/repo/js/食材加工(模拟点击)/assets/F_Dialogue.png differ diff --git a/repo/js/食材加工(模拟点击)/assets/pageScroll.json b/repo/js/食材加工(模拟点击)/assets/pageScroll.json new file mode 100644 index 000000000..ae0447780 --- /dev/null +++ b/repo/js/食材加工(模拟点击)/assets/pageScroll.json @@ -0,0 +1,22 @@ +{ + "macroEvents": [ + {"type": 2, "mouseX": 1200, "mouseY": 901, "time": 0}, + {"type": 2, "mouseX": 1200, "mouseY": 801, "time": 50}, + {"type": 2, "mouseX": 1200, "mouseY": 701, "time": 100}, + {"type": 2, "mouseX": 1200, "mouseY": 601, "time": 150}, + {"type": 2, "mouseX": 1200, "mouseY": 501, "time": 200}, + {"type": 2, "mouseX": 1200, "mouseY": 401, "time": 250}, + {"type": 2, "mouseX": 1200, "mouseY": 301, "time": 300}, + {"type": 2, "mouseX": 1200, "mouseY": 201, "time": 350}, + {"type": 2, "mouseX": 1200, "mouseY": 200, "mouseButton": "Left", "time": 400} + ], + "info": { + "name": "", + "description": "", + "x": 0, + "y": 0, + "width": 1920, + "height": 1080, + "recordDpi": 1 + } +} diff --git a/repo/js/食材加工(模拟点击)/assets/pageScroll2.json b/repo/js/食材加工(模拟点击)/assets/pageScroll2.json new file mode 100644 index 000000000..8ac7db36c --- /dev/null +++ b/repo/js/食材加工(模拟点击)/assets/pageScroll2.json @@ -0,0 +1,22 @@ +{ + "macroEvents": [ + {"type": 2, "mouseX": 1200, "mouseY": 901, "time": 0}, + {"type": 2, "mouseX": 1200, "mouseY": 801, "time": 50}, + {"type": 2, "mouseX": 1200, "mouseY": 701, "time": 100}, + {"type": 2, "mouseX": 1200, "mouseY": 601, "time": 150}, + {"type": 2, "mouseX": 1200, "mouseY": 501, "time": 200}, + {"type": 2, "mouseX": 1200, "mouseY": 401, "time": 250}, + {"type": 2, "mouseX": 1200, "mouseY": 301, "time": 300}, + {"type": 2, "mouseX": 1200, "mouseY": 205, "time": 350}, + {"type": 2, "mouseX": 1200, "mouseY": 204, "mouseButton": "Left", "time": 400} + ], + "info": { + "name": "", + "description": "", + "x": 0, + "y": 0, + "width": 1920, + "height": 1080, + "recordDpi": 1 + } +} diff --git a/repo/js/食材加工(模拟点击)/assets/滚轮下翻.json b/repo/js/食材加工(模拟点击)/assets/滚轮下翻.json new file mode 100644 index 000000000..cd0e99aca --- /dev/null +++ b/repo/js/食材加工(模拟点击)/assets/滚轮下翻.json @@ -0,0 +1,3 @@ +{"macroEvents":[{"type":6,"mouseX":0,"mouseY":-120,"time":0}, +{"type":6,"mouseX":0,"mouseY":0,"time":100}], +"info":{"name":"","description":"","x":0,"y":0,"width":1920,"height":1080,"recordDpi":1}} \ No newline at end of file diff --git a/repo/js/食材加工(模拟点击)/assets/璃月杂货商东升旁灶台.json b/repo/js/食材加工(模拟点击)/assets/璃月杂货商东升旁灶台.json new file mode 100644 index 000000000..50e424da9 --- /dev/null +++ b/repo/js/食材加工(模拟点击)/assets/璃月杂货商东升旁灶台.json @@ -0,0 +1,29 @@ +{ + "info": { + "name": "璃月杂货商东升旁灶台", + "type": "collect", + "author": "吉吉喵", + "version": "1.0", + "description": "", + "bgi_version": "0.42.3" + }, + "positions": [ + { + "id": 1, + "x": 267.92, + "y": -665.01, + "action": "force_tp", + "move_mode": "walk", + "type": "teleport" + }, + { + "id": 2, + "x": 255.099609375, + "y": -680.1826171875, + "type": "target", + "move_mode": "walk", + "action": "", + "action_params": "" + } + ] +} \ No newline at end of file diff --git a/repo/js/食材加工(模拟点击)/main.js b/repo/js/食材加工(模拟点击)/main.js new file mode 100644 index 000000000..f43c17de0 --- /dev/null +++ b/repo/js/食材加工(模拟点击)/main.js @@ -0,0 +1,312 @@ +(async function () { + notification.send("烹饪脚本开始"); + setGameMetrics(1920, 1080, 1.25); // 设置编写脚本环境的游戏分辨率和DPI缩放 + await genshin.returnMainUi(); // 返回主界面 + + let foodName = settings.foodName ?? 0; + let foodNum = settings.foodNum ?? 0; + let flour = settings.flour ?? false; + + + let rawmeat = settings.rawmeat ?? false; + let fish = settings.fish ?? false; + let mysteriousmeat = settings.mysteriousmeat ?? false; + + let ryeflour = settings.ryeflour ?? false; + + let cream = settings.cream ?? false; + let smokedPoultry = settings.smokedPoultry ?? false; + let butter = settings.butter ?? false; + let ham = settings.ham ?? false; + let sugar = settings.sugar ?? false; + let spice = settings.spice ?? false; + let smetana = settings.smetana ?? false; + + let crabRoe = settings.crabRoe ?? false; + let jam = settings.jam ?? false; + let cheese = settings.cheese ?? false; + let bacon = settings.bacon ?? false; + let sausage = settings.sausage ?? false; + + // 优化后的食材列表,顺序即加工顺序 + const ingredientList = [ + { key: "面粉", value: flour }, + + { key: "兽肉", value: rawmeat }, + { key: "鱼肉", value: fish }, + { key: "神秘肉", value: mysteriousmeat }, + + { key: "黑麦粉", value: ryeflour }, + + { key: "奶油", value: cream }, + { key: "熏禽肉", value: smokedPoultry }, + { key: "黄油", value: butter }, + { key: "火腿", value: ham }, + { key: "糖", value: sugar }, + { key: "香辛料", value: spice }, + { key: "酸奶油", value: smetana }, + + { key: "蟹黄", value: crabRoe }, + { key: "果酱", value: jam }, + { key: "奶酪", value: cheese }, + { key: "培根", value: bacon }, + { key: "香肠", value: sausage }, + ]; + + + // 判断是否有食材参数 + const allEmpty = ingredientList.every(item => !item.value); + if (!foodName && !foodNum && allEmpty) { + notification.send("未设置烹饪参数,跳过烹饪操作"); + await genshin.returnMainUi(); + return; + } + + await sleep(1000); + await pathingScript.runFile("assets/璃月杂货商东升旁灶台.json"); + + // 行列均从 0 开始计数 + function getItemPosition(row, col) { + const startX = 115; + const startY = 120; + const itemWidth = 124; + const itemHeight = 152; + const colGap = 22; + const rowGap = 22; + + const x = startX + col * (itemWidth + colGap) + itemWidth / 2; + const y = startY + row * (itemHeight + rowGap) + itemHeight / 2; + //const x = startX + col * (itemWidth / 2 + (colGap - 22)); + //const y = startY + row * (itemHeight / 2 + (rowGap - 22)); + + return { x, y }; + } + // 自动分配行列坐标 + const maxCols = 8; + const ingredientCoordinates = ingredientList.map((item, idx) => { + const row = Math.floor(idx / maxCols); + const col = idx % maxCols; + const { x, y } = getItemPosition(row, col); + return { ...item, x, y, row, col }; + }); + // 通用:处理食材制作步骤 + async function processIngredient(quantity, row, col, key) { + const { x, y } = getItemPosition(row, col); + if (quantity) { + log.info(`开始加工:${key}`); + click(x, y); + await sleep(1000); + + click(1690, 1015); // 制作 + await sleep(1000); + // 输入数量 + //click(965, 455); + //await sleep(1000); + //await inputText(quantity); + //拉满 + click(1190, 590); + await sleep(1000); + + click(1190, 755); // 确认 + await sleep(1000); + } + }; + // 通用:模拟输入文本 + async function inputText(text) { + for (const char of text) { + keyPress(char); + await sleep(500); + } + }; + + + /** + F交互区 +**/ + // 定义一个函数用于模拟按键操作 + async function simulateKeyOperations(key, duration) { + keyDown(key); + await sleep(duration); + keyUp(key); + await sleep(500); // 释放按键后等待 500 毫秒 + } + + // 识别 F 图标 + async function recognizeFIcon() { + const fDialogueRo = RecognitionObject.TemplateMatch( + file.ReadImageMatSync("assets/F_Dialogue.png"), + 1101, + 400, + 36, + 400 + ); + + let ra = captureGameRegion(); + let fRes = ra.find(fDialogueRo); + + if (!fRes.isExist()) { + let f_attempts = 0; // 初始化尝试次数 + while (f_attempts < 3) { // 最多尝试 3 次 + f_attempts++; + log.info(`当前尝试次数:${f_attempts}`); + + if (f_attempts === 1 || f_attempts === 2) { + // 第一次未找到 F 图标 + await simulateKeyOperations("S", 200); // 后退 200 毫秒 + log.info("执行后退操作"); + await sleep(200); + await simulateKeyOperations("W", 600); // 前进 600 毫秒 + log.info("执行前进操作"); + } else if (f_attempts === 3) { + // 第二次未找到 F 图标 + log.info("重新加载路径文件"); + const filePath = `assets/璃月杂货商东升旁灶台.json`; + log.info(`加载路径文件:${filePath}`); + await pathingScript.runFile(filePath); + await sleep(500); + } + + // 重新获取游戏区域截图 + ra = captureGameRegion(); + fRes = ra.find(fDialogueRo); + + // 打印识别结果 + log.info(`识别结果:${fRes.isExist()}`); + + // 如果识别成功,立即退出循环 + if (fRes.isExist()) { + log.info("识别成功,退出循环"); + break; + } + + await sleep(500); + } + } + + // 如果尝试次数已达上限,返回 null + if (!fRes.isExist()) { + log.error("尝试次数已达上限"); + return null; + } + + return fRes; + } + + // 识别 Cooking 图标 + async function recognizeCookingIcon(centerYF) { + const cookingRo = RecognitionObject.TemplateMatch( + file.ReadImageMatSync("assets/Cooking.png"), + 1176, + centerYF - 18, // 以 F 图标的中心,向上偏移 18 像素 + 27, // 宽度范围 + 36 // 高度范围 + ); + + let ra = captureGameRegion(); + let cookingRes = ra.find(cookingRo); + + if (cookingRes.isExist()) { + log.info("找到 灶台 图标"); + return cookingRes; + } else { + log.info("未找到 灶台 图标"); + return null; + } + } + + + + + + // 主逻辑函数 + async function main() { + // 识别 F 图标 + let fRes = await recognizeFIcon(); + if (!fRes) { + log.error("未能识别 F 图标,退出任务"); + return; + } + + // 获取 F 图标的中心点 Y 坐标 + let centerYF = Math.round(fRes.y + fRes.height / 2); + + const maxScrollAttempts = 5; // 最大滚轮操作次数限制 + let scrollAttempts = 0; + + while (scrollAttempts < maxScrollAttempts) { + // 识别 灶台 图标 + let cookingRes = await recognizeCookingIcon(centerYF); + if (cookingRes) { + // log.info("找到 灶台 图标"); + return cookingRes; // 识别成功,返回结果 + } + + // 如果未找到 Cooking 图标,执行滚轮操作 + log.info(`未找到 Cooking 图标,执行滚轮操作,当前尝试次数:${scrollAttempts + 1}`); + await keyMouseScript.runFile(`assets/滚轮下翻.json`); + await sleep(1000); + + // 重新识别 F 图标,获取最新的中心点 + fRes = await recognizeFIcon(); + if (!fRes) { + log.error("滚轮操作后,未能重新识别 F 图标,退出任务"); + return; + } + + centerYF = Math.round(fRes.y + fRes.height / 2); // 更新 F 图标的中心点 Y 坐标 + + // 增加尝试次数 + scrollAttempts++; + } + + // 如果超过最大滚轮操作次数,返回 null + log.error(`滚轮操作次数已达上限 ${maxScrollAttempts} 次,未能找到 Cooking 图标`); + return null; + } + + + try { + // 识别 Cooking 图标 + const cookingRes = await main(); + if (!cookingRes) { + log.error("未能识别 灶台 图标,退出任务"); + return; + } + + keyPress("F"); + await sleep(1000); + + + + //食材加工 + + click(1010, 50); //选择食材加工 + await sleep(1000); + click(255, 1020); //全部领取 + await sleep(1000); + click(960, 1045); //点击任意处 + await sleep(1000); + click(960, 1045); //点击任意处 + await sleep(1000); + click(960, 1045); //点击任意处 + await sleep(2000); + + // 按行列处理所有食材 + for (const ingredient of ingredientCoordinates) { + if (ingredient.value) { + await processIngredient(ingredient.value, ingredient.row, ingredient.col, ingredient.key); + } + } + + await genshin.returnMainUi(); + await sleep(1000); + keyDown("S"); + await sleep(1500); + keyUp("S"); + await sleep(1000); + } catch (error) { + log.error(`执行按键或鼠标操作时发生错误:${error.message}`); + } + + notification.send("烹饪脚本结束"); +})(); diff --git a/repo/js/食材加工(模拟点击)/manifest.json b/repo/js/食材加工(模拟点击)/manifest.json new file mode 100644 index 000000000..6fbbe1e6c --- /dev/null +++ b/repo/js/食材加工(模拟点击)/manifest.json @@ -0,0 +1,15 @@ +{ + "manifest_version": 1, + "name": "食材加工", + "version": "1.0", + "description": "根据选择加工物,自动加工食材。加工时会直接拉满加工数量。\n \n使用前请阅读“readme”文件以获取更多详细信息。", + "tags": ["食材加工", "模拟点击"], + + "authors": [ + { + "name": "呱呱z" + } + ], + "settings_ui": "settings.json", + "main": "main.js" +} diff --git a/repo/js/食材加工(模拟点击)/settings.json b/repo/js/食材加工(模拟点击)/settings.json new file mode 100644 index 000000000..b70eede41 --- /dev/null +++ b/repo/js/食材加工(模拟点击)/settings.json @@ -0,0 +1,87 @@ +[ + { + "name": "flour", + "type": "checkbox", + "label": "——选择需要加工的食材——\n\n 面粉" + }, + { + "name": "rawmeat", + "type": "checkbox", + "label": " 兽肉" + }, + { + "name": "fish", + "type": "checkbox", + "label": " 鱼肉" + }, + { + "name": "mysteriousmeat", + "type": "checkbox", + "label": " 神秘肉" + }, + { + "name": "ryeflour", + "type": "checkbox", + "label": " 黑麦粉" + }, + { + "name": "cream", + "type": "checkbox", + "label": " 奶油" + }, + { + "name": "smokedPoultry", + "type": "checkbox", + "label": " 熏禽肉" + }, + { + "name": "butter", + "type": "checkbox", + "label": " 黄油" + }, + { + "name": "ham", + "type": "checkbox", + "label": " 火腿" + }, + { + "name": "sugar", + "type": "checkbox", + "label": " 糖" + }, + { + "name": "spice", + "type": "checkbox", + "label": " 香辛料" + }, + { + "name": "smetanaNum", + "type": "checkbox", + "label": " 酸奶油" + }, + { + "name": "crabRoe", + "type": "checkbox", + "label": " 蟹黄" + }, + { + "name": "jam", + "type": "checkbox", + "label": " 果酱" + }, + { + "name": "cheese", + "type": "checkbox", + "label": " 奶酪" + }, + { + "name": "bacon", + "type": "checkbox", + "label": " 培根" + }, + { + "name": "sausage", + "type": "checkbox", + "label": " 香肠" + } +] \ No newline at end of file