mirror of
https://github.com/babalae/bettergi-scripts-list.git
synced 2026-03-26 05:09:52 +08:00
351 lines
11 KiB
JavaScript
351 lines
11 KiB
JavaScript
// 原神每日委托自动执行脚本 - AutoSkip步骤处理器
|
||
// 共同的AutoSkip逻辑函数
|
||
var executeAutoSkipLogic = async function (stepData, stepName) {
|
||
try {
|
||
log.info("执行{stepName}步骤", stepName);
|
||
|
||
// 从stepData中提取配置参数
|
||
var customPriorityOptions = stepData.priorityOptions || [];
|
||
var customBlacklist = stepData.blacklist || [];
|
||
var customPriorityIcons = stepData.priorityIcons || [];
|
||
var customNpcWhiteList = stepData.npcWhiteList || [];
|
||
|
||
var StoryRo = RecognitionObject.TemplateMatch(
|
||
file.ReadImageMatSync("Data/RecognitionObject/disabled_ui.png"),
|
||
265,
|
||
37,
|
||
30,
|
||
22
|
||
);
|
||
|
||
// 识别图像函数
|
||
var recognizeImage = async function (recognitionObject) {
|
||
try {
|
||
// 尝试识别图像
|
||
let captureRegion = captureGameRegion();
|
||
var imageResult = captureRegion.find(recognitionObject);
|
||
captureRegion.dispose();
|
||
if (
|
||
imageResult &&
|
||
imageResult.x !== 0 &&
|
||
imageResult.y !== 0 &&
|
||
imageResult.width !== 0 &&
|
||
imageResult.height !== 0
|
||
) {
|
||
return { success: true, x: imageResult.x, y: imageResult.y };
|
||
}
|
||
} catch (error) {
|
||
log.error("识别图像时发生异常: {error}", error.message);
|
||
}
|
||
return { success: false };
|
||
};
|
||
|
||
var AutoSkip = async function (
|
||
customPriorityOptions,
|
||
customBlacklist,
|
||
customPriorityIcons,
|
||
customNpcWhiteList
|
||
) {
|
||
customPriorityOptions = customPriorityOptions || [];
|
||
customBlacklist = customBlacklist || [];
|
||
customPriorityIcons = customPriorityIcons || [];
|
||
customNpcWhiteList = customNpcWhiteList || [];
|
||
|
||
// 默认配置
|
||
var defaultPriorityOptions = [];
|
||
var defaultBlacklist = [];
|
||
var defaultPriorityIcons = [];
|
||
|
||
// 将npcWhiteList添加到priorityOptions的前面
|
||
var mergedPriorityOptions = customNpcWhiteList.concat(
|
||
customPriorityOptions
|
||
);
|
||
|
||
// 合并用户自定义配置和默认配置
|
||
var effectivePriorityOptions = defaultPriorityOptions.concat(
|
||
mergedPriorityOptions
|
||
);
|
||
var effectiveBlacklist = defaultBlacklist.concat(customBlacklist);
|
||
var effectivePriorityIcons =
|
||
customPriorityIcons.length > 0
|
||
? customPriorityIcons
|
||
: defaultPriorityIcons;
|
||
|
||
// 重复执行自动剧情,直到返回主界面
|
||
var maxAttempts = 1200; // 设置最大尝试次数,防止无限循环
|
||
var attempts = 0;
|
||
var SkipTime = 100; // 跳过间隔时间(毫秒)
|
||
var storyIconDetectedOnce = false; // 首次出现机制标志
|
||
|
||
await sleep(1000);
|
||
|
||
// 预加载优先图标识别对象
|
||
var priorityIconROs = [];
|
||
for (var k = 0; k < effectivePriorityIcons.length; k++) {
|
||
var iconName = effectivePriorityIcons[k];
|
||
try {
|
||
var iconPath = "Data/RecognitionObject/" + iconName;
|
||
var iconMat = file.ReadImageMatSync(iconPath);
|
||
if (iconMat) {
|
||
var ro = RecognitionObject.TemplateMatch(iconMat);
|
||
priorityIconROs.push(ro);
|
||
}
|
||
} catch (error) {
|
||
log.warn(
|
||
"无法加载优先图标 {iconName}: {error}",
|
||
iconName,
|
||
error.message
|
||
);
|
||
}
|
||
}
|
||
|
||
while (attempts < maxAttempts) {
|
||
var StoryResult = await recognizeImage(StoryRo);
|
||
|
||
// 首次出现机制:如果图标曾经出现过,就必须通过这个判断
|
||
if (storyIconDetectedOnce) {
|
||
if (!StoryResult.success) {
|
||
log.info("剧情图标消失,结束AutoSkip");
|
||
return;
|
||
}
|
||
} else {
|
||
// 如果图标第一次被检测到,记录首次出现
|
||
if (StoryResult.success) {
|
||
storyIconDetectedOnce = true;
|
||
log.info("检测到剧情图标首次出现,启用图标检测机制");
|
||
}
|
||
// 如果图标从未出现过,继续执行不进行判断
|
||
}
|
||
|
||
attempts++;
|
||
|
||
var startTime = new Date().getTime();
|
||
|
||
// 1秒内按空格键跳过
|
||
while (new Date().getTime() - startTime < 1000) {
|
||
keyPress("VK_SPACE");
|
||
await sleep(SkipTime);
|
||
}
|
||
|
||
// 1. 查找F图标
|
||
var fIconFound = false;
|
||
var fIconY = 0;
|
||
|
||
// F图标检测逻辑
|
||
var fIconRO = RecognitionObject.TemplateMatch(
|
||
file.ReadImageMatSync("Data/RecognitionObject/F.png"),
|
||
1207,
|
||
0,
|
||
43,
|
||
850
|
||
);
|
||
var fIconResult = await recognizeImage(fIconRO);
|
||
log.info(fIconResult.success)
|
||
|
||
if (fIconResult.success) {
|
||
fIconFound = true;
|
||
fIconY = fIconResult.y;
|
||
}
|
||
|
||
// 2. 查找优先图标
|
||
var priorityIconClicked = false;
|
||
if (fIconFound) {
|
||
for (var m = 0; m < priorityIconROs.length; m++) {
|
||
var iconRO = priorityIconROs[m];
|
||
var iconResult = await recognizeImage(iconRO);
|
||
if (iconResult.success) {
|
||
log.info("找到优先图标点击");
|
||
click(iconResult.x, iconResult.y);
|
||
priorityIconClicked = true;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 3. 如果没有找到优先图标,进行OCR识别
|
||
if (fIconFound && !priorityIconClicked) {
|
||
// 定义OCR区域:1250, F图标的y+10 到 1800,850
|
||
var ocrStartY = fIconY + 10;
|
||
var ocrHeight = 850 - ocrStartY;
|
||
|
||
if (ocrHeight > 0) {
|
||
var captureRegion = captureGameRegion();
|
||
var dialogArea = captureRegion.DeriveCrop(
|
||
1250,
|
||
ocrStartY,
|
||
550,
|
||
ocrHeight
|
||
);
|
||
|
||
// 创建OCR识别对象并识别文本
|
||
var ocrRo = RecognitionObject.Ocr(
|
||
0,
|
||
0,
|
||
dialogArea.width,
|
||
dialogArea.height
|
||
);
|
||
var ocrResults = dialogArea.FindMulti(ocrRo);
|
||
captureRegion.dispose();
|
||
dialogArea.dispose();
|
||
|
||
if (ocrResults && ocrResults.count > 0) {
|
||
var foundValidOption = false;
|
||
var firstNonBlacklistOption = null;
|
||
|
||
// 首先查找优先选项
|
||
for (var i = 0; i < ocrResults.count; i++) {
|
||
var ocrText = ocrResults[i].text;
|
||
log.debug("选项 {index}: {text}", i + 1, ocrText);
|
||
|
||
// 检查是否在优先选项列表中
|
||
for (var j = 0; j < effectivePriorityOptions.length; j++) {
|
||
var priorityOption = effectivePriorityOptions[j];
|
||
if (ocrText.includes(priorityOption)) {
|
||
log.info(
|
||
"找到优先选项: {option},点击该选项",
|
||
priorityOption
|
||
);
|
||
ocrResults[i].click();
|
||
foundValidOption = true;
|
||
break;
|
||
}
|
||
}
|
||
if (foundValidOption) break;
|
||
|
||
// 记录第一个非黑名单选项
|
||
if (!firstNonBlacklistOption) {
|
||
var isBlacklisted = false;
|
||
for (var k = 0; k < effectiveBlacklist.length; k++) {
|
||
var blackOption = effectiveBlacklist[k];
|
||
if (ocrText.includes(blackOption)) {
|
||
isBlacklisted = true;
|
||
break;
|
||
}
|
||
}
|
||
if (!isBlacklisted) {
|
||
firstNonBlacklistOption = ocrResults[i];
|
||
}
|
||
}
|
||
}
|
||
|
||
// 如果没有找到优先选项,但有非黑名单选项,点击第一个非黑名单选项
|
||
if (!foundValidOption && firstNonBlacklistOption) {
|
||
firstNonBlacklistOption.click();
|
||
foundValidOption = true;
|
||
}
|
||
|
||
// 如果既没有优先选项也没有非黑名单选项,按F键
|
||
if (!foundValidOption) {
|
||
keyPress("F");
|
||
}
|
||
} else {
|
||
keyPress("F");
|
||
}
|
||
}
|
||
}
|
||
}
|
||
};
|
||
|
||
// 执行AutoSkip功能
|
||
await AutoSkip(
|
||
customPriorityOptions,
|
||
customBlacklist,
|
||
customPriorityIcons,
|
||
customNpcWhiteList
|
||
);
|
||
|
||
log.info("{stepName}步骤执行完成", stepName);
|
||
} catch (error) {
|
||
log.error("执行{stepName}步骤时出错: {error}", stepName, error.message);
|
||
throw error;
|
||
}
|
||
};
|
||
|
||
// 注册"AutoSkip"步骤处理器
|
||
StepProcessorLoader.register("AutoSkip", async function (stepData, context) {
|
||
await executeAutoSkipLogic(stepData, "AutoSkip");
|
||
});
|
||
|
||
// 注册"对话"步骤处理器
|
||
StepProcessorLoader.register("对话", async function (stepData, context) {
|
||
await executeAutoSkipLogic(stepData, "对话");
|
||
});
|
||
|
||
/*
|
||
使用示例 - JSON格式配置:
|
||
|
||
1. 基本用法(使用默认配置):
|
||
{
|
||
"type": "AutoSkip"
|
||
}
|
||
|
||
2. 带优先选项的用法:
|
||
{
|
||
"type": "AutoSkip",
|
||
"priorityOptions": ["帮助", "同意", "确认"],
|
||
"note": "优先点击包含'帮助'、'同意'、'确认'的选项"
|
||
}
|
||
|
||
3. 带NPC白名单的用法:
|
||
{
|
||
"type": "AutoSkip",
|
||
"npcWhiteList": ["派蒙", "旅行者", "温迪"],
|
||
"note": "最优先点击包含指定NPC名称的选项"
|
||
}
|
||
|
||
4. 带黑名单选项的用法:
|
||
{
|
||
"type": "AutoSkip",
|
||
"blacklist": ["拒绝", "离开", "结束对话"],
|
||
"note": "避免点击包含'拒绝'、'离开'、'结束对话'的选项"
|
||
}
|
||
|
||
5. 带优先图标的用法:
|
||
{
|
||
"type": "AutoSkip",
|
||
"priorityIcons": ["icon_quest.png", "icon_important.png"],
|
||
"note": "优先点击指定图标"
|
||
}
|
||
|
||
6. 完整配置示例:
|
||
{
|
||
"type": "AutoSkip",
|
||
"npcWhiteList": ["委托发布者", "任务NPC"],
|
||
"priorityOptions": ["帮助", "委托", "任务"],
|
||
"blacklist": ["拒绝", "离开"],
|
||
"priorityIcons": ["icon_quest.png"],
|
||
"note": "完整配置:NPC白名单优先级最高,然后是任务相关选项,避免拒绝类选项"
|
||
}
|
||
|
||
7. 实际场景示例:
|
||
{
|
||
"type": "AutoSkip",
|
||
"npcWhiteList": ["凯瑟琳", "委托发布人"],
|
||
"priorityOptions": ["接受", "好的", "没问题"],
|
||
"blacklist": ["算了", "不了", "再见"],
|
||
"note": "委托对话:最优先选择NPC相关选项,然后是接受委托选项,避免拒绝选项"
|
||
}
|
||
|
||
参数说明:
|
||
- npcWhiteList: NPC白名单关键词数组,具有最高优先级,会被添加到priorityOptions的前面
|
||
- priorityOptions: 优先选项关键词数组,会优先点击包含这些关键词的对话选项
|
||
- blacklist: 黑名单关键词数组,会避免点击包含这些关键词的选项
|
||
- priorityIcons: 优先图标文件名数组,图标文件需放在Data/RecognitionObject/目录下
|
||
- note: 步骤说明(可选),用于注释当前步骤的作用
|
||
|
||
优先级顺序:
|
||
1. NPC白名单选项(npcWhiteList)- 最高优先级
|
||
2. 普通优先选项(priorityOptions)
|
||
3. 非黑名单选项
|
||
4. 按F键(默认操作)
|
||
|
||
功能说明:
|
||
- 自动识别剧情对话界面(通过disabled_ui.png图标)
|
||
- 连续按空格键跳过剧情文本
|
||
- 检测F键提示图标的位置
|
||
- 优先点击指定的图标(如果配置了priorityIcons)
|
||
- 使用OCR识别对话选项文本
|
||
- 按上述优先级顺序选择对话选项
|
||
- 循环执行直到剧情结束
|
||
*/
|