From 793223246e11400602d945cbe6a7c6305ef442bb Mon Sep 17 00:00:00 2001 From: Tool_tingsu <143606015+Tooltingsu@users.noreply.github.com> Date: Thu, 11 Sep 2025 23:06:12 +0800 Subject: [PATCH] 1 (#1865) --- .../Assets/characterimage/班尼特02.png | Bin 0 -> 10656 bytes repo/js/AutoSwitchRoles/main.js | 511 ++++++++++-------- 2 files changed, 297 insertions(+), 214 deletions(-) create mode 100644 repo/js/AutoSwitchRoles/Assets/characterimage/班尼特02.png diff --git a/repo/js/AutoSwitchRoles/Assets/characterimage/班尼特02.png b/repo/js/AutoSwitchRoles/Assets/characterimage/班尼特02.png new file mode 100644 index 0000000000000000000000000000000000000000..bebbb87eb2054a19e7e1c43bcd275a95f6735386 GIT binary patch literal 10656 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 literal 0 HcmV?d00001 diff --git a/repo/js/AutoSwitchRoles/main.js b/repo/js/AutoSwitchRoles/main.js index 33edeb4c7..05994b455 100644 --- a/repo/js/AutoSwitchRoles/main.js +++ b/repo/js/AutoSwitchRoles/main.js @@ -35,10 +35,10 @@ function readAliases() { setGameMetrics(1920, 1080, 1); // 返回主界面 await genshin.returnMainUi(); - //切换配对 - if (settings.switchPartyName) { - await genshin.switchParty(settings.switchPartyName); - } + //切换配对 + if (settings.switchPartyName) { + await genshin.switchParty(settings.switchPartyName); + } const option = settings.option; if (option === '推荐-非快速配对模式 @Tool_tingsu') { @@ -50,6 +50,9 @@ function readAliases() { [1462, 538] ]; + // 获取初始角色数组 + const initialAvatars = getAvatars(); + // 读取别名 const aliases = readAliases(); @@ -58,15 +61,21 @@ function readAliases() { settings.position2, settings.position3, settings.position4 - ].map(input => { - if (input && input.trim()!== "") { + ].map((input, index) => { + if (input && input.trim() !== "") { const actualName = aliases[input] || input; log.info(`设置对应号位为【${input}】,切换角色为【${actualName}】`); + // 替换初始数组对应位置 + initialAvatars[index] = actualName; return actualName; } return null; }); + // 目标角色数组(替换后的初始数组) + const targetAvatars = [...initialAvatars]; + log.info(`目标角色: [${targetAvatars}]`); + // 识别对象定义 const roTeamConfig = RecognitionObject.TemplateMatch(file.ReadImageMatSync(`Assets/RecognitionObject/队伍配置.png`), 0, 0, 1920, 1080); const roReplace = RecognitionObject.TemplateMatch(file.ReadImageMatSync(`Assets/RecognitionObject/更换.png`), 0, 0, 1920, 1080); @@ -74,9 +83,11 @@ function readAliases() { let openPairingTries = 0; let totalOpenPairingTries = 0; + let retryCount = 0; // 重试计数器 + let switchSuccess = false; // 在进入角色切换逻辑前进行检测,如果所有角色设置均为空则直接退出 - if (positionSettings.every((item) =>!item)) { + if (positionSettings.every((item) => !item)) { log.info("未设置任何角色,跳过切换队伍步骤"); await genshin.returnMainUi(); return; @@ -104,97 +115,130 @@ function readAliases() { } } - if (!(await openPairingInterface())) { + // 角色切换逻辑封装 + async function switchCharacters() { + if (!(await openPairingInterface())) { + return false; + } + + for (let i = 0; i < positionSettings.length; i++) { + let rolenum = i + 1; + const selectedCharacter = positionSettings[i]; + if (!selectedCharacter) { + log.info(`未设置${rolenum}号位角色,跳过`); + continue; + } + const [x, y] = positionCoordinates[i]; + click(x, y); + log.info(`开始设置${rolenum}号位角色`); + await sleep(1000); + let characterFound = false; + let pageTries = 0; + + // 最多尝试滚动页面20次 + while (pageTries < 20) { + // 尝试识别所有可能的角色文件名 + for (let num = 1; ; num++) { + const paddedNum = num.toString().padStart(2, "0"); + const characterFileName = `${selectedCharacter}${paddedNum}`; + try { + const characterRo = RecognitionObject.TemplateMatch( + file.ReadImageMatSync(`Assets/characterimage/${characterFileName}.png`), + 0, 0, 1920, 1080 + ); + const characterResult = captureGameRegion().find(characterRo); + if (characterResult.isExist()) { + log.info(`已找到角色【${selectedCharacter}】`); + characterResult.click(); + await sleep(500); + characterFound = true; + break; + } + } catch (error) { + // 文件不存在,跳出循环 + break; + } + } + + if (characterFound) { + break; + } + + // 滚动页面 + if (pageTries < 15) { + log.info("当前页面没有目标角色,滚动页面"); + await scrollPage(200); + } + pageTries++; + } + + if (!characterFound) { + log.error(`未找到【${selectedCharacter}】`); + continue; + } + + // 识别"更换"或"加入"按钮 + const replaceResult = captureGameRegion().find(roReplace); + const joinResult = captureGameRegion().find(roJoin); + + if (replaceResult.isExist() || joinResult.isExist()) { + await sleep(300); + if (replaceResult.isExist()){ + replaceResult.click(); + } else { + joinResult.click(); + } + keyPress("VK_LBUTTON"); + await sleep(500); + } else { + log.error(`该角色已在队伍中,无需切换`); + await sleep(300); + keyPress("VK_ESCAPE"); + await sleep(500); + } + await sleep(500); + } + return true; + } + + // 执行切换并检查结果 + while (retryCount < 2) { // 最多尝试2次(初始1次+重试1次) + if (!await switchCharacters()) { + log.error("角色切换过程失败"); + return; + } + + // 返回主界面后获取最终角色数组 + await genshin.returnMainUi(); + const finalAvatars = getAvatars(); + + // 比较数组是否完全一致 + const arraysEqual = targetAvatars.length === finalAvatars.length && + targetAvatars.every((val, idx) => val === finalAvatars[idx]); + + if (arraysEqual) { + log.info("角色切换成功"); + switchSuccess = true; + break; + } else { + log.warn("角色不匹配,准备重试..."); + retryCount++; + if (retryCount >= 2) { + log.error("角色切换失败"); + return; + } + // 重新打开配对界面准备重试 + await genshin.returnMainUi(); + } + } + + if (!switchSuccess) { + log.error("角色切换失败"); return; } - // 角色切换逻辑 - for (let i = 0; i < positionSettings.length; i++) { - let rolenum = i + 1; - const selectedCharacter = positionSettings[i]; - if (!selectedCharacter) { - log.info(`未设置${rolenum}号位角色,跳过`); - continue; - } - const [x, y] = positionCoordinates[i]; - click(x, y); - log.info(`开始设置${rolenum}号位角色`); - await sleep(1000); - let characterFound = false; - let pageTries = 0; - - // 最多尝试滚动页面20次 - while (pageTries < 20) { - // 尝试识别所有可能的角色文件名 - for (let num = 1; ; num++) { - const paddedNum = num.toString().padStart(2, "0"); - const characterFileName = `${selectedCharacter}${paddedNum}`; - try { - const characterRo = RecognitionObject.TemplateMatch( - file.ReadImageMatSync(`Assets/characterimage/${characterFileName}.png`), - 0, - 0, - 1920, - 1080 - ); - const characterResult = captureGameRegion().find(characterRo); - if (characterResult.isExist()) { - log.info(`已找到角色${selectedCharacter}`); - // 计算向右偏移70像素、向下偏移70像素的位置 - const targetX = characterResult.x + 35; - const targetY = characterResult.y + 35; - - // 边界检查,确保坐标在屏幕范围内 - const safeX = Math.min(Math.max(targetX, 0), 1920); - const safeY = Math.min(Math.max(targetY, 0), 1080); - - click(safeX, safeY); - await sleep(500); // 点击角色后等待0.5秒 - characterFound = true; - break; - } - } catch (error) { - // 如果文件不存在,跳出循环 - break; - } - } - - if (characterFound) { - break; - } - - // 如果不是最后一次尝试,尝试滚动页面 - if (pageTries < 15) { - log.info("当前页面没有目标角色,滚动页面"); - await scrollPage(200); // 滚动距离可根据实际情况调整 - } - pageTries++; - } - - if (!characterFound) { - log.error(`未找到【${selectedCharacter}】`); - continue; - } - - // 识别"更换"或"加入"按钮 - const replaceResult = captureGameRegion().find(roReplace); - const joinResult = captureGameRegion().find(roJoin); - - if (replaceResult.isExist() || joinResult.isExist()) { - await sleep(300); - click(68, 1020); - keyPress("VK_LBUTTON"); - await sleep(500); - } else { - log.error(`该角色已在队伍中,无需切换`); - await sleep(300); - keyPress("VK_ESCAPE"); - await sleep(500); - } - await sleep(500); - } } else if (option === '存在bug-快速配对模式 @兩夢三醒') { - // 切换队伍 + // 切换队伍 if (!!settings.partyName) { try { log.info("正在尝试切换至" + settings.partyName); @@ -212,6 +256,9 @@ function readAliases() { await genshin.returnMainUi(); } + // 获取初始角色数组 + const initialAvatars = getAvatars(); + // 角色位置坐标 const positionCoordinates = [ [107, 190], @@ -224,25 +271,31 @@ function readAliases() { const aliases = readAliases(); // 获取需要切换的角色,并进行别名替换 - const positionSettings = [settings.position1, settings.position2, settings.position3, settings.position4].map(input => { - if (input && input.trim()!== "") { + const positionSettings = [settings.position1, settings.position2, settings.position3, settings.position4].map((input, index) => { + if (input && input.trim() !== "") { const actualName = aliases[input] || input; log.info(`设置对应号位为【${input}】,切换角色为【${actualName}】`); + // 替换初始数组对应位置 + initialAvatars[index] = actualName; return actualName; } return null; }); + // 目标角色数组(替换后的初始数组) + const targetAvatars = [...initialAvatars]; + log.info(`目标角色: [${targetAvatars}]`); + // 识别对象定义 const roTeamConfig = RecognitionObject.TemplateMatch(file.ReadImageMatSync(`Assets/RecognitionObject/队伍配置.png`), 0, 0, 1920, 1080); - // const roReplace = RecognitionObject.TemplateMatch(file.ReadImageMatSync(`Assets/RecognitionObject/更换.png`), 0, 0, 1920, 1080); - // const roJoin = RecognitionObject.TemplateMatch(file.ReadImageMatSync(`Assets/RecognitionObject/加入.png`), 0, 0, 1920, 1080); let openPairingTries = 0; let totalOpenPairingTries = 0; + let retryCount = 0; // 重试计数器 + let switchSuccess = false; // 在进入角色切换逻辑前进行检测,如果所有角色设置均为空则直接退出 - if (positionSettings.every((item) =>!item)) { + if (positionSettings.every((item) => !item)) { log.info("未设置任何角色,跳过切换队伍步骤"); await genshin.returnMainUi(); return; @@ -271,130 +324,160 @@ function readAliases() { } } - if (!(await openPairingInterface())) { - return; - } - - // 需要取消选择的数量 - const ocrRegions = [ - [340, 181, 315, 330], - [655, 181, 315, 330], - [970, 181, 315, 330], - [1285, 181, 315, 330], - ]; - let regionsWithTextCount = 0; - let captureRegion = captureGameRegion(); - for (const [x, y, w, h] of ocrRegions) { - const regionOcrResult = captureRegion.findMulti(RecognitionObject.ocr(x, y, w, h)); - if (regionOcrResult.count > 0) { - regionsWithTextCount++; + // 角色切换逻辑封装 + async function switchCharacters() { + if (!(await openPairingInterface())) { + return false; } - } - log.info(`有文字的区域数量为: ${regionsWithTextCount}`); - // 角色切换逻辑 - click(1212, 1020); // 点击快速编队 - await sleep(1000); - log.info(`点击快速编队`); - for (let i = 0; i < regionsWithTextCount; i++) { - if (i >= positionCoordinates.length) { - break; - } - const [x, y] = positionCoordinates[i]; - click(x, y); - await sleep(1000); - log.info(`取消选择${x},${y}位置的角色`); - } - - for (let i = 0; i < positionSettings.length; i++) { - let rolenum = i + 1; - const selectedCharacter = positionSettings[i]; - const [x, y] = positionCoordinates[i]; - click(800, 123); - await sleep(1000); - if (!selectedCharacter) { - log.info(`未设置${rolenum}号位角色,保持原来的选择,可能存在未知bug`); - click(x, y); - await sleep(1000); - continue; - } - log.info(`开始设置${rolenum}号位角色`); - log.info(`目标角色为:【${selectedCharacter}】`); - - let characterFound = false; - let pageTries = 0; - - // 最多尝试滚动页面20×2次 - while (pageTries < 40) { - // 尝试识别所有可能的角色文件名 - for (let num = 1; ; num++) { - const paddedNum = num.toString().padStart(2, "0"); - const characterFileName = `${selectedCharacter}${paddedNum}`; - try { - const characterRo = RecognitionObject.TemplateMatch( - file.ReadImageMatSync(`Assets/characterimage/${characterFileName}.png`), - 0, - 0, - 1920, - 1080 - ); - const characterResult = captureGameRegion().find(characterRo); - if (characterResult.isExist()) { - log.info(`已找到角色【${selectedCharacter}】`); - // 计算向右偏移70像素、向下偏移70像素的位置 - const targetX = characterResult.x + 35; - const targetY = characterResult.y + 35; - - // 边界检查,确保坐标在屏幕范围内 - const safeX = Math.min(Math.max(targetX, 0), 1920); - const safeY = Math.min(Math.max(targetY, 0), 1080); - - click(safeX, safeY); - await sleep(500); // 点击角色后等待0.5秒 - characterFound = true; - break; - } - } catch (error) { - // 如果文件不存在,跳出循环 - break; - } + // 需要取消选择的数量 + const ocrRegions = [ + [340, 181, 315, 330], + [655, 181, 315, 330], + [970, 181, 315, 330], + [1285, 181, 315, 330], + ]; + let regionsWithTextCount = 0; + let captureRegion = captureGameRegion(); + for (const [x, y, w, h] of ocrRegions) { + const regionOcrResult = captureRegion.findMulti(RecognitionObject.ocr(x, y, w, h)); + if (regionOcrResult.count > 0) { + regionsWithTextCount++; } + } + log.info(`有文字的区域数量为: ${regionsWithTextCount}`); - if (characterFound) { + // 角色切换逻辑 + click(1212, 1020); // 点击快速编队 + await sleep(1000); + log.info(`点击快速编队`); + for (let i = 0; i < regionsWithTextCount; i++) { + if (i >= positionCoordinates.length) { break; } - - // 如果不是最后一次尝试,尝试滚动页面 - if (pageTries < 30) { - log.info(`当前页面没有目标角色【${selectedCharacter}】,滚动页面`); - await scrollPage(200); // 滚动距离可根据实际情况调整 - } - if (pageTries == 15) { - log.info("滚动完毕,重置位置,再试一次"); - click(800, 123); - await sleep(1000); - } - pageTries++; - } - - if (!characterFound) { - log.error(`未找到【${selectedCharacter}】,尝试选择原来的角色`); - click(800, 123); - await sleep(1000); + const [x, y] = positionCoordinates[i]; click(x, y); await sleep(1000); - continue; + log.info(`取消选择${x},${y}位置的角色`); + } + + for (let i = 0; i < positionSettings.length; i++) { + let rolenum = i + 1; + const selectedCharacter = positionSettings[i]; + const [x, y] = positionCoordinates[i]; + click(800, 123); + await sleep(1000); + if (!selectedCharacter) { + log.info(`未设置${rolenum}号位角色,保持原来的选择,可能存在未知bug`); + click(x, y); + await sleep(1000); + continue; + } + log.info(`开始设置${rolenum}号位角色`); + log.info(`目标角色为:【${selectedCharacter}】`); + + let characterFound = false; + let pageTries = 0; + + // 最多尝试滚动页面20×2次 + while (pageTries < 40) { + // 尝试识别所有可能的角色文件名 + for (let num = 1; ; num++) { + const paddedNum = num.toString().padStart(2, "0"); + const characterFileName = `${selectedCharacter}${paddedNum}`; + try { + const characterRo = RecognitionObject.TemplateMatch( + file.ReadImageMatSync(`Assets/characterimage/${characterFileName}.png`), + 0, 0, 1920, 1080 + ); + const characterResult = captureGameRegion().find(characterRo); + if (characterResult.isExist()) { + log.info(`已找到角色【${selectedCharacter}】`); + characterResult.click(); + await sleep(500); + characterFound = true; + break; + } + } catch (error) { + // 文件不存在,跳出循环 + break; + } + } + + if (characterFound) { + break; + } + + // 滚动页面 + if (pageTries < 30) { + log.info(`当前页面没有目标角色【${selectedCharacter}】,滚动页面`); + await scrollPage(200); + } + if (pageTries == 15) { + log.info("滚动完毕,重置位置,再试一次"); + click(800, 123); + await sleep(1000); + } + pageTries++; + } + + if (!characterFound) { + log.error(`未找到【${selectedCharacter}】,尝试选择原来的角色`); + click(800, 123); + await sleep(1000); + click(x, y); + await sleep(1000); + continue; + } + } + + // 点击保存 + click(427, 1024); + await sleep(1000); + keyPress("VK_LBUTTON"); + await sleep(500); + return true; + } + + // 执行切换并检查结果 + while (retryCount < 2) { // 最多尝试2次(初始1次+重试1次) + if (!await switchCharacters()) { + log.error("角色切换过程失败"); + return; + } + + // 返回主界面后获取最终角色数组 + await genshin.returnMainUi(); + const finalAvatars = getAvatars(); + + // 比较数组是否完全一致 + const arraysEqual = targetAvatars.length === finalAvatars.length && + targetAvatars.every((val, idx) => val === finalAvatars[idx]); + + if (arraysEqual) { + log.info("角色切换成功"); + switchSuccess = true; + break; + } else { + log.warn("角色不匹配,准备重试..."); + retryCount++; + if (retryCount >= 2) { + log.error("角色切换失败"); + return; + } + // 重新打开配对界面准备重试 + await genshin.returnMainUi(); } } - // 点击保存 - click(427, 1024); - await sleep(1000); - keyPress("VK_LBUTTON"); - await sleep(500); - } - // 返回主界面 - await genshin.returnMainUi(); - //清空角色缓存 - genshin.ClearPartyCache(); + if (!switchSuccess) { + log.error("角色切换失败"); + return; + } + } + + // 返回主界面 + await genshin.returnMainUi(); + // 清空角色缓存 + genshin.ClearPartyCache(); })(); \ No newline at end of file