diff --git a/repo/js/FullyAutoAndSemiAutoTools/assets/Configure Team Button.png b/repo/js/FullyAutoAndSemiAutoTools/assets/Configure Team Button.png new file mode 100644 index 000000000..e6bdd02af Binary files /dev/null and b/repo/js/FullyAutoAndSemiAutoTools/assets/Configure Team Button.png differ diff --git a/repo/js/FullyAutoAndSemiAutoTools/assets/Confirm Deploy Button.png b/repo/js/FullyAutoAndSemiAutoTools/assets/Confirm Deploy Button.png new file mode 100644 index 000000000..6c870dfc6 Binary files /dev/null and b/repo/js/FullyAutoAndSemiAutoTools/assets/Confirm Deploy Button.png differ diff --git a/repo/js/FullyAutoAndSemiAutoTools/assets/Leave Button.png b/repo/js/FullyAutoAndSemiAutoTools/assets/Leave Button.png new file mode 100644 index 000000000..58c150b41 Binary files /dev/null and b/repo/js/FullyAutoAndSemiAutoTools/assets/Leave Button.png differ diff --git a/repo/js/FullyAutoAndSemiAutoTools/assets/Quick Setup Button.png b/repo/js/FullyAutoAndSemiAutoTools/assets/Quick Setup Button.png new file mode 100644 index 000000000..4b7e37512 Binary files /dev/null and b/repo/js/FullyAutoAndSemiAutoTools/assets/Quick Setup Button.png differ diff --git a/repo/js/FullyAutoAndSemiAutoTools/assets/Slider Bottom.png b/repo/js/FullyAutoAndSemiAutoTools/assets/Slider Bottom.png new file mode 100644 index 000000000..4af2e3cb2 Binary files /dev/null and b/repo/js/FullyAutoAndSemiAutoTools/assets/Slider Bottom.png differ diff --git a/repo/js/FullyAutoAndSemiAutoTools/assets/Slider Top.png b/repo/js/FullyAutoAndSemiAutoTools/assets/Slider Top.png new file mode 100644 index 000000000..7334e462d Binary files /dev/null and b/repo/js/FullyAutoAndSemiAutoTools/assets/Slider Top.png differ diff --git a/repo/js/FullyAutoAndSemiAutoTools/main.js b/repo/js/FullyAutoAndSemiAutoTools/main.js index 16c65a5d3..bce42d556 100644 --- a/repo/js/FullyAutoAndSemiAutoTools/main.js +++ b/repo/js/FullyAutoAndSemiAutoTools/main.js @@ -40,8 +40,9 @@ const config_list = { } const SevenElement = { - SevenElements: ['火', '水', '风', '雷', '草', '冰', '岩'], + SevenElements: ['矿物', '火', '水', '风', '雷', '草', '冰', '岩'], SevenElementsMap: new Map([ + ['矿物', []], ['火', []], ['水', ['海露花']], ['风', ['蒲公英籽']], @@ -51,6 +52,8 @@ const SevenElement = { ['岩', []], ]), } + + const team = { current: undefined, currentElementName: undefined, @@ -302,6 +305,7 @@ async function getValueByMultiCheckboxName(name) { async function init() { let settingsConfig = await initSettings(); let utils = [ + "SwitchTeam", "uid", ] for (let util of utils) { @@ -671,6 +675,30 @@ async function runPath(path, stopKey = AUTO_STOP) { log.info(`[{mode}] 路径已执行: {path},跳过执行`, settings.mode, path) return } + + const entry = [...SevenElement.SevenElementsMap.entries()].find(([key, val]) => { + return val.some(item => path.includes(`\\${item}\\`)); + }); + if (entry) { + const [key, val] = entry; + const index = SevenElement.SevenElements.indexOf(key); + const teamName = team.SevenElements.length > index && index >= 0 ? + team.SevenElements[index] : undefined; + + if (!teamName || teamName === "") { + log.debug(`[{mode}] 没有设置队伍: {teamName},跳过切换`, settings.mode, teamName); + } else if (team.current === teamName) { + log.debug(`[{mode}] 当前队伍为: {teamName},无需切换`, settings.mode, teamName); + } else { + log.info(`[{mode}] 检测到需要: {key},切换至{val}`, settings.mode, key, teamName); + const teamSwitch = await switchUtil.SwitchPartyMain(teamName); + if (teamSwitch) { + team.current = teamSwitch; + } + } + + } + try { const one = JSON.parse(file.readTextSync(path)) if (one.info && one.info.description.includes("请配置好战斗策略")) { diff --git a/repo/js/FullyAutoAndSemiAutoTools/settings.json b/repo/js/FullyAutoAndSemiAutoTools/settings.json index 2c7c90039..7c6654fbf 100644 --- a/repo/js/FullyAutoAndSemiAutoTools/settings.json +++ b/repo/js/FullyAutoAndSemiAutoTools/settings.json @@ -49,13 +49,13 @@ { "name": "teamSevenElements", "type": "input-text", - "label": "7元素队伍配置 按 火,水,风,雷,草,冰,岩 该顺序填写", + "label": "队伍配置 按 `矿物,火,水,风,雷,草,冰,岩` 该顺序填写", "default": "" }, { "name": "choose_best", "type": "checkbox", - "label": "择优模式", + "label": "择优模式(默认关闭 优先跑之前没跑过的)", "default": false }, { @@ -66,6 +66,6 @@ { "name": "autoSkip", "type": "input-text", - "label": "自动跳过运行快捷键(独立BGI的快捷键请勿冲突)" + "label": "【测试功能-无效配置】自动跳过运行快捷键(独立BGI的快捷键请勿冲突)" } ] \ No newline at end of file diff --git a/repo/js/FullyAutoAndSemiAutoTools/utils/SwitchTeam.js b/repo/js/FullyAutoAndSemiAutoTools/utils/SwitchTeam.js new file mode 100644 index 000000000..f5e6bb4cf --- /dev/null +++ b/repo/js/FullyAutoAndSemiAutoTools/utils/SwitchTeam.js @@ -0,0 +1,210 @@ +// Party Setup +const QuickSetupButtonRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("assets/Quick Setup Button.png"), 1100, 900, 400, 180); +const ConfigureTeamButtonRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("assets/Configure Team Button.png"), 0, 900, 200, 180); +const ConfirmDeployButtonRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("assets/Confirm Deploy Button.png"), 0, 900, 1920, 180); +// Slider +const LeftSliderTopRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("assets/Slider Top.png"), 650, 50, 100, 100); +const LeftSliderBottomRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("assets/Slider Bottom.png"), 650, 100, 100, 900); +const MiddleSliderTopRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("assets/Slider Top.png"), 1250, 50, 100, 200); +const MiddleSliderBottomRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("assets/Slider Bottom.png"), 1250, 100, 100, 900); +const RightSliderTopRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("assets/Slider Top.png"), 1750, 100, 100, 100); +const RightSliderBottomRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("assets/Slider Bottom.png"), 1750, 100, 100, 900); + +// 翻页 +async function pageDown(SliderBottomRo) { + let captureRegion = captureGameRegion(); + let SliderBottom = captureRegion.find(SliderBottomRo); + captureRegion.dispose(); + if (SliderBottom.isExist()) { + log.info("当前页面已识别&点击完毕,向下滑动"); + // log.info("滑块当前位置:({x},{y},{h},{w})", SliderBottom.x, SliderBottom.y, SliderBottom.Width, SliderBottom.Height); + click(Math.ceil(SliderBottom.x + SliderBottom.Width / 2), Math.ceil(SliderBottom.y + SliderBottom.Height * 2)); + await moveMouseTo(0, 0); + await sleep(100); + } +} + +// 滑条顶端 +async function pageTop(SliderTopRo) { + let captureRegion = captureGameRegion(); + let SliderTop = captureRegion.find(SliderTopRo); + captureRegion.dispose(); + if (SliderTop.isExist()) { + log.info("识别到滑条顶端位置:({x},{y},{h},{w})", SliderTop.x, SliderTop.y, SliderTop.Width, SliderTop.Height); + await moveMouseTo(Math.ceil(SliderTop.x + SliderTop.Width / 2), Math.ceil(SliderTop.y + SliderTop.Height * 1)); + leftButtonDown(); + await sleep(1000); + leftButtonUp(); + await moveMouseTo(0, 0); + await sleep(100); + } +} + +// 切换队伍 +async function SwitchParty(partyName) { + let ConfigureStatue = false; + + let foundQuickSetup = false; + for (let j = 0; j < 2; j++) { // 尝试两次 + keyPress("VK_L"); + await sleep(2000); + for (let i = 0; i < 2; i++) { + let captureRegion = captureGameRegion(); + let QuickSetupButton = captureRegion.find(QuickSetupButtonRo); + captureRegion.dispose(); + if (QuickSetupButton.isExist()) { + log.info("已进入队伍配置页面"); + foundQuickSetup = true; + break; + } else { + await sleep(1000); + } + } + if (foundQuickSetup) { + break; // 第一次找到就退出循环 + } + } + + if (!foundQuickSetup) { + log.error("两次尝试都未能进入队伍配置页面"); + return false; + } + // 识别当前队伍 + let captureRegion = captureGameRegion(); + let resList = captureRegion.findMulti(RecognitionObject.ocr(100, 900, 300, 180)); + captureRegion.dispose(); + let currentPartyFound = false; + + for (let i = 0; i < resList.count; i++) { + let res = resList[i]; + log.info("当前队伍名称位置:({x},{y},{w},{h}), 识别结果:{text}", res.x, res.y, res.Width, res.Height, res.text); + if (res.text.includes(partyName)) { + log.info("当前队伍即为目标队伍,无需切换"); + notification.send(`当前队伍即为目标队伍:${partyName},无需切换`); + keyPress("VK_ESCAPE"); + await sleep(500); + currentPartyFound = true; + break; + } + } + if (!currentPartyFound) { + await sleep(1000); + let captureRegion = captureGameRegion(); + let ConfigureTeamButton = captureRegion.find(ConfigureTeamButtonRo); + captureRegion.dispose(); + if (ConfigureTeamButton.isExist()) { + log.info("识别到配置队伍按钮"); + ConfigureTeamButton.click(); + await sleep(500); + await pageTop(LeftSliderTopRo); + + for (let p = 0; p < 4; p++) { + // 识别当前页 + let captureRegion = captureGameRegion(); + let resList = captureRegion.findMulti(RecognitionObject.ocr(0, 100, 400, 900)); + captureRegion.dispose(); + for (let i = 0; i < resList.count; i++) { + let res = resList[i]; + if (settings.enableDebug) { + log.info("文本位置:({x},{y},{w},{h}), 识别内容:{text}", res.x, res.y, res.Width, res.Height, res.text); + } + if (res.text.includes(partyName)) { + log.info("目标队伍位置:({x},{y},{w},{h}), 识别结果:{text}", res.x, res.y, res.Width, res.Height, res.text); + click(Math.ceil(res.x + 360), res.y + Math.ceil(res.Height / 2)); + + // 找到目标队伍,点击确定、部署 + await sleep(1500); + let ConfirmButtonCaptureRegion = captureGameRegion(); + let ConfirmButton = ConfirmButtonCaptureRegion.find(ConfirmDeployButtonRo); + ConfirmButtonCaptureRegion.dispose(); + if (ConfirmButton.isExist()) { + log.info("识别到确定按钮:({x},{y},{w},{h})", ConfirmButton.x, ConfirmButton.y, ConfirmButton.Width, ConfirmButton.Height); + ConfirmButton.click(); + } + await sleep(1500); + let DeployButtonCaptureRegion = captureGameRegion(); + let DeployButton = DeployButtonCaptureRegion.find(ConfirmDeployButtonRo); + DeployButtonCaptureRegion.dispose(); + if (DeployButton.isExist()) { + log.info("识别到部署按钮:({x},{y},{w},{h})", DeployButton.x, DeployButton.y, DeployButton.Width, DeployButton.Height); + DeployButton.click(); + notification.send(`寻找到目标队伍:${partyName}`); + ConfigureStatue = true; + break; + } + } + } + if (ConfigureStatue) { + await genshin.returnMainUi(); + break; + } else { + await pageDown(LeftSliderBottomRo); + } + } + if (!ConfigureStatue) { + // 没找到指定队伍名称的队伍,抛出异常 + log.error(`没有找到指定队伍名称:${partyName}`); + notification.error(`没有找到指定队伍名称:${partyName}`); + await genshin.returnMainUi(); + throw new Error(`没有找到指定队伍名称:${partyName}`); + } + } else { + // 没找到配置队伍按钮,抛出异常 + log.error("没有找到配置队伍按钮"); + notification.error("没有找到配置队伍按钮"); + await genshin.returnMainUi(); + throw new Error("没有找到配置队伍按钮"); + } + } else { + // 当前队伍就是目标队伍,设置成功状态 + ConfigureStatue = true; + } + return ConfigureStatue; +} + +async function SwitchPartyMain(partyName, disableGoStatue) { + if (!!partyName) { + try { + if (!disableGoStatue) { + // 强制去七天神像换队 + log.info("强制传送到七天神像切换队伍"); + await genshin.TpToStatueOfTheSeven(); + log.info("正在尝试切换至" + partyName); + await SwitchParty(partyName); + } else { + // 先尝试在当前位置换队 + await genshin.returnMainUi(); + log.info("正在尝试切换至" + partyName); + let switchResult = await SwitchParty(partyName); + + if (!switchResult) { + // 如果当前位置换队失败,去七天神像再试一次 + log.info("当前位置换队失败,传送到七天神像重试"); + await genshin.TpToStatueOfTheSeven(); + log.info("正在七天神像重新尝试切换至" + partyName); + await SwitchParty(partyName); + } + } + genshin.clearPartyCache(); + return partyName + } catch (error) { + log.error("队伍切换失败:" + error.message); + notification.error("队伍切换失败:" + error.message); + await genshin.returnMainUi(); + } + } else { + log.error("没有设置切换队伍"); + notification.error("没有设置切换队伍"); + await genshin.returnMainUi(); + } +} +this.switchUtil={ + SwitchPartyMain +} +// /** +// * @returns {Promise} +// */ +// +// (async function () { +// await SwitchPartyMain(settings.partyName, settings.disableGoStatue); +// })(); \ No newline at end of file