diff --git a/repo/js/AutoFishingTeyvat/READEME.md b/repo/js/AutoFishingTeyvat/READEME.md new file mode 100644 index 00000000..a872c175 --- /dev/null +++ b/repo/js/AutoFishingTeyvat/READEME.md @@ -0,0 +1,31 @@ +脚本名称:提瓦特自动钓鱼(全流程+自选) + +功能描述:支持自动追踪并垂钓bgi支持的全提瓦特垂钓点 + +## 核心功能 + +1. 可自选地区、鱼类、鱼饵 +2. 可直接钓取特定物品的兑换材料(例如渔获) +3. 脚本会根据需要的鱼类自动调节时间,不需要的时段会跳过 +4. 支持部分地图追踪无法到达的钓鱼点(例如炽岩斗士急流鱼钓鱼点,枫丹廷东北钓鱼点、雷鸣仙垂钓点) +5. 支持从特定的垂钓点继续任务(仅启用所有垂钓点时可用) +6. 默认禁用需要战斗的路线,如有需要请在JS脚本配置内启用 +7. 支持自定义钓鱼超时时间 +8. 支持设置定时关闭(最多24小时) +9. 4点自动领取月卡(可选) +10. 自动记录垂钓点冷却时间(进入其他世界钓鱼时请关闭此功能) +11. 启用自动拾取(可选) + +## 注意事项 + +1. 部分点位涉及战斗,且队伍内不能有双风和跑步(不是冲刺)时加移速的角色 +2. 跑图位必须是少男体型(防止键鼠路线[GCM]出错) +3. 同时选择鱼类和鱼饵的情况下按照以下逻辑选择路线: 所有被选的鱼类会被加入任务列表,如果选择的鱼饵中某个鱼饵不是已选的任何一个鱼类的对应的鱼饵,那么这个鱼饵对应的所有鱼类将被添加到任务列表 +4. JS脚本的设置内各设置项含有优先级,如果存在高优先级且选项不为默认,则只有最高优先级的设置项生效 +5. 部分钓鱼点为路径追踪+键鼠脚本(GCM)的混合模式,可能会出现因键鼠脚本误差卡死的情况,如果出现这种情况,请在JS脚本设置禁用键鼠路线来禁用所有包含键鼠脚本的钓鱼点 + +## 其它 + +作者:提瓦特钓鱼玳师 + +脚本反馈邮箱:hijiwos@hotmail.com \ No newline at end of file diff --git a/repo/js/AutoFishingTeyvat/main.js b/repo/js/AutoFishingTeyvat/main.js index 13628fd9..c2c12432 100644 --- a/repo/js/AutoFishingTeyvat/main.js +++ b/repo/js/AutoFishingTeyvat/main.js @@ -1,4 +1,4 @@ -(async function () { +(async function () { // 多人模式不计CD,CD读写仍有优化空间 const area_list = ['蒙德', '璃月', '稻妻', '须弥', '枫丹', '纳塔', '至冬', '层岩巨渊·地下矿区', '渊下宫'] const fish_list = ['花鳉', '波波心羽鲈', '烘烘心羽鲈', '维护机关·水域清理者', '维护机关·态势控制者', '维护机关·澄金领队型', '海涛斧枪鱼', '维护机关·初始能力型', '维护机关·白金典藏型', '吹沙角鲀', '甜甜花鳉', '擒霞客', '水晶宴', '斗棘鱼', '炮鲀', '流纹褐蝶鱼', '锖假龙', '金赤假龙', '玉玉心羽鲈', '赤魔王', '长生仙', '苦炮鲀', '肺棘鱼', '流纹京紫蝶鱼', '琉璃花鳉', '伪装鲨鲨独角鱼', '繁花斗士急流鱼', '深潜斗士急流鱼', '晚霞翻车鲀', '青浪翻车鲀', '拟似燃素独角鱼', '炽岩斗士急流鱼', '蓝染花鳉', '鸩棘鱼', '流纹茶蝶鱼', '雪中君', '真果角鲀', '青金斧枪鱼', '暮云角鲀', '翡玉斧枪鱼', '沉波蜜桃', '雷鸣仙', '佛玛洛鳐', '迪芙妲鳐', '秘源机关·巡戒使'] @@ -158,6 +158,95 @@ // 存储本次任务中的所有鱼类,作为调节时间的关键参考 let list_fish = []; + /** + * + * 将毫秒形式的字符串转换为更清晰的时间格式 + * + * @param ms + * @returns {string} + */ + function formatTimeDifference(ms) { + ms = Number(ms); + // 计算天、小时、分钟、秒 + const seconds = Math.floor(ms / 1000); + const minutes = Math.floor(seconds / 60); + const hours = Math.floor(minutes / 60); + const days = Math.floor(hours / 24); + + // 计算剩余的小时、分钟、秒 + const remainingHours = hours % 24; + const remainingMinutes = minutes % 60; + const remainingSeconds = seconds % 60; + + // 返回格式化字符串 + return `${days}天 ${remainingHours}小时 ${remainingMinutes}分钟 ${remainingSeconds}秒`; + } + + /** + * + * 垂钓点CD存档写入 + * + * @param {string} pathing_name 路径名称 + * @param {string} time_status 垂钓点时间状态(白天,夜晚) + * @param {string} timestamp 时间戳 + * @param {string} user_id 原神UID + */ + function write_archive(pathing_name, time_status, timestamp, user_id) { + let assets_dir = Array.from(file.readPathSync("assets")); + let content = {}; + if (assets_dir.includes("assets\\archive.json")) { + content = JSON.parse(file.readTextSync("assets/archive.json")); + if (time_status === "全天") { + content[user_id][pathing_name]["Daytime"] = timestamp; + content[user_id][pathing_name]["Nighttime"] = timestamp; + } else if (time_status === "白天") { + content[user_id][pathing_name]["Daytime"] = timestamp; + content[user_id][pathing_name]["Nighttime"] = Object.keys(content[user_id][pathing_name]).includes("Nighttime") ? content[user_id][pathing_name]["Nighttime"]: null; + } else if (time_status === "夜晚") { + content[user_id][pathing_name]["Daytime"] = Object.keys(content[user_id][pathing_name]).includes("Daytime") ? content[user_id][pathing_name]["Daytime"]: null; + content[user_id][pathing_name]["Nighttime"] = timestamp; + } + + } else { + content[user_id] = {}; + content[user_id][pathing_name] = { + "Daytime": time_status === "白天" || time_status === "全天" ? timestamp : null, + "Nighttime": time_status === "夜晚" || time_status === "全天" ? timestamp : null + }; + + } + + file.WriteTextSync("assets/archive.json", JSON.stringify(content, null, 2), false); + } + + /** + * + * 垂钓点CD存档读取 + * + * @param {string} pathing_name 路径名称 + * @param {string} user_id 原神UID + * + * @return Daytime/Nighttime 字典 + */ + function read_archive(pathing_name, user_id) { + let assets_dir = Array.from(file.readPathSync("assets")); + + if (assets_dir.includes("assets\\archive.json")) { + let content = JSON.parse(file.readTextSync("assets/archive.json")); + if (Object.keys(content).includes(user_id)) { + if (Object.keys(content[user_id]).includes(pathing_name)) { + return content[user_id][pathing_name]; + } else { + return null; + } + } else { + return null; + } + } else { + return null; + } + } + /** * 获取路径包含的信息 * @@ -298,7 +387,7 @@ } } - async function run_file(path_msg, time_out_throw, time_out_whole, is_con, block_gcm, block_fight, block_tsurumi, auto_skip) { + async function run_file(path_msg, time_out_throw, time_out_whole, is_con, block_gcm, block_fight, block_tsurumi, auto_skip, fishing_cd, uid = "default_user") { const base_path_pathing = "assets/pathing/"; const base_path_gcm = "assets/KeyMouseScript/"; const base_path_statues = "assets/pathing_statues/"; @@ -408,7 +497,65 @@ log.info(`该钓鱼点的时间: ${fishing_time}`); - await pathingScript.runFile(base_path_pathing + file_name + ".json"); + // 检查垂钓点CD + if (fishing_cd) { + let current_cd = read_archive(file_name, uid); + if (current_cd !== null) { + const now = Date.now(); + if (fishing_time === "全天") { + let daytime = true; + if (current_cd["Daytime"] !== null) { + let difference = now - current_cd["Daytime"]; + if (difference < 259200000) { + log.info(`该垂钓点(白天)处于冷却状态,剩余时间: ${formatTimeDifference(259200000 - difference)}`); + log.info(`${file_name}(白天) 已跳过...`); + daytime = false; + fishing_time = "夜晚"; + } else { + log.info(`该垂钓点(白天)未处于冷却状态,闲置时间: ${formatTimeDifference(difference - 259200000)}`); + } + } + if (current_cd["Nighttime"] !== null) { + let difference = now - current_cd["Nighttime"]; + if (difference < 259200000) { + log.info(`该垂钓点(夜晚)处于冷却状态,剩余时间: ${formatTimeDifference(259200000 - difference)}`); + log.info(`${file_name}(夜晚) 已跳过...`); + if (daytime) { + fishing_time = "白天"; + } else { + return null; + } + } else { + log.info(`该垂钓点(夜晚)未处于冷却状态,闲置时间: ${formatTimeDifference(difference - 259200000)}`); + } + } + } else if (fishing_time === "白天") { + if (current_cd["Daytime"] !== null) { + let difference = now - current_cd["Daytime"]; + if (difference < 259200000) { + log.info(`该垂钓点(白天)处于冷却状态,剩余时间: ${formatTimeDifference(259200000 - difference)}`); + log.info(`${file_name}(白天) 已跳过...`); + return null; + } else { + log.info(`该垂钓点(白天)未处于冷却状态,闲置时间: ${formatTimeDifference(difference - 259200000)}`); + } + } + } else if (fishing_time === "夜晚") { + if (current_cd["Nighttime"] !== null) { + let difference = now - current_cd["Nighttime"]; + if (difference < 259200000) { + log.info(`该垂钓点(夜晚)处于冷却状态,剩余时间: ${formatTimeDifference(259200000 - difference)}`); + log.info(`${file_name}(夜晚) 已跳过...`); + return null; + } else { + log.info(`该垂钓点(夜晚)未处于冷却状态,闲置时间: ${formatTimeDifference(difference - 259200000)}`); + } + } + } + } + } + + //await pathingScript.runFile(base_path_pathing + file_name + ".json"); // 执行键鼠脚本 if (path_msg["addition"] === "GCM") { @@ -417,11 +564,15 @@ // 调用自动钓鱼 // await genshin.autofishing(fishing_time_dic[fishing_time]["param"]); - await dispatcher.runTask(new SoloTask("AutoFishing", { - "fishingTimePolicy": fishing_time_dic[fishing_time]["param"], - "throwRodTimeOutTimeoutSeconds": time_out_throw, - "wholeProcessTimeoutSeconds": time_out_whole - })); + // await dispatcher.runTask(new SoloTask("AutoFishing", { + // "fishingTimePolicy": fishing_time_dic[fishing_time]["param"], + // "throwRodTimeOutTimeoutSeconds": time_out_throw, + // "wholeProcessTimeoutSeconds": time_out_whole + // })); + + if (fishing_cd) { + write_archive(file_name, fishing_time, Date.now(), uid); + } } async function main() { @@ -451,12 +602,33 @@ const auto_pick = typeof(settings.auto_pick) === 'undefined' ? false : settings.auto_pick; // 读取4点自动领取月卡的设置 const auto_skip = typeof(settings.auto_skip) === 'undefined' ? false : settings.auto_skip; + // 读取垂钓点CD统计 + const fishing_cd = typeof(settings.fishing_cd) === 'undefined' ? false: settings.fishing_cd; // 读取终止时间 const kill_hour = typeof(settings.time_kill_hour) === 'undefined' ? "无" : settings.time_kill_hour; const kill_minute = typeof(settings.time_kill_minute) === 'undefined' ? "无" : settings.time_kill_minute; const is_time_kill = kill_hour !== "无" && kill_minute !== "无"; // 判断是否启用 let time_target = new Date(); + // 获取当前用户UID + let uid = "default_user"; + if (fishing_cd) { + const ocrRo = RecognitionObject.Ocr(166, 198, 120, 22); + + genshin.returnMainUi(); + await sleep(1000); + keyPress("Escape"); + await sleep(1000); + + let ocr = captureGameRegion().Find(ocrRo); // 当前页面OCR + if (ocr.isExist()) { + uid = ocr.text; + } + + keyPress("Escape"); + + } + if (is_time_kill) { let now = new Date(); time_target.setHours(parseInt(kill_hour), 10); @@ -495,8 +667,7 @@ } // 路径详细信息 const path_msg = get_pathing_msg(path_filter[i]); - try { - await sleep(100); + // try { let current_msg = `${path_msg["area"]}-${path_msg["detail"]}` log.info(`当前钓鱼点: ${current_msg}(进度: ${i + 1}/${path_filter.length})`); if (path_continue === current_msg) { @@ -509,13 +680,13 @@ continue; } - await run_file(path_msg, time_out_throw, time_out_whole, is_con, block_gcm, block_fight, block_tsurumi, auto_skip); - } catch (error) { - const file_name = `${path_msg["area"]}-${path_msg["type"]}-${path_msg["detail"]}`; - log.info(`路径: ${file_name} 执行时出错,已跳过...\n错误信息: ${error}`) - } + await run_file(path_msg, time_out_throw, time_out_whole, is_con, block_gcm, block_fight, block_tsurumi, auto_skip, fishing_cd, uid); + // } catch (error) { + // const file_name = `${path_msg["area"]}-${path_msg["type"]}-${path_msg["detail"]}`; + // log.info(`路径: ${file_name} 执行时出错,已跳过...\n错误信息: ${error}`) + // } } } await main(); -})(); +})(); \ No newline at end of file diff --git a/repo/js/AutoFishingTeyvat/manifest.json b/repo/js/AutoFishingTeyvat/manifest.json index c7c142aa..002f2c19 100644 --- a/repo/js/AutoFishingTeyvat/manifest.json +++ b/repo/js/AutoFishingTeyvat/manifest.json @@ -1,15 +1,14 @@ { "manifest_version": 1, "name": "提瓦特自动钓鱼(全流程+自选)", - "version": "2.1.0", - "bgi_version": "0.45.0", - "description": "脚本名称:提瓦特自动钓鱼(全流程+自选)\n功能描述:支持自动追踪并垂钓bgi支持的全提瓦特垂钓点\n核心功能------------------------------>\n1.可自选地区、鱼类、鱼饵\n2.可直接钓取特定物品的兑换材料(例如渔获)\n3.脚本会根据需要的鱼类自动调节时间,不需要的时段会跳过\n4.支持部分地图追踪无法到达的钓鱼点(例如炽岩斗士急流鱼钓鱼点,枫丹廷东北钓鱼点、雷鸣仙垂钓点)\n5.支持从特定的垂钓点继续任务(仅启用所有垂钓点时可用)\n6.默认禁用需要战斗的路线,如有需要请在JS脚本配置内启用\n7.支持自定义钓鱼超时时间\n8.支持设置定时关闭(最多24小时)\n9.4点自动领取月卡(可选)\n10.启用自动拾取(可选)\n注意事项------------------------------>\n1.部分点位涉及战斗,且队伍内不能有双风和跑步(不是冲刺)时加移速的角色\n2.跑图位必须是少男体型(防止键鼠路线[GCM]出错)\n3.同时选择鱼类和鱼饵的情况下按照以下逻辑选择路线: 所有被选的鱼类会被加入任务列表,如果选择的鱼饵中某个鱼饵不是已选的任何一个鱼类的对应的鱼饵,那么这个鱼饵对应的所有鱼类将被添加到任务列表\n4.JS脚本的设置内各设置项含有优先级,如果存在高优先级且选项不为默认,则只有最高优先级的设置项生效\n5.部分钓鱼点为路径追踪+键鼠脚本(GCM)的混合模式,可能会出现因键鼠脚本误差卡死的情况,如果出现这种情况,请在JS脚本设置禁用键鼠路线来禁用所有包含键鼠脚本的钓鱼点\n---------------------------------------->\n作者:提瓦特钓鱼玳师\n脚本反馈邮箱:hijiwos@hotmail.com", + "version": "2.2.0", + "bgi_version": "0.47.0", + "description": "脚本名称:提瓦特自动钓鱼(全流程+自选)\n功能描述:支持自动追踪并垂钓bgi支持的全提瓦特垂钓点\n核心功能------------------------------>\n1.可自选地区、鱼类、鱼饵\n2.可直接钓取特定物品的兑换材料(例如渔获)\n3.脚本会根据需要的鱼类自动调节时间,不需要的时段会跳过\n4.支持部分地图追踪无法到达的钓鱼点(例如炽岩斗士急流鱼钓鱼点,枫丹廷东北钓鱼点、雷鸣仙垂钓点)\n5.支持从特定的垂钓点继续任务(仅启用所有垂钓点时可用)\n6.默认禁用需要战斗的路线,如有需要请在JS脚本配置内启用\n7.支持自定义钓鱼超时时间\n8.支持设置定时关闭(最多24小时)\n9.4点自动领取月卡(可选)\n10.自动记录垂钓点冷却时间(进入其他世界钓鱼时请关闭此功能)\n11.启用自动拾取(可选)\n注意事项------------------------------>\n1.部分点位涉及战斗,且队伍内不能有双风和跑步(不是冲刺)时加移速的角色\n2.跑图位必须是少男体型(防止键鼠路线[GCM]出错)\n3.同时选择鱼类和鱼饵的情况下按照以下逻辑选择路线: 所有被选的鱼类会被加入任务列表,如果选择的鱼饵中某个鱼饵不是已选的任何一个鱼类的对应的鱼饵,那么这个鱼饵对应的所有鱼类将被添加到任务列表\n4.JS脚本的设置内各设置项含有优先级,如果存在高优先级且选项不为默认,则只有最高优先级的设置项生效\n5.部分钓鱼点为路径追踪+键鼠脚本(GCM)的混合模式,可能会出现因键鼠脚本误差卡死的情况,如果出现这种情况,请在JS脚本设置禁用键鼠路线来禁用所有包含键鼠脚本的钓鱼点\n---------------------------------------->\n作者:提瓦特钓鱼玳师\n脚本反馈邮箱:hijiwos@hotmail.com", "authors": [ { - "name": "提瓦特钓鱼玳师", - "links": "https://github.com/Hijiwos" + "name": "提瓦特钓鱼玳师" } ], "settings_ui": "settings.json", "main": "main.js" -} \ No newline at end of file +} diff --git a/repo/js/AutoFishingTeyvat/settings.json b/repo/js/AutoFishingTeyvat/settings.json index 78feae9b..e6d2aa22 100644 --- a/repo/js/AutoFishingTeyvat/settings.json +++ b/repo/js/AutoFishingTeyvat/settings.json @@ -2,7 +2,8 @@ { "name": "show_info", "type": "input-text", - "label": "下方输入的内容用空格隔开、括号内是优先级\n(只会执行当前非默认最高优先级的选项)" + "label": "下方输入的内容用空格隔开、括号内是优先级\n(只会执行当前非默认最高优先级的选项)", + "default": "该输入框无需输入内容" }, { "name": "path_sort_area", @@ -127,22 +128,32 @@ { "name": "time_out_throw", "type": "input-text", - "label": "自动抛竿未上钩超时时间(秒) 默认: 10" + "label": "自动抛竿未上钩超时时间(秒)", + "default": 10 }, { "name": "time_out_whole", "type": "input-text", - "label": "整个任务超时时间(秒) 默认: 300" + "label": "整个任务超时时间(秒)", + "default": 300 }, { "name": "auto_pick", "type": "checkbox", - "label": "启用自动拾取(默认禁用)" + "label": "启用自动拾取", + "default": false }, { "name": "auto_skip", "type": "checkbox", - "label": "启用4点领取月卡(默认禁用)" + "label": "启用4点领取月卡", + "default": false + }, + { + "name": "fishing_cd", + "type": "checkbox", + "label": "启用垂钓点CD统计(自动跳过冷却中的垂钓点)", + "default": true }, { "name": "time_kill_hour", @@ -247,17 +258,20 @@ { "name": "block_gcm", "type": "checkbox", - "label": "禁用键鼠路线(默认启用键鼠路线)" + "label": "禁用键鼠路线(启用前请自行了解队伍配置要求)", + "default": false }, { "name": "block_fight", "type": "checkbox", - "label": "启用战斗路线(默认禁用战斗路线)" + "label": "启用战斗路线(需要自行配置战斗策略)", + "default": false }, { "name": "block_tsurumi", "type": "checkbox", - "label": "启用鹤观路线(默认禁用鹤观路线)" + "label": "启用鹤观路线(请确保任务已经完成,小道具交互的点位尚不可用)", + "default": false }, { "name": "path_select",