mirror of
https://github.com/babalae/bettergi-scripts-list.git
synced 2026-05-21 22:35:48 +08:00
feat(auto-tool): 添加队伍切换功能并支持元素匹配
- 在SevenElement中新增矿物元素类型 - 实现基于路径的元素匹配和队伍切换逻辑 - 添加SwitchTeam工具模块实现队伍配置功能 - 集成OCR识别和图像匹配的队伍切换机制 - 支持自动翻页查找目标队伍功能 - 实现七天神像传送和队伍缓存清理功能
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.0 KiB |
BIN
repo/js/FullyAutoAndSemiAutoTools/assets/Leave Button.png
Normal file
BIN
repo/js/FullyAutoAndSemiAutoTools/assets/Leave Button.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.0 KiB |
BIN
repo/js/FullyAutoAndSemiAutoTools/assets/Quick Setup Button.png
Normal file
BIN
repo/js/FullyAutoAndSemiAutoTools/assets/Quick Setup Button.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.4 KiB |
BIN
repo/js/FullyAutoAndSemiAutoTools/assets/Slider Bottom.png
Normal file
BIN
repo/js/FullyAutoAndSemiAutoTools/assets/Slider Bottom.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 307 B |
BIN
repo/js/FullyAutoAndSemiAutoTools/assets/Slider Top.png
Normal file
BIN
repo/js/FullyAutoAndSemiAutoTools/assets/Slider Top.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 517 B |
@@ -40,8 +40,9 @@ const config_list = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const SevenElement = {
|
const SevenElement = {
|
||||||
SevenElements: ['火', '水', '风', '雷', '草', '冰', '岩'],
|
SevenElements: ['矿物', '火', '水', '风', '雷', '草', '冰', '岩'],
|
||||||
SevenElementsMap: new Map([
|
SevenElementsMap: new Map([
|
||||||
|
['矿物', []],
|
||||||
['火', []],
|
['火', []],
|
||||||
['水', ['海露花']],
|
['水', ['海露花']],
|
||||||
['风', ['蒲公英籽']],
|
['风', ['蒲公英籽']],
|
||||||
@@ -51,6 +52,8 @@ const SevenElement = {
|
|||||||
['岩', []],
|
['岩', []],
|
||||||
]),
|
]),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const team = {
|
const team = {
|
||||||
current: undefined,
|
current: undefined,
|
||||||
currentElementName: undefined,
|
currentElementName: undefined,
|
||||||
@@ -302,6 +305,7 @@ async function getValueByMultiCheckboxName(name) {
|
|||||||
async function init() {
|
async function init() {
|
||||||
let settingsConfig = await initSettings();
|
let settingsConfig = await initSettings();
|
||||||
let utils = [
|
let utils = [
|
||||||
|
"SwitchTeam",
|
||||||
"uid",
|
"uid",
|
||||||
]
|
]
|
||||||
for (let util of utils) {
|
for (let util of utils) {
|
||||||
@@ -671,6 +675,30 @@ async function runPath(path, stopKey = AUTO_STOP) {
|
|||||||
log.info(`[{mode}] 路径已执行: {path},跳过执行`, settings.mode, path)
|
log.info(`[{mode}] 路径已执行: {path},跳过执行`, settings.mode, path)
|
||||||
return
|
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 {
|
try {
|
||||||
const one = JSON.parse(file.readTextSync(path))
|
const one = JSON.parse(file.readTextSync(path))
|
||||||
if (one.info && one.info.description.includes("请配置好战斗策略")) {
|
if (one.info && one.info.description.includes("请配置好战斗策略")) {
|
||||||
|
|||||||
@@ -49,13 +49,13 @@
|
|||||||
{
|
{
|
||||||
"name": "teamSevenElements",
|
"name": "teamSevenElements",
|
||||||
"type": "input-text",
|
"type": "input-text",
|
||||||
"label": "7元素队伍配置 按 火,水,风,雷,草,冰,岩 该顺序填写",
|
"label": "队伍配置 按 `矿物,火,水,风,雷,草,冰,岩` 该顺序填写",
|
||||||
"default": ""
|
"default": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "choose_best",
|
"name": "choose_best",
|
||||||
"type": "checkbox",
|
"type": "checkbox",
|
||||||
"label": "择优模式",
|
"label": "择优模式(默认关闭 优先跑之前没跑过的)",
|
||||||
"default": false
|
"default": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -66,6 +66,6 @@
|
|||||||
{
|
{
|
||||||
"name": "autoSkip",
|
"name": "autoSkip",
|
||||||
"type": "input-text",
|
"type": "input-text",
|
||||||
"label": "自动跳过运行快捷键(独立BGI的快捷键请勿冲突)"
|
"label": "【测试功能-无效配置】自动跳过运行快捷键(独立BGI的快捷键请勿冲突)"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
210
repo/js/FullyAutoAndSemiAutoTools/utils/SwitchTeam.js
Normal file
210
repo/js/FullyAutoAndSemiAutoTools/utils/SwitchTeam.js
Normal file
@@ -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<void>}
|
||||||
|
// */
|
||||||
|
//
|
||||||
|
// (async function () {
|
||||||
|
// await SwitchPartyMain(settings.partyName, settings.disableGoStatue);
|
||||||
|
// })();
|
||||||
Reference in New Issue
Block a user