js:采集cd管理和自动狗粮更新 (#1039)

* js:自动狗粮和采集cd更新

* js:自动狗粮改为输入最低好感任务运行次数,默认10
This commit is contained in:
mno
2025-06-09 03:00:08 +08:00
committed by GitHub
parent 4c599e05ff
commit e1bfb67d89
5 changed files with 52 additions and 29 deletions

View File

@@ -16,7 +16,7 @@
使用即表示您已阅读并同意上述条款。 使用即表示您已阅读并同意上述条款。
**Last Updated:** 2025-05-27 **Last Updated:** 2025-06-09
--- ---
@@ -89,9 +89,9 @@
4. 02收尾超出100以外的调查点 4. 02收尾超出100以外的调查点
5. 03额外不受上限影响消失 5. 03额外不受上限影响消失
## 五、队伍配置 ## 五、推荐配置
- **双风阵容**:早柚+枫原万叶/砂糖(提升移动效率 - **双风阵容**早柚+枫原万叶/砂糖(提高移速
- **迪希雅**:白天时段提供移速加成 - **迪希雅**:白天时段提供移速加成
## 六、选择建议 ## 六、选择建议
@@ -132,6 +132,7 @@
1. 修改盗宝团触发路线,减少摩拉丢失 1. 修改盗宝团触发路线,减少摩拉丢失
2.优化ocr模块现在识别失败时会尝试点击中心位置 2.优化ocr模块现在识别失败时会尝试点击中心位置
3.优化流程现在只有当用户勾选了不分解四星时才会两次快速选择可以节约约5秒 3.优化流程现在只有当用户勾选了不分解四星时才会两次快速选择可以节约约5秒
4.修改自定义配置现在可以输入最低好感运行次数默认10次用来保证能够完成最低的好感任务次数。
### 1.22025.06.08 ### 1.22025.06.08
1. 加入狗粮分解和经验统计功能。 1. 加入狗粮分解和经验统计功能。
2.优化逻辑已经运行完成狗粮路线时仍然可以直接执行本js来完成好感 2.优化逻辑已经运行完成狗粮路线时仍然可以直接执行本js来完成好感

View File

@@ -239,7 +239,7 @@ const DEFAULT_FIGHT_TIMEOUT_SECONDS = 120;
const fightTimeout = validateTimeoutSetting(settings.fightTimeout, DEFAULT_FIGHT_TIMEOUT_SECONDS, "战斗"); const fightTimeout = validateTimeoutSetting(settings.fightTimeout, DEFAULT_FIGHT_TIMEOUT_SECONDS, "战斗");
// 好感循环开始 // 好感循环开始
await AutoFriendshipDev(50, ocrTimeout, fightTimeout, enemyType, endTime); const runnedTimes = await AutoFriendshipDev(50, ocrTimeout, fightTimeout, enemyType, endTime);
} }
} }
@@ -323,7 +323,7 @@ const DEFAULT_FIGHT_TIMEOUT_SECONDS = 120;
//完成剩下好感 //完成剩下好感
if (settings.completeRemainingFriendship) { if (runnedTimes < settings.minTimesForFirendship) {
//切换至好感队 //切换至好感队
await switchPartyIfNeeded(friendshipPartyName); await switchPartyIfNeeded(friendshipPartyName);
// 验证超时设置 // 验证超时设置
@@ -343,7 +343,7 @@ const DEFAULT_FIGHT_TIMEOUT_SECONDS = 120;
await AutoPath('鳄鱼-准备'); await AutoPath('鳄鱼-准备');
} }
// 好感循环开始 // 好感循环开始
await AutoFriendshipDev(50, ocrTimeout, fightTimeout, enemyType, endTime + 24 * 60 * 60 * 1000); await AutoFriendshipDev(settings.minTimesForFirendship - runnedTimes, ocrTimeout, fightTimeout, enemyType, endTime + 24 * 60 * 60 * 1000);
} }
//伪造js开始记录 //伪造js开始记录
@@ -706,10 +706,10 @@ async function AutoFriendshipDev(times, ocrTimeout, fightTimeout, enemyType = "
await fakeLog(`${i + 1}次好感`, false, false, 0); await fakeLog(`${i + 1}次好感`, false, false, 0);
} }
log.info(`${enemyType}好感已完成`); log.info(`${enemyType}好感运行了${i + 1}`);
await genshin.tpToStatueOfTheSeven(); await genshin.tpToStatueOfTheSeven();
return true; return i + 1;
} }
// 验证输入是否是正整数 // 验证输入是否是正整数
@@ -777,8 +777,9 @@ async function waitForBattleResult(timeout = 2 * 60 * 1000, enemyType = "盗宝
while (Date.now() - fightStartTime < timeout) { while (Date.now() - fightStartTime < timeout) {
try { try {
// 简化OCR检测只使用一个try-catch块 // 简化OCR检测只使用一个try-catch块
let result = captureGameRegion().find(RecognitionObject.ocr(850, 150, 200, 80)); let captureRegion = captureGameRegion();
let result2 = captureGameRegion().find(RecognitionObject.ocr(0, 200, 300, 300)); let result = captureRegion.find(RecognitionObject.ocr(850, 150, 200, 80));
let result2 = captureRegion.find(RecognitionObject.ocr(0, 200, 300, 300));
let text = result.text; let text = result.text;
let text2 = result2.text; let text2 = result2.text;

View File

@@ -57,9 +57,9 @@
"default": "120" "default": "120"
}, },
{ {
"name": "completeRemainingFriendship", "name": "minTimesForFirendship",
"type": "checkbox", "type": "input-text",
"label": "是否在狗粮路线结束后完成剩余盗宝团好感\n【勾选后将在狗粮路线结束后继续完成剩余的好感任务】", "label": "好感任务最低运行次数\n【若卡时间好感次数不足该次数在狗粮结束后补齐】",
"default": false "default": "10"
} }
] ]

View File

@@ -86,7 +86,7 @@ async function fakeLog(name, isJs, isStart, duration) {
// 定义目标文件夹路径和记录文件路径 // 定义目标文件夹路径和记录文件路径
const recordFolder = "record"; // 存储记录文件的文件夹路径 const recordFolder = "record"; // 存储记录文件的文件夹路径
const timestamp = "::2000-01-01T00:00:00.000Z"; // 固定的时间戳 const defaultTimeStamp = "2000-01-01T00:00:00.000Z"; // 固定的时间戳
// 从 settings 中读取用户配置,并设置默认值 // 从 settings 中读取用户配置,并设置默认值
const userSettings = { const userSettings = {
@@ -159,19 +159,16 @@ function removeJsonSuffix(fileName) {
} }
log.debug(`路径组1.txt 是否存在: ${indexDoExist}`); log.debug(`路径组1.txt 是否存在: ${indexDoExist}`);
// 根据用户配置选择操作模式 {
if (userSettings.operationMode === "重新生成索引文件用于强制刷新CD或更新文件)" || !indexDoExist) { if (userSettings.operationMode === "重新生成索引文件用于强制刷新CD") {
if (userSettings.operationMode === "重新生成索引文件用于强制刷新CD或更新文件") {
log.info("重新生成索引文件模式,将覆盖现有索引文件"); log.info("重新生成索引文件模式,将覆盖现有索引文件");
} else { }
log.info("路径组1.txt 文件不存在,将生成文件"); if (!indexDoExist) {
log.info("路径组1.txt 文件不存在,将尝试生成索引文件");
} }
// 循环处理多个路径组 // 循环处理多个路径组
for (let i = 1; ; i++) { for (let i = 1; ; i++) {
const targetFolder = `pathing/路径组${i}`; // 动态生成目标文件夹路径
const filePaths = file.ReadPathSync(targetFolder);
// 检查当前路径组的 cdtype 是否为空 // 检查当前路径组的 cdtype 是否为空
const currentCdType = pathGroupCdType[i - 1] || ""; const currentCdType = pathGroupCdType[i - 1] || "";
if (!currentCdType) { if (!currentCdType) {
@@ -179,6 +176,9 @@ function removeJsonSuffix(fileName) {
break; break;
} }
const targetFolder = `pathing/路径组${i}`; // 动态生成目标文件夹路径
const filePaths = file.ReadPathSync(targetFolder);
// 如果文件夹为空,退出循环 // 如果文件夹为空,退出循环
if (filePaths.length === 0) { if (filePaths.length === 0) {
log.info(`路径组${i} 文件夹为空,停止处理`); log.info(`路径组${i} 文件夹为空,停止处理`);
@@ -187,13 +187,37 @@ function removeJsonSuffix(fileName) {
// 用于存储符合条件的文件名的数组 // 用于存储符合条件的文件名的数组
const jsonFileNames = []; const jsonFileNames = [];
const entryMap = {};
// 如果 indexDoExist 为 true则读取对应的原文件
if (indexDoExist) {
const pathGroupFilePath = `${subFolderPath}/路径组${i}.txt`; // 使用外层循环的变量 i
let pathGroupContent = await file.readText(pathGroupFilePath);
let pathGroupEntries = pathGroupContent.trim().split('\n');
// 创建一个对象来存储 entryName 和 entryTimestamp 的映射
for (let j = 0; j < pathGroupEntries.length; j++) {
const entryWithTimestamp = pathGroupEntries[j].trim();
const [entryName, entryTimestamp] = entryWithTimestamp.split('::');
entryMap[entryName] = entryTimestamp;
}
}
// 遍历文件路径数组并提取文件名 // 遍历文件路径数组并提取文件名
for (const filePath of filePaths) { for (const filePath of filePaths) {
const fileName = basename(filePath); // 提取文件名 const fileName = basename(filePath); // 提取文件名
if (fileName.endsWith('.json')) { // 检查文件名是否以 .json 结尾 if (fileName.endsWith('.json')) { // 检查文件名是否以 .json 结尾
const fileNameWithoutSuffix = removeJsonSuffix(fileName); // 移除 .json 后缀 const fileNameWithoutSuffix = removeJsonSuffix(fileName); // 移除 .json 后缀
jsonFileNames.push(`${fileNameWithoutSuffix}${timestamp}`); // 添加时间戳并存储
// 给 routeTimeStamp 赋值为 defaultTimeStamp
let routeTimeStamp = defaultTimeStamp;
if (indexDoExist && userSettings.operationMode !== "重新生成索引文件用于强制刷新CD" && entryMap[fileNameWithoutSuffix]) {
routeTimeStamp = entryMap[fileNameWithoutSuffix];
}
routeTimeStamp = `::${routeTimeStamp}`;
// 添加时间戳并存储
jsonFileNames.push(`${fileNameWithoutSuffix}${routeTimeStamp}`);
} }
} }
@@ -218,9 +242,6 @@ function removeJsonSuffix(fileName) {
log.error(`写入文件失败: ${recordFilePath}`); log.error(`写入文件失败: ${recordFilePath}`);
} }
} }
} else {
// 如果用户选择的不是“重新生成索引文件”且文件已存在,则输出特定日志信息
log.debug("奶龙");
} }
// 新增逻辑:当选择“执行任务(若不存在索引文件则自动创建)”时,执行类似路径执行的逻辑 // 新增逻辑:当选择“执行任务(若不存在索引文件则自动创建)”时,执行类似路径执行的逻辑
@@ -414,7 +435,7 @@ function removeJsonSuffix(fileName) {
log.info('所有路径组的任务运行完成'); log.info('所有路径组的任务运行完成');
//伪造js开始的日志 //伪造js开始的日志
await fakeLog("采集cd管", true, true, 0); await fakeLog("采集cd管", true, true, 0);
} }
} catch (error) { } catch (error) {
log.error(`操作失败: ${error}`); log.error(`操作失败: ${error}`);

View File

@@ -1,7 +1,7 @@
{ {
"manifest_version": 1, "manifest_version": 1,
"name": "采集cd管理", "name": "采集cd管理",
"version": "1.1", "version": "1.2",
"bgi_version": "0.44.8", "bgi_version": "0.44.8",
"description": "仅面对会操作文件和读readme的用户基于文件夹操作自动管理采集路线的cd会按照路径组的顺序依次运行直到指定的时间并会按照给定的cd类型自动跳过未刷新的路线", "description": "仅面对会操作文件和读readme的用户基于文件夹操作自动管理采集路线的cd会按照路径组的顺序依次运行直到指定的时间并会按照给定的cd类型自动跳过未刷新的路线",
"authors": [ "authors": [