diff --git a/repo/js/WeeklyThousandStarRealm/README.md b/repo/js/WeeklyThousandStarRealm/README.md index d10ccc890..532e493fb 100644 --- a/repo/js/WeeklyThousandStarRealm/README.md +++ b/repo/js/WeeklyThousandStarRealm/README.md @@ -8,24 +8,31 @@ ## ❗ 使用前重要说明(免责声明) -本脚本依赖“**删除第一个奇域地图存档**”来实现重复获取成就经验。 +本脚本依赖“**删除奇域地图存档**”来实现重复获取成就经验。 这意味着: -- 当脚本执行删除存档时,如果 **第一个存档不是你正在刷的地图**,可能会误删你正常游玩的关卡数据。 +- 当脚本执行删除存档时,可能会误删你正常游玩的关卡数据。 若你完全理解并接受此风险,请在脚本的 *自定义 JS 配置* 中手动勾选 `我已阅读说明中的免责声明` 才可继续执行脚本。 请务必确认你能承担潜在损失后再继续使用。 --- +## 🔥 焚诀 + +自己发布的千星奇域的地图也可以用来增长经验,但是并不需要发布成功,仅需要点击一下发布再预览详情,即可在弹窗中进行收藏。 +这就意味着可以自行制作秒刷图,然后“发布”进行收藏,在收藏中使用自己实际上并未真正发布的地图进行秒刷。 +最新版脚本进行了重构,优化了点击速度,秒刷图一周刷完仅需8分45秒。 +地图制作请自行学习。 + ## 🌟 功能特点 -- 🔁 自动重复通关指定奇域地图 -- 🧹 自动删除存档,实现成就经验可重复获取 -- 📅 自动监测每周经验上限,到达后自动停止 -- 🏞️ 完成后自动返回提瓦特大陆,不影响其他自动化脚本 -- ⭐ 可刷收藏地图,支持自定义地图名称 +* 自动重复通关指定奇域地图 +* 自动删除存档,实现成就经验可重复获取 +* 自动监测每周经验上限,到达后自动停止 +* 完成后自动返回提瓦特大陆,不影响其他自动化脚本 +* 可刷收藏地图,支持自定义地图名称 --- @@ -47,9 +54,10 @@ ## ❗ 注意事项 - 游戏窗口需保持 **16:9** 的宽高比例,否则可能影响图像识别。 -- `singleExp` 请填写正确,否则脚本的剩余次数计算会不准确。 +- `每次通关可获得的经验值` 请填写正确,否则脚本的剩余次数计算会不准确。 - 若默认地图下架,请手动输入可游玩的地图号。 -- 勾选收藏模式后,请确保 `starRoomName` 填写正确地图名称。 +- 勾选收藏模式后,请确保 `收藏模式所使用的地图名称` 填写正确地图名称。 - 成就模式和收藏模式可以同时开启,但请确保地图符合对应要求。 +- 若出现红色报错,提示文件不存在,无需在意,不会造成问题。 --- diff --git a/repo/js/WeeklyThousandStarRealm/data/store.json b/repo/js/WeeklyThousandStarRealm/data/store.json deleted file mode 100644 index 9aed3ad2a..000000000 --- a/repo/js/WeeklyThousandStarRealm/data/store.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "weekMaxExp": 4000, - "singleExp": 270, - "weekTotal": 15 -} \ No newline at end of file diff --git a/repo/js/WeeklyThousandStarRealm/main.js b/repo/js/WeeklyThousandStarRealm/main.js index 5f8db676f..857dc2a0d 100644 --- a/repo/js/WeeklyThousandStarRealm/main.js +++ b/repo/js/WeeklyThousandStarRealm/main.js @@ -1,5 +1,11 @@ -const attempts = 20; // 最大尝试次数 -const interval = 1000; // 每次间隔 ms +import { + getImgMat, + findText, + findTextAndClick, + findImgAndClick, + waitUntilTextAppear +} from "../../../packages/utils/tool"; + const duration = 1000; // 默认点击等待延时 const storePath = "data/store.json" @@ -14,11 +20,6 @@ const weekMaxExp = Number(settings.weekMaxExp || "4000"); const singleExp = Number(settings.singleExp || "270"); let weekTotal = initWeekTotal(); -// 获取图片资源 -function getImgMat(path) { - return file.readImageMatSync('assets/' + path + '.png'); -} - // 读取存档 function loadWeekData() { try { @@ -106,87 +107,12 @@ function decreaseWeekTotal() { weekTotal = stored.weekTotal; } -// 查找文本 -async function findText(text, x, y, w, h, textAttempts = attempts) { - const searchText = text.toLowerCase(); - - for (let i = 0; i < textAttempts; i++) { - const captureRegion = captureGameRegion(); - const ro = RecognitionObject.ocr(x, y, w, h); - const results = captureRegion.findMulti(ro); - captureRegion.dispose(); - - for (let j = 0; j < results.count; j++) { - const region = results[j]; - if (region.isExist() && region.text.toLowerCase().includes(searchText)) { - return region; - } - } - - await sleep(interval); - } - - return null; -} - // 升级特殊界面点击 async function findAndClickWhiteSpaceNext() { - const captureRegion = captureGameRegion(); - const ro = RecognitionObject.ocr(610, 950, 700, 60); - const results = captureRegion.findMulti(ro); - captureRegion.dispose(); - - for (let j = 0; j < results.count; j++) { - const region = results[j]; - if (region.isExist()) { - const text = region.text.toLowerCase(); - if (text.includes("点击") && text.includes("继续")) { - await sleep(duration); - click(610, 950); - } - } - } -} - -// 查找图片 -async function findImage(imgMat, x, y, w, h, imgAttempts = attempts) { - const searchImg = RecognitionObject.TemplateMatch(imgMat, x, y, w, h); - - for (let i = 0; i < imgAttempts; i++) { - const captureRegion = captureGameRegion(); - const result = captureRegion.find(searchImg); - captureRegion.dispose(); - - if (result.isExist()) { - return result; - } - - await sleep(interval); - } - - return null; -} - -// 查找文本并点击 -async function findTextAndClick(text, x, y, w, h, textAttempts = attempts) { - const target = await findText(text, x, y, w, h, textAttempts); - if (target) { + const result = await findText(["点击", "继续"],610, 950, 700, 60); + if (result) { await sleep(duration); - target.click(); - } else { - log.error("文本{text}查找失败", text); - } -} - -// 查找图片并点击 -async function findImageAndClick(path, x, y, w, h, imgAttempts = attempts) { - const imgMat = getImgMat(path); - const target = await findImage(imgMat, x, y, w, h, imgAttempts); - if (target) { - await sleep(duration); - target.click(); - } else { - log.error("图标{path}查找失败", path); + click(610, 950); } } @@ -198,7 +124,7 @@ async function findSaveInList(keyword) { const region = await findText( keyword, 200, 250, 1500, 700, - 1 + 3 ); if (region) { @@ -227,8 +153,8 @@ async function deleteSource() { keyPress("VK_B"); await sleep(duration); - await findTextAndClick("管理关卡", 960, 0, 960, 100); - await findTextAndClick("管理", 960, 980, 960, 100); + await findTextAndClick("管理关卡", 960, 0, 960, 100, 50, 50); + await findTextAndClick("管理", 960, 980, 960, 100, 50, 50); // 查找目标存档 const saveRegion = await findSaveInList(starRoomName); @@ -242,12 +168,13 @@ async function deleteSource() { const sy = saveRegion.y - 30; await sleep(300); - await findImageAndClick("check_box", 0, sy, 1480, saveRegion.height + 70); + const check_box = getImgMat("assets/check_box.png"); + await findImgAndClick(check_box, 0, sy, 1480, saveRegion.height + 70, 2000); // 删除 await sleep(duration); - await findTextAndClick("删除", 960, 980, 960, 100); - await findTextAndClick("确认", 960, 600, 960, 400); - await findTextAndClick("确认", 960, 600, 960, 400); + await findTextAndClick("删除", 960, 980, 960, 100, 50, 100); + await findTextAndClick("确认", 960, 600, 960, 400, 50, 100); + await findTextAndClick("确认", 960, 600, 960, 400, 50, 100); log.info("关卡存档删除完成"); await sleep(duration); @@ -257,29 +184,48 @@ async function deleteSource() { // 进入千星奇域的全部奇域页面 async function enterSourcePage() { // 1. 检测是否在房间内,在则退出 - const inRoom = await findText("房间", 1500, 0, 420, 500, 5); + const inRoom = await findText("房间", 1500, 0, 420, 500, 5, 100); if (inRoom) { keyPress("VK_P"); - await sleep(duration); - await findImageAndClick("exit_room", 960, 0, 960, 540); + const exit_room = getImgMat("assets/exit_room.png"); + await waitUntilTextAppear( + "确认", + async () => { + await findImgAndClick(exit_room, 960, 0, 960, 540, 500); + }, + 960, + 600, + 960, + 400, + 10 + ); await findTextAndClick("确认", 960, 600, 960, 400); await genshin.returnMainUi(); keyPress("VK_F6"); } else { keyPress("VK_F6"); } - await sleep(duration); } // 进入千星奇域的收藏奇域页面 async function enterStarSourcePage() { // 1. 检测是否在房间内,在则退出 - const inRoom = await findText("房间", 1500, 0, 420, 500, 5); + const inRoom = await findText("房间", 1500, 0, 420, 500, 5, 100); if (inRoom) { keyPress("VK_P"); - await sleep(duration); - await findImageAndClick("exit_room", 960, 0, 960, 540); + const exit_room = getImgMat("assets/exit_room.png"); + await waitUntilTextAppear( + "确认", + async () => { + await findImgAndClick(exit_room, 960, 0, 960, 540, 500); + }, + 960, + 600, + 960, + 400, + 100 + ); await findTextAndClick("确认", 960, 600, 960, 400); await genshin.returnMainUi(); keyPress("VK_B"); @@ -302,20 +248,9 @@ async function createMap() { await sleep(duration); click(355, 365); await sleep(duration); - while (true) { - const result = await findText("房间", 960, 100, 960, 200, 2); - if (result) { - await sleep(duration); - result.click(); - await sleep(duration); - break; - } else { - const result2 = await findText("大厅", 960, 600, 960, 400, 2); - if (result2) { - result2.click(); - await sleep(duration); - } - } + const result = await findTextAndClick("房间",960, 100, 960, 200, 2); + if (!result) { + await findTextAndClick("大厅", 960, 600, 960, 400, 2); } await findText("开始游戏", 960, 540, 960, 540); click(770, 275); @@ -326,25 +261,16 @@ async function createMap() { async function createStarMap() { await findTextAndClick("搜索", 0, 0, 1920, 120); inputText(roomID); - await sleep(1000); + await sleep(500); await findTextAndClick("搜索", 0, 0, 1920, 120); await sleep(duration); click(420, 830); await sleep(duration); - while (true) { - const result = await findText("房间", 960, 100, 960, 200, 2); - if (result) { - await sleep(duration); - result.click(); - await sleep(duration); - break; - } else { - const result2 = await findText("大厅", 960, 600, 960, 400, 2); - if (result2) { - result2.click(); - await sleep(duration); - } - } + const result = await findTextAndClick("房间",960, 100, 960, 200, 2); + if (!result) { + await findTextAndClick("大厅", 960, 600, 960, 400, 2); + await waitUntilTextAppear("房间", () => {},960, 100, 960, 200, 50, 1000); + await findTextAndClick("房间",960, 100, 960, 200); } await findText("开始游戏", 960, 540, 960, 540); click(770, 275); @@ -363,49 +289,30 @@ async function playMap() { await createMap(); } - while (true) { - await sleep(duration); - const result = await findText("开始游戏", 960, 540, 960, 540, 5); - if (result) { - await sleep(duration); - result.click(); - log.info("开始执行第{i}/{total}次奇域挑战", 1, total); - await sleep(duration); - } else { - await sleep(duration); - break; - } - } + await findTextAndClick("开始游戏", 960, 540, 960, 540, 5, 50, 50); + log.info("开始执行第{i}/{total}次奇域挑战", 1, total); let firstOutputCount = 0; - while (true) { - const whiteText = await findText("空白", 610, 900, 700, 100, 1); - if (whiteText) { - await sleep(duration); - click(610, 950); - } - - const result = await findText("返回大厅", 960, 540, 960, 540, 1); - if (result) { - await sleep(duration); - result.click(); - await sleep(duration); - if (!useFixedAttempts) { - decreaseWeekTotal(); - } - log.info("本次关卡结束"); - break; - } else { - const inRoom = await findText("房间", 1500, 0, 420, 500, 1); - if (inRoom) { - break; - } + await waitUntilTextAppear( + "返回大厅", + async () => { + await findAndClickWhiteSpaceNext(); if (firstOutputCount % 16 === 0) { log.info("等待本次关卡结束..."); } firstOutputCount++; - await sleep(interval); - } + }, + 960, + 540, + 960, + 540, + 500, + 2000 + ); + await findTextAndClick("返回大厅", 960, 540, 960, 540); + if (!useFixedAttempts) { + decreaseWeekTotal(); } + log.info("本次关卡结束"); await deleteSource(); @@ -415,42 +322,28 @@ async function playMap() { await sleep(duration); keyPress("VK_P"); await sleep(duration); - while (true) { - const result = await findText("开始游戏", 960, 540, 960, 540, 1); - if (result) { - await sleep(duration); - result.click(); - log.info("开始执行第{i}/{total}次奇域挑战", i + 1, total); - await sleep(duration); - break; - } else { - await sleep(duration); - } - } + await findTextAndClick("开始游戏", 960, 540, 960, 540, 20, 50, 50); + log.info("开始执行第{i}/{total}次奇域挑战", i + 1, total); let outputCount = 0; - while (true) { - await findAndClickWhiteSpaceNext(); - const result = await findText("返回大厅", 960, 540, 960, 540, 1); - if (result) { - await sleep(duration); - result.click(); - await sleep(duration); - if (!useFixedAttempts) { - decreaseWeekTotal(); - } - log.info("本次关卡结束"); - break; - } else { - const inRoom = await findText("房间", 1500, 0, 420, 500, 1); - if (inRoom) { - break; - } - if (outputCount % 10 === 0) { + await waitUntilTextAppear( + "返回大厅", + async () => { + await findAndClickWhiteSpaceNext(); + if (outputCount % 16 === 0) { log.info("等待本次关卡结束..."); } outputCount++; - await sleep(interval); - } + }, + 960, + 540, + 960, + 540, + 500, + 2000 + ); + await findTextAndClick("返回大厅", 960, 540, 960, 540); + if (!useFixedAttempts) { + decreaseWeekTotal(); } await deleteSource(); } diff --git a/repo/js/WeeklyThousandStarRealm/manifest.json b/repo/js/WeeklyThousandStarRealm/manifest.json index 37da30a38..a57832079 100644 --- a/repo/js/WeeklyThousandStarRealm/manifest.json +++ b/repo/js/WeeklyThousandStarRealm/manifest.json @@ -1,9 +1,9 @@ { "manifest_version": 1, "name": "千星奇域每周成就经验刷取", - "version": "2.7", - "bgi_version": "0.54.0", - "description": "无需自己找图,可用于利用成就高经验值刷取经验,默认配置每周刷满需要24分钟", + "version": "3.0", + "bgi_version": "0.57.0", + "description": "无需自己找图,可用于利用成就高经验值刷取经验,默认配置每周刷满需要22分钟,秒刷图仅需9分钟", "authors": [ { "name": "躁动的氨气",