mirror of
https://github.com/babalae/bettergi-scripts-list.git
synced 2026-03-19 03:59:51 +08:00
246 lines
7.8 KiB
JavaScript
246 lines
7.8 KiB
JavaScript
// 原神每日委托自动执行脚本 - 对话处理器模块
|
||
var DialogProcessor = {
|
||
// 执行优化的自动对话
|
||
executeOptimizedAutoTalk: async function (
|
||
customPriorityOptions,
|
||
customNpcWhiteList,
|
||
isInMainUI
|
||
) {
|
||
customPriorityOptions = customPriorityOptions || null;
|
||
customNpcWhiteList = customNpcWhiteList || null;
|
||
var effectivePriorityOptions = customPriorityOptions || [];
|
||
var effectiveNpcWhiteList = customNpcWhiteList || [];
|
||
|
||
// 初始化
|
||
keyPress("V");
|
||
|
||
// 从委托描述中提取任务相关的人名存为列表
|
||
extractedName = [];
|
||
// 委托描述的OCR识别区域
|
||
var nameRegion = {X: 75, Y: 240, WIDTH: 225, HEIGHT: 60};
|
||
var nameResults = await Utils.easyOCR(nameRegion);
|
||
// 尝试提取任务人名
|
||
for (var i = 0; i < nameResults.count; i++) {
|
||
var text = nameResults[i].text;
|
||
log.info("任务区域识别文本: {text}", text);
|
||
|
||
// 尝试提取任务人名
|
||
var name = Utils.extractName(text);
|
||
if (name) {
|
||
extractedName = name;
|
||
log.info("提取到人名: {name}", extractedName);
|
||
break;
|
||
}
|
||
}
|
||
|
||
// 交互选项区域OCR识别
|
||
var dialogRegion = { X: 1150, Y: 300, WIDTH: 350, HEIGHT: 400 };
|
||
// 对话选项的ICON识别区域
|
||
var talkIconRegion = { X: 1260, Y: 300, WIDTH: 90, HEIGHT: 550 };
|
||
nameResults = await Utils.easyOCR(dialogRegion);
|
||
var clickedWhitelistNPC = false;
|
||
var clickedExtractedName = false;
|
||
|
||
// 处理人名区域的OCR结果
|
||
if (nameResults.count > 0) {
|
||
log.info("人名区域识别到 {count} 个文本", nameResults.count);
|
||
|
||
// 首先尝试点击白名单中的NPC
|
||
for (var i = 0; i < nameResults.count; i++) {
|
||
var text = nameResults[i].text;
|
||
var res = nameResults[i];
|
||
log.info(
|
||
"人名区域识别到{text}:位置({x},{y},{h},{w})",
|
||
res.text,
|
||
res.x,
|
||
res.y,
|
||
res.width,
|
||
res.Height
|
||
);
|
||
// 检查是否包含白名单中的NPC名称
|
||
for (var j = 0; j < effectiveNpcWhiteList.length; j++) {
|
||
if (text.includes(effectiveNpcWhiteList[j])) {
|
||
log.info(
|
||
"找到白名单NPC: {npc},点击该NPC",
|
||
effectiveNpcWhiteList[j]
|
||
);
|
||
keyDown("VK_MENU");
|
||
await sleep(500);
|
||
click(res.x, res.y);
|
||
leftButtonClick();
|
||
keyUp("VK_MENU");
|
||
await sleep(200);
|
||
if (!isInMainUI()) {
|
||
clickedWhitelistNPC = true;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 如果没有点击白名单NPC,尝试点击包含提取到的人名的选项
|
||
if (!clickedWhitelistNPC && extractedName) {
|
||
for (var i = 0; i < nameResults.count; i++) {
|
||
var text = nameResults[i].text;
|
||
var res = nameResults[i];
|
||
if (text.includes(extractedName)) {
|
||
log.info("点击包含提取到任务人名的选项: {text}", text);
|
||
keyDown("VK_MENU");
|
||
await sleep(500);
|
||
click(res.x, res.y);
|
||
leftButtonClick();
|
||
keyUp("VK_MENU");
|
||
await sleep(200);
|
||
if (!isInMainUI()) {
|
||
clickedExtractedName = true;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 如果没有找到NPC,使用默认触发
|
||
if (!clickedWhitelistNPC && !clickedExtractedName) {
|
||
log.info("未找到匹配的NPC,使用默认触发方式");
|
||
keyPress("F"); // 默认触发剧情
|
||
await sleep(100);
|
||
keyPress("F"); // 默认触发剧情
|
||
await sleep(400);
|
||
}
|
||
|
||
// 重复执行自动剧情,直到返回主界面
|
||
var maxAttempts = 100; // 设置最大尝试次数,防止无限循环
|
||
var attempts = 0;
|
||
await sleep(1000);
|
||
log.info("开始执行自动剧情");
|
||
|
||
while (!isInMainUI() && attempts < maxAttempts) {
|
||
attempts++;
|
||
|
||
var startTime = new Date().getTime();
|
||
|
||
// 1秒内按空格键跳过
|
||
while (new Date().getTime() - startTime < 1000) {
|
||
keyPress("VK_SPACE");
|
||
await sleep(200);
|
||
}
|
||
|
||
if (isInMainUI()) {
|
||
log.info("检测到已返回主界面,结束循环");
|
||
break;
|
||
}
|
||
|
||
// 检查是否有匹配的优先选项
|
||
var foundPriorityOption = false;
|
||
|
||
// 获取对话区域截图并进行OCR识别
|
||
var dialogOptionsRegion = {
|
||
X: 1250,
|
||
Y: 250,
|
||
WIDTH: 550,
|
||
HEIGHT: 600,
|
||
};
|
||
var ocrResults = await Utils.easyOCR(dialogOptionsRegion);
|
||
if (ocrResults.count > 0) {
|
||
log.info("识别到 {count} 个选项", ocrResults.count);
|
||
|
||
for (var i = 0; i < ocrResults.count; i++) {
|
||
var ocrText = ocrResults[i].text;
|
||
|
||
// 检查是否在优先选项列表中
|
||
for (var j = 0; j < effectivePriorityOptions.length; j++) {
|
||
if (ocrText.includes(effectivePriorityOptions[j])) {
|
||
log.info(
|
||
"找到优先选项: {option},点击该选项",
|
||
effectivePriorityOptions[j]
|
||
);
|
||
// 点击该选项
|
||
ocrResults[i].click();
|
||
await sleep(500);
|
||
foundPriorityOption = true;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (foundPriorityOption) break;
|
||
}
|
||
|
||
// 如果没有找到优先选项,则使用默认跳过
|
||
if (!foundPriorityOption && !isInMainUI()) {
|
||
let exitList = await Utils.easyTemplateMatch(
|
||
Constants.TALK_EXIT_IMAGE_PATH,
|
||
talkIconRegion,
|
||
true
|
||
);
|
||
let iconList = await Utils.easyTemplateMatch(
|
||
Constants.TALK_ICON_IMAGE_PATH,
|
||
talkIconRegion
|
||
);
|
||
let clickXY = null;
|
||
//正常应该只识别到一个退出选项
|
||
if (exitList.count === 1) {
|
||
log.info("发现一个退出对话选项");
|
||
clickXY = [exitList[0].x, exitList[0].y];
|
||
|
||
//点击最下边的气泡选项
|
||
} else if (iconList.count > 0) {
|
||
log.info(
|
||
`发现{count}个气泡对话选项,点击最后一个气泡选项`,
|
||
iconList.count
|
||
);
|
||
iconList = [...iconList];
|
||
iconList.sort((a, b) => b.y - a.y);
|
||
clickXY = [iconList[0].x, iconList[0].y];
|
||
|
||
// 有对话选项时,点击最后一个选项
|
||
} else if (ocrResults.count > 0) {
|
||
log.info("指定类型的对话选项不符合数量条件,默认点击最后一个选项");
|
||
//C#的List不能用-1索引,^1不确定在js中能否使用,所以用count-1
|
||
clickXY = [
|
||
ocrResults[ocrResults.count - 1].x,
|
||
ocrResults[ocrResults.count - 1].y
|
||
];
|
||
|
||
} else {
|
||
log.warn("指定类型的对话选项不符合数量条件,不进行操作");
|
||
log.warn(
|
||
`退出图标:{exit}个,气泡图标:{icon}个,对话选项:{ocrResults}个`,
|
||
exitList.count,
|
||
iconList.count,
|
||
ocrResults.count
|
||
);
|
||
}
|
||
|
||
//点击对话选项
|
||
if (clickXY) {
|
||
keyDown("VK_MENU");
|
||
await sleep(300);
|
||
click(...clickXY);
|
||
leftButtonClick();
|
||
keyUp("VK_MENU");
|
||
}
|
||
}
|
||
}
|
||
|
||
// 检查是否已返回主界面
|
||
if (isInMainUI()) {
|
||
log.info("检测到已返回主界面,结束循环");
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (isInMainUI()) {
|
||
log.info("已返回主界面,自动剧情执行完成");
|
||
await sleep(500) //等主界面加载完毕,防止吞操作
|
||
keyPress("V");
|
||
await sleep(2000) //等待委托任务描述加载完毕
|
||
} else {
|
||
log.warn(
|
||
"已达到最大尝试次数 {attempts},但未检测到返回主界面",
|
||
maxAttempts
|
||
);
|
||
}
|
||
},
|
||
};
|