From a0477d073df1f81ca3ce4dcd4c82df98da04a7f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=91=E7=AB=AF=E5=AE=A2?= <107686912+Kirito520Asuna@users.noreply.github.com> Date: Sun, 17 Aug 2025 12:41:32 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=87=E6=8D=A2=E6=B4=BB=E5=8A=A8=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=20(#1618)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 添加原神初露之源水下采集脚本(init) * feat: 初露之源添加<自体自身之塔>上部、中部、下部区域采集功能(补齐完整) * feat: 添加队伍切换功能 * feat: 添加返回主界面功能JS(方便扩展调度器使用) * feat: 添加活动页面切换功能 * docs: 添加活动切换脚本说明文档及代码优化 * docs: 更新活动切换脚本说明文档 * refactor: (用于提交PR)移除废弃的队伍切换和采集脚本-并修正切换活动页面的默认值 * refactor: 调整分页和OCR计数相关参数 --- repo/js/ActivitySwitch/READEME.md | 19 ++ .../assets/(活动页面)鼠标向上移动一格.json | 1 + .../assets/(活动页面)鼠标向下移动一格.json | 1 + repo/js/ActivitySwitch/main.js | 232 ++++++++++++++++++ repo/js/ActivitySwitch/manifest.json | 14 ++ repo/js/ActivitySwitch/settings.json | 69 ++++++ 6 files changed, 336 insertions(+) create mode 100644 repo/js/ActivitySwitch/READEME.md create mode 100644 repo/js/ActivitySwitch/assets/(活动页面)鼠标向上移动一格.json create mode 100644 repo/js/ActivitySwitch/assets/(活动页面)鼠标向下移动一格.json create mode 100644 repo/js/ActivitySwitch/main.js create mode 100644 repo/js/ActivitySwitch/manifest.json create mode 100644 repo/js/ActivitySwitch/settings.json diff --git a/repo/js/ActivitySwitch/READEME.md b/repo/js/ActivitySwitch/READEME.md new file mode 100644 index 000000000..a43a6e2fc --- /dev/null +++ b/repo/js/ActivitySwitch/READEME.md @@ -0,0 +1,19 @@ +脚本名称:切换活动页面 + +功能描述: 打开活动页面、鼠标上滑并根据活动名称选择活动的脚本 (需要处于主界面) + + +## 核心功能 + +1. 返回主界面,打开活动页面,切换活动页面 +2. 可设置 启动返回主界面(建议启用), 活动名称,最大识别次数(默认2次,不包含首次识别),滑多少次数到顶(默认6次,建议设大点) +3. 其他料理获取:除了烹饪以外的部分料理的获取[仅有数据,未实装] + +## 注意事项 + +1. 请尽量确保原神分辨率是1920x1080(虽然已兼容其他分辨率,但建议使用1920x1080,其他分辨率未测试过) + +## 其它 + +作者:Kirito520Asuna +脚本反馈邮箱:doutianmianxia@qq.com \ No newline at end of file diff --git a/repo/js/ActivitySwitch/assets/(活动页面)鼠标向上移动一格.json b/repo/js/ActivitySwitch/assets/(活动页面)鼠标向上移动一格.json new file mode 100644 index 000000000..0845b3095 --- /dev/null +++ b/repo/js/ActivitySwitch/assets/(活动页面)鼠标向上移动一格.json @@ -0,0 +1 @@ +{"macroEvents":[{"type":2,"mouseX":699,"mouseY":589,"time":875},{"type":2,"mouseX":699,"mouseY":584,"time":921},{"type":2,"mouseX":700,"mouseY":579,"time":953},{"type":2,"mouseX":701,"mouseY":576,"time":984},{"type":2,"mouseX":701,"mouseY":569,"time":1031},{"type":2,"mouseX":702,"mouseY":561,"time":1062},{"type":2,"mouseX":703,"mouseY":555,"time":1093},{"type":2,"mouseX":704,"mouseY":554,"time":1171},{"type":2,"mouseX":704,"mouseY":545,"time":1203},{"type":2,"mouseX":705,"mouseY":541,"time":1234},{"type":2,"mouseX":706,"mouseY":539,"time":1265},{"type":2,"mouseX":706,"mouseY":534,"time":1312},{"type":2,"mouseX":706,"mouseY":527,"time":1343},{"type":2,"mouseX":706,"mouseY":521,"time":1375},{"type":2,"mouseX":706,"mouseY":517,"time":1421},{"type":2,"mouseX":707,"mouseY":511,"time":1468},{"type":2,"mouseX":707,"mouseY":508,"time":1500}],"info":{"name":"","description":"","x":342,"y":126,"width":1920,"height":1080,"recordDpi":1}} \ No newline at end of file diff --git a/repo/js/ActivitySwitch/assets/(活动页面)鼠标向下移动一格.json b/repo/js/ActivitySwitch/assets/(活动页面)鼠标向下移动一格.json new file mode 100644 index 000000000..18eea3f48 --- /dev/null +++ b/repo/js/ActivitySwitch/assets/(活动页面)鼠标向下移动一格.json @@ -0,0 +1 @@ +{"macroEvents":[{"type":2,"mouseX":699,"mouseY":599,"time":1125},{"type":2,"mouseX":699,"mouseY":600,"time":1157},{"type":2,"mouseX":699,"mouseY":603,"time":1188},{"type":2,"mouseX":699,"mouseY":607,"time":1235},{"type":2,"mouseX":699,"mouseY":608,"time":1328},{"type":2,"mouseX":699,"mouseY":613,"time":1360},{"type":2,"mouseX":699,"mouseY":618,"time":1391},{"type":2,"mouseX":699,"mouseY":629,"time":1422},{"type":2,"mouseX":699,"mouseY":635,"time":1453},{"type":2,"mouseX":699,"mouseY":644,"time":1485},{"type":2,"mouseX":699,"mouseY":647,"time":1516},{"type":2,"mouseX":699,"mouseY":652,"time":1547},{"type":2,"mouseX":699,"mouseY":653,"time":1594},{"type":2,"mouseX":699,"mouseY":658,"time":1641},{"type":2,"mouseX":698,"mouseY":666,"time":1672},{"type":2,"mouseX":698,"mouseY":669,"time":1703},{"type":2,"mouseX":697,"mouseY":670,"time":1735},{"type":2,"mouseX":697,"mouseY":675,"time":1766},{"type":2,"mouseX":697,"mouseY":679,"time":1797},{"type":2,"mouseX":696,"mouseY":686,"time":1828},{"type":2,"mouseX":696,"mouseY":687,"time":1860},{"type":2,"mouseX":696,"mouseY":689,"time":1922},{"type":2,"mouseX":696,"mouseY":692,"time":1985},{"type":2,"mouseX":696,"mouseY":693,"time":2016}],"info":{"name":"","description":"","x":342,"y":126,"width":1920,"height":1080,"recordDpi":1}} \ No newline at end of file diff --git a/repo/js/ActivitySwitch/main.js b/repo/js/ActivitySwitch/main.js new file mode 100644 index 000000000..fa1ab36d3 --- /dev/null +++ b/repo/js/ActivitySwitch/main.js @@ -0,0 +1,232 @@ +// 切换到活动页面 +async function switchToActivityPage(activityName, activityKey, maxOcrCount) { + try { + //标记点击成功 + let switchToActivity = false; + // 记录日志 + log.info(`正在尝试切换到活动页面: ${activityName}`); + + // 检查游戏窗口信息 + const gameWidth = genshin.width; + const gameHeight = genshin.height; + if (!gameWidth || !gameHeight) { + notification.error('无法获取游戏窗口信息,请确保原神正在运行!'); + return; + } + log.info(`按下 ${activityKey}`) + // 打开活动页面 + await keyDown(activityKey); + await sleep(1000); // 等待活动页面加载 + await keyUp(activityKey); + + await sleep(1000); + let ocr_x = parseInt(100 * gameWidth / 1920 + '') + let ocr_y = parseInt(200 * gameHeight / 1080 + '') + let ocr_width = parseInt(450 * gameWidth / 1920 + '') + let ocr_hight = parseInt(600 * gameHeight / 1080 + '') + log.info(`参考值(1920*1080):{"x": 100, "y": 200, "width": 450, "height": 600}`) + let ocrRegion = { + "x": ocr_x, + "y": ocr_y, + "width": ocr_width, + "height": ocr_hight + } + log.info(`实际值(${gameWidth}*${gameHeight}):{"x": ${ocr_x}, "y": ${ocr_y}, "width": ${ocr_width}, "height": ${ocr_hight}}`) + let activity = await lookForClickActivity(ocrRegion, activityName); + + switchToActivity = activity.switchToActivity + if (!switchToActivity) { + //第一页没有找到活动 + //第一次不记录(存在不标准从第二次<标准化后>开始记录) + let lastActivityNameOne = null//记录最后一个活动名称第一次 + let lastActivityNameTwo = null//记录最后一个活动名称第二次 + //俩个名称一致时说明活动识别完了 + let isOne = true; + let index = 1;//记录滑动几次 + while (lastActivityNameOne !== lastActivityNameTwo || (isOne && lastActivityNameOne === null && lastActivityNameTwo === null)) { + isOne = false + await sleep(1000) + if (index === 1) { + //滑动 + await slideToTop(activity.act_x1, activity.act_y1); + log.info('滑动到顶') + } else { + await swipeOnePageDown(activity.act_x1, activity.act_y1); + log.info('滑动一页') + } + await sleep(1000) + let clickActivity = await lookForClickActivity(ocrRegion, activityName); + switchToActivity = clickActivity.switchToActivity + + if (index % 2 !== 0) { + lastActivityNameOne = clickActivity.lastActivityName + } else { + lastActivityNameTwo = clickActivity.lastActivityName + } + log.info(`滑动次数:${index}`) + if (!switchToActivity && maxOcrCount <= index) { + log.error(`已识别:${index}次,已超出最大次数:${maxOcrCount}`) + break; + } + index += 1 + if (switchToActivity) { + //点击成功 + break; + } + } + } + if (!switchToActivity) { + notification.error(`未找到活动: ${activityName}`); + } + } catch (error) { + log.error(`切换活动页面失败: ${error.message}`); + notification.error(`错误: ${error.message}`); + } +} + + +/** + * 移动向上鼠标 + * @param height + * @returns {Promise} + */ +async function moveMouseUp(x, y, height) { + for (let i = 0; i < height; i++) { + await moveMouseTo(x, y); + await sleep(1000) + await leftButtonDown(); + await keyMouseScript.runFile(`assets/(活动页面)鼠标向上移动一格.json`) + await leftButtonUp(); + } +} + +/** + * 移动向下鼠标 + * @param height + * @returns {Promise} + */ +async function moveMouseDown(x, y, height) { + for (let i = 0; i < height; i++) { + await moveMouseTo(x, y); + await sleep(1000) + await leftButtonDown(); + await keyMouseScript.runFile(`assets/(活动页面)鼠标向下移动一格.json`) + await leftButtonUp(); + } +} + +/** + * 自定义 个活动/一页 ==> 滑动多少次 + * @returns {Promise} + */ +async function onePage() { + let onePage = 3 + if (settings.onePage && settings.onePage !== '默认') { + onePage = parseInt(settings.onePage) + } + return onePage +} + +/** + * 向下滑动一页(6次为一页) + */ +async function swipeOnePageDown(x, y) { + let count = await onePage(); + let move_height = parseInt(count * genshin.height / 1080 + '') + await moveMouseUp(x, y, move_height) +} + +/** + * 滑动到顶次数 + * @returns {Promise>} + */ +async function toTopPage() { + let toTopPage = 4 + if (settings.toTopPage && settings.toTopPage !== '默认') { + toTopPage = parseInt(settings.toTopPage) + } + return toTopPage +} + +/** + * 滑动到顶 + * @param act_x1 + * @param act_y1 + */ +async function slideToTop(act_x1, act_y1) { + let count = await toTopPage(); + let move_height = parseInt(count * genshin.height / 1080 + '') + await moveMouseDown(act_x1, act_y1, move_height) +} + +/** + * 查找点击活动 + * @param ocrRegion + * @param activityName + * @returns {Promise} + */ +async function lookForClickActivity(ocrRegion, activityName) { + let switchToActivity = false + let captureRegion = captureGameRegion(); + const ocrObject = RecognitionObject.Ocr(ocrRegion.x, ocrRegion.y, ocrRegion.width, ocrRegion.height); + // ocrObject.threshold = 1.0; + let resList = captureRegion.findMulti(ocrObject); + let firstRes = null + let lastRes = null + for (let res of resList) { + // log.info(`res:${res}`) + // log.info(`识别结果: ${res.text}, 原始坐标: x=${res.x}, y=${res.y}`); + if (res.text.includes(activityName)) { + log.info(`找到活动: ${activityName}`); + // 模拟点击活动 + await sleep(1000) + await click(res.x, res.y); + switchToActivity = true; + break; + } + if (firstRes === null) { + firstRes = res + } + lastRes = res + } + let resObject = { + "switchToActivity": switchToActivity,//记录是否点击成功 + "act_x1": null,//第一个活动的x坐标 + "act_y1": null,//第一个活动的y坐标 + "lastActivityName": null//记录最后一个活动名称 点击成功就为空 + } + if (firstRes !== null) { + resObject.act_x1 = firstRes.x + resObject.act_y1 = firstRes.y + } + if (!switchToActivity && (lastRes !== null)) { + // log.info(`test--length-1`) + resObject.lastActivityName = lastRes.text + } + return resObject +} + +(async function () { + setGameMetrics(1920, 1080, 2); // 设置游戏窗口大小和DPI + // await swipeOnePageDown(300, 240) + if (settings.enable) { + //返回主界面 + log.info('返回主界面'); + genshin.returnMainUi(); + } + await sleep(1000); + const activityName = settings.activityName; + let activityKey = settings.activityKey; + let maxOcrCount = 3; + if (settings.maxOcrCount && settings.maxOcrCount !== '默认') { + maxOcrCount = parseInt(settings.maxOcrCount) + } + if (!activityName) { + notification.error('未配置活动名称,请设置'); + return; + } + if (!activityKey) { + activityKey = 'F5'; + } + await switchToActivityPage(activityName, activityKey, maxOcrCount); +})(); diff --git a/repo/js/ActivitySwitch/manifest.json b/repo/js/ActivitySwitch/manifest.json new file mode 100644 index 000000000..7b997c836 --- /dev/null +++ b/repo/js/ActivitySwitch/manifest.json @@ -0,0 +1,14 @@ +{ + "name": "切换活动页面", + "version": "1.0.1", + "description": "(需要处于主界面)一个通过 F5 打开活动页面、鼠标上滑并根据活动名称选择活动的脚本", + "settings_ui": "settings.json", + "main": "main.js", + "authors": [ + { + "name": "Kirito520Asuna", + "link": "https://github.com/Kirito520Asuna" + } + ], + "dependencies": [] +} \ No newline at end of file diff --git a/repo/js/ActivitySwitch/settings.json b/repo/js/ActivitySwitch/settings.json new file mode 100644 index 000000000..735d48d36 --- /dev/null +++ b/repo/js/ActivitySwitch/settings.json @@ -0,0 +1,69 @@ +[ + { + "name": "enable", + "type": "checkbox", + "label": "启用先返回主界面后执行切换", + "default": true + }, + { + "name": "activityName", + "type": "input-text", + "label": "活动名称" + }, + { + "name": "maxOcrCount", + "type": "select", + "label": "最大识别次数(默认3次,理论上3次就够了,不包含首次识别)", + "options": [ + "默认", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + ] + }, + { + "name": "toTopPage", + "type": "select", + "label": "滑多少次数到顶(默认4次),建议设大点", + "options": [ + "默认", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + ] + }, + { + "name": "onePage", + "type": "select", + "label": "设置一页多少次(默认3次),建议设置到合适识别即可", + "options": [ + "默认", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + ] + }, + { + "name": "activityKey", + "type": "input-text", + "label": "打开活动页面按键(不填,默认:F5)" + } +]