diff --git a/repo/js/使用历练点完成每日委托/Assets/RecognitionObject/Adventurer Handbook Button.png b/repo/js/使用历练点完成每日委托/Assets/RecognitionObject/Adventurer Handbook Button.png new file mode 100644 index 00000000..0269c714 Binary files /dev/null and b/repo/js/使用历练点完成每日委托/Assets/RecognitionObject/Adventurer Handbook Button.png differ diff --git a/repo/js/使用历练点完成每日委托/Assets/RecognitionObject/Co-Op Mode Button.png b/repo/js/使用历练点完成每日委托/Assets/RecognitionObject/Co-Op Mode Button.png new file mode 100644 index 00000000..5e2d67f2 Binary files /dev/null and b/repo/js/使用历练点完成每日委托/Assets/RecognitionObject/Co-Op Mode Button.png differ diff --git a/repo/js/使用历练点完成每日委托/Assets/RecognitionObject/Co-Op Mode Page.png b/repo/js/使用历练点完成每日委托/Assets/RecognitionObject/Co-Op Mode Page.png new file mode 100644 index 00000000..d3848bef Binary files /dev/null and b/repo/js/使用历练点完成每日委托/Assets/RecognitionObject/Co-Op Mode Page.png differ diff --git a/repo/js/使用历练点完成每日委托/Assets/RecognitionObject/Configure Team Button.png b/repo/js/使用历练点完成每日委托/Assets/RecognitionObject/Configure Team Button.png new file mode 100644 index 00000000..e6bdd02a Binary files /dev/null and b/repo/js/使用历练点完成每日委托/Assets/RecognitionObject/Configure Team Button.png differ diff --git a/repo/js/使用历练点完成每日委托/Assets/RecognitionObject/Confirm Deploy Button.png b/repo/js/使用历练点完成每日委托/Assets/RecognitionObject/Confirm Deploy Button.png new file mode 100644 index 00000000..6c870dfc Binary files /dev/null and b/repo/js/使用历练点完成每日委托/Assets/RecognitionObject/Confirm Deploy Button.png differ diff --git a/repo/js/使用历练点完成每日委托/Assets/RecognitionObject/Encounter Points Stage Rewards.png b/repo/js/使用历练点完成每日委托/Assets/RecognitionObject/Encounter Points Stage Rewards.png new file mode 100644 index 00000000..6d32075d Binary files /dev/null and b/repo/js/使用历练点完成每日委托/Assets/RecognitionObject/Encounter Points Stage Rewards.png differ diff --git a/repo/js/使用历练点完成每日委托/Assets/RecognitionObject/Friends Button.png b/repo/js/使用历练点完成每日委托/Assets/RecognitionObject/Friends Button.png new file mode 100644 index 00000000..42ca7168 Binary files /dev/null and b/repo/js/使用历练点完成每日委托/Assets/RecognitionObject/Friends Button.png differ diff --git a/repo/js/使用历练点完成每日委托/Assets/RecognitionObject/Leave Button.png b/repo/js/使用历练点完成每日委托/Assets/RecognitionObject/Leave Button.png new file mode 100644 index 00000000..58c150b4 Binary files /dev/null and b/repo/js/使用历练点完成每日委托/Assets/RecognitionObject/Leave Button.png differ diff --git a/repo/js/使用历练点完成每日委托/Assets/RecognitionObject/My Friends Page.png b/repo/js/使用历练点完成每日委托/Assets/RecognitionObject/My Friends Page.png new file mode 100644 index 00000000..ed39e777 Binary files /dev/null and b/repo/js/使用历练点完成每日委托/Assets/RecognitionObject/My Friends Page.png differ diff --git a/repo/js/使用历练点完成每日委托/Assets/RecognitionObject/Quick Setup Button.png b/repo/js/使用历练点完成每日委托/Assets/RecognitionObject/Quick Setup Button.png new file mode 100644 index 00000000..4b7e3751 Binary files /dev/null and b/repo/js/使用历练点完成每日委托/Assets/RecognitionObject/Quick Setup Button.png differ diff --git a/repo/js/使用历练点完成每日委托/Assets/RecognitionObject/Slider Bottom.png b/repo/js/使用历练点完成每日委托/Assets/RecognitionObject/Slider Bottom.png new file mode 100644 index 00000000..4af2e3cb Binary files /dev/null and b/repo/js/使用历练点完成每日委托/Assets/RecognitionObject/Slider Bottom.png differ diff --git a/repo/js/使用历练点完成每日委托/Assets/RecognitionObject/Slider Top.png b/repo/js/使用历练点完成每日委托/Assets/RecognitionObject/Slider Top.png new file mode 100644 index 00000000..7334e462 Binary files /dev/null and b/repo/js/使用历练点完成每日委托/Assets/RecognitionObject/Slider Top.png differ diff --git a/repo/js/使用历练点完成每日委托/Assets/RecognitionObject/paimon_menu.png b/repo/js/使用历练点完成每日委托/Assets/RecognitionObject/paimon_menu.png new file mode 100644 index 00000000..c424325b Binary files /dev/null and b/repo/js/使用历练点完成每日委托/Assets/RecognitionObject/paimon_menu.png differ diff --git a/repo/js/使用历练点完成每日委托/README.md b/repo/js/使用历练点完成每日委托/README.md new file mode 100644 index 00000000..20706a73 --- /dev/null +++ b/repo/js/使用历练点完成每日委托/README.md @@ -0,0 +1,94 @@ +# 使用历练点完成每日委托脚本使用指南 + +## 功能概述 + +1. **队伍管理**: + - 自动切换到指定队伍 + - 可选择是否传送至七天神像切换队伍 + +2. **历练点使用**: + - 自动领取历练点奖励 + - 支持直接使用历练点(不获取双倍好感) + +3. **灵活执行时间设置**: + - 可设置为每天执行 + - 或指定每周的特定几天执行(如只在周一、周三、周五执行) + +4. **双倍好感度获取**: + - **在好友的尘歌壶内,队伍人数≤2人时使用历练点完成每日委托才能获取双倍好感度** + - 自动进入好友的尘歌壶 + - 支持指定特定好友 + - 可让指定角色离队,确保队伍人数≤2人(双倍好感度必要条件) + + + +## 参数设置说明 + +### 基本设置 +| 说明 | 默认值 | 示例 | +|------|--------|------| +|需要领取好感的队伍名称(不填则不切换队伍) | 无 | "好感队" | +|关闭前往七天神像切换队伍 | 未勾选 | 勾选后不传送到神像 | +|指定星期几执行(","分隔)
输入"0"为每天执行 | "0" | "1,3,5"(周一、三、五执行) | +|直接使用历练点完成每日委托
(全角色满好感时推荐启用) | 已勾选 | 勾选后不获取双倍好感 | + +### 尘歌壶双倍好感设置 +|说明 | 示例 | +|------|------| +| (选填)指定好友名称 | "旅行者123" | +| (选填)申请好友数(≤7) | "5" | +|让1号位角色离队 | 勾选 | +| 让2号位角色离队 | 勾选 | +| 让3号位角色离队 | 勾选 | +| 让4号位角色离队 | 勾选 | + + +## 使用建议 + +### 双倍好感度获取流程 +0. 先自行消耗120体力 +1. 自动进入好友尘歌壶 +2. 让指定位置角色离队(确保队伍≤2人) +3. 打开冒险之证领取历练点奖励 +4. 返回大世界 + +### 角色离队策略 +- 当需要获取双倍好感时,建议保留2个需要提升好感的角色 +- 勾选需要离队的角色位置(1号位为最左侧角色) +- **注意**:不能同时让所有角色离队(至少保留1个角色) + +### 时间设置技巧 +- 使用"0"设置为每天执行 +- 使用"1,3,5"设置为周一、三、五执行 +- 脚本会自动处理凌晨时段(00:00-04:00视为前一天) + +## 常见问题 + +**Q:为什么没有进入好友尘歌壶?** +A:请检查: +1. 是否已禁用双倍好感 (**直接使用历练点完成每日委托** 被勾选) +2. 好友名称是否正确(区分大小写和空格) +3. 好友尘歌壶权限是否设置为"允许直接加入" + +**Q:角色没有离队怎么办?** +A:请检查: +1. 是否正确勾选了角色位置 +2. 游戏是否处于可切换队伍状态 + + +**Q:如何知道今天是否会执行脚本?** +A:脚本日志会显示: +- "今天是星期X,开始使用历练点完成每日委托" +- 或"今天是星期X,不使用历练点" + +**Q:为什么切换队伍失败?** +A:可能因为: +1. 处于联机模式 +2. 队伍名称设置错误 + +## 注意事项 + +1. 游戏需运行在**1920×1080分辨率**下 +2. 进入好友尘歌壶需要**网络连接良好** +3. 双倍好感度需要队伍中**不超过2个角色** +4. 若使用指定好友功能,请确保**好友名称完全匹配** diff --git a/repo/js/使用历练点完成每日委托/main.js b/repo/js/使用历练点完成每日委托/main.js new file mode 100644 index 00000000..7108462f --- /dev/null +++ b/repo/js/使用历练点完成每日委托/main.js @@ -0,0 +1,610 @@ +// Encounter Points +const AdventurerHandbookButtonRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("Assets/RecognitionObject/Adventurer Handbook Button.png"), 100, 300, 700, 700); +const EncounterPointsStageRewardsRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("Assets/RecognitionObject/Encounter Points Stage Rewards.png"), 1500, 700, 100, 100); +// MainUi +const paimonMenuRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("Assets/RecognitionObject/paimon_menu.png"), 0, 0, 100, 100); +// Paimon Menu +const FriendsButtonRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("Assets/RecognitionObject/Friends Button.png"), 0, 300, 700, 780); +const CoOpModeButtonRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("Assets/RecognitionObject/Co-Op Mode Button.png"), 100, 300, 700, 780); +// Co-Op Mode Page +const CoOpModeRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("Assets/RecognitionObject/Co-Op Mode Page.png"), 0, 0, 200, 100); +const MyFriendsRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("Assets/RecognitionObject/My Friends Page.png"), 0, 0, 200, 100); +const LeaveButtonRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("Assets/RecognitionObject/Leave Button.png"), 1400, 900, 300, 180); +// Party Setup +const QuickSetupButtonRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("Assets/RecognitionObject/Quick Setup Button.png"), 1100, 900, 400, 180); +const ConfigureTeamButtonRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("Assets/RecognitionObject/Configure Team Button.png"), 0, 900, 200, 180); +const ConfirmDeployButtonRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("Assets/RecognitionObject/Confirm Deploy Button.png"), 0, 900, 1920, 180); +// Slider +const LeftSliderTopRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("Assets/RecognitionObject/Slider Top.png"), 650, 50, 100, 100); +const LeftSliderBottomRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("Assets/RecognitionObject/Slider Bottom.png"), 650, 100, 100, 900); +const MiddleSliderTopRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("Assets/RecognitionObject/Slider Top.png"), 1250, 50, 100, 200); +const MiddleSliderBottomRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("Assets/RecognitionObject/Slider Bottom.png"), 1250, 100, 100, 900); +const RightSliderTopRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("Assets/RecognitionObject/Slider Top.png"), 1750, 100, 100, 100); +const RightSliderBottomRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("Assets/RecognitionObject/Slider Bottom.png"), 1750, 100, 100, 900); + +// 取得需要离队角色資訊 +const removedCharacters1 = settings.removedCharacters1 || false; +const removedCharacters2 = settings.removedCharacters2 || false; +const removedCharacters3 = settings.removedCharacters3 || false; +const removedCharacters4 = settings.removedCharacters4 || false; +// 读取配置文件 +const settingsWeek = settings.week; +const settingsNotDoublePoints = settings.notDoublePoints || false; +const settingsAppointFriendName = settings.appointFriendName ? settings.appointFriendName.trim() : ""; + +/** + * @returns {Promise} + */ +(async function () { + let shouldRun = false; // 标志变量 + let dayOfWeek = -1; // 星期变量 + + // 判断设置合法性 + var items = []; + + // 判定 每天执行 / 星期几、是否使用历练点领奖 + if (settingsWeek === "0") { + shouldRun = true; + log.info("设置每天执行,开始使用历练点完成每日委托"); + } else if (settingsWeek) { + items = validateAndStoreNumbers(settingsWeek); + if (!items) { + log.error("星期设置格式错误,请使用类似'1,3,5,7'的格式"); + return; + } + + // 获取调整后的星期几(考虑00:00~04:00视为前一天) + dayOfWeek = getAdjustedDayOfWeek(); + + // 检查当前星期是否在用户设置的范围内 + if (items.includes(dayOfWeek)) { + shouldRun = true; + log.info(`今天是星期 ${dayOfWeek},开始使用历练点完成每日委托`); + } else { + log.info(`今天是星期 ${dayOfWeek},不使用历练点`); + return; + } + } else { + log.error("还没有设置需要在星期几使用历练点完成每日委托呢"); + log.error("请在调试器里添加本脚本->右键JS脚本->修改JS脚本自定义配置."); + return; + } + + if (shouldRun) { + try { + // 切换队伍 + if (!!settings.partyName) { + try { + log.info("正在尝试切换至" + settings.partyName); + if (!settings.disableGoStatue) { + log.info("正在传送回七天神像切换队伍"); + await genshin.TpToStatueOfTheSeven(); + await SwitchParty(settings.partyName); + } else { + await genshin.returnMainUi(); + await SwitchParty(settings.partyName); + } + } catch { + log.warn("\n\n队伍切换失败,可能是:\n1.处于联机模式 \n2.无法正确识别\n3.JS自定义配置中的队伍名称设置错误,请检查!\n"); + await genshin.returnMainUi(); + } + } else { + log.warn("没有设置切换队伍,使用当前队伍使用历练點"); + await genshin.returnMainUi(); + } + + // 区分双倍好感 + if (settingsNotDoublePoints == true) { + log.info(`不使用好友尘歌壶历练点领取双倍好感,直接使用历练点`); + await claimEncounterPointsRewards(); + } else if (settingsNotDoublePoints == false) { + // 进尘歌壶领历练点奖励后返回大世界 + let request_times = settings.request_times * 2; + let total_clicks = request_times ? request_times : 14; + // 指定好友名称 + if (settingsAppointFriendName !== "") { + let enterStatus = await AppointFriendRequestToVisitSereniteaPot(); + if (enterStatus) { + await sleep(2000); + log.info("正在让指定位置角色离队"); + await removeSpecifiedRole(); + await claimEncounterPointsRewards(); + await ReturnToBigWorld(); + } else { + log.warn("好友列表未能识别出设置的好友名称"); + log.info("尝试依次进入"); + await pageTop(RightSliderTopRo); + let enterStatus = await RequestToVisitSereniteaPot(total_clicks); + if (enterStatus) { + await sleep(2000); + log.info("正在让指定位置角色离队"); + await removeSpecifiedRole(); + await claimEncounterPointsRewards(); + await ReturnToBigWorld(); + } + } + } else if (settingsAppointFriendName == "") { + log.warn("未设置指定好友,执行依次进入"); + let enterStatus = await RequestToVisitSereniteaPot(total_clicks); + if (enterStatus) { + await sleep(2000); + log.info("正在让指定位置角色离队"); + await removeSpecifiedRole(); + await claimEncounterPointsRewards(); + await ReturnToBigWorld(); + } + } else { + log.warn("出现异常,请检查自定义参数和日志,也可能是没有好友开放尘歌壶"); + } + } + + } catch (e) { + log.error("失败,请检查设置"); + return; + } + } + + + // 以下为可供调用的函数部分 + + // 切换队伍 + async function SwitchParty(partyName) { + let ConfigureStatue = false; + keyPress("VK_L"); + + for (let i = 0; i < 10; i++) { + let QuickSetupButton = captureGameRegion().find(QuickSetupButtonRo); + if (QuickSetupButton.isExist()) { + log.info("已进入队伍配置页面"); + break; + } else { + await sleep(1000); + } + } + // 识别当前队伍 + let captureRegion = captureGameRegion(); + let resList = captureRegion.findMulti(RecognitionObject.ocr(100, 900, 300, 180)); + 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("当前队伍即为目标队伍,无需切换"); + keyPress("VK_ESCAPE"); + await sleep(500); + } else { + await sleep(1000); + let ConfigureTeamButton = captureGameRegion().find(ConfigureTeamButtonRo); + 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)); + 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)) { + if (settings.enableDebug) { + log.info("目标队伍位置:({x},{y},{w},{h}), 识别结果:{text}", res.x, res.y, res.Width, res.Height, res.text); + } + click(res.x, Math.ceil(res.y + res.Height * 1.35)); + + // 找到目标队伍,点击确定、部署 + await sleep(1500); + let ConfirmButton = captureGameRegion().find(ConfirmDeployButtonRo); + if (ConfirmButton.isExist()) { + if (settings.enableDebug) { + log.info("识别到确定按钮:({x},{y},{w},{h})", ConfirmButton.x, ConfirmButton.y, ConfirmButton.Width, ConfirmButton.Height); + } + ConfirmButton.click(); + } + await sleep(1500); + let DeployButton = captureGameRegion().find(ConfirmDeployButtonRo); + if (DeployButton.isExist()) { + if (settings.enableDebug) { + log.info("识别到部署按钮:({x},{y},{w},{h})", DeployButton.x, DeployButton.y, DeployButton.Width, DeployButton.Height); + } + DeployButton.click(); + ConfigureStatue = true; + break; + } + } + } + if (ConfigureStatue) { + await genshin.returnMainUi(); + break; + } else { + await pageDown(LeftSliderBottomRo); + } + } + if (!ConfigureStatue) { + log.warn("\n\n队伍切换失败,可能是:\n1.处于联机模式 \n2.无法正确识别\n3.JS自定义配置中的队伍名称设置错误,请检查!\n"); + await genshin.returnMainUi(); + break; + } + } + } + } + } + + // 模板匹配&OCR进指定好友尘歌壶 + async function AppointFriendRequestToVisitSereniteaPot() { + let enterStatus = false; + await sleep(2000); + keyPress("VK_ESCAPE"); + await sleep(2000); + + let FriendsBotton = captureGameRegion().find(FriendsButtonRo); + if (FriendsBotton.isExist()) { + log.info("识别到好友按钮"); + FriendsBotton.click(); + await sleep(2000); + } else { + log.warn("未识别到按钮,使用坐标点击"); + click(680, 550); + await sleep(2000); + } + + for (let p = 0; p < 5; p++) { + // 点击好友头像 + let captureRegion = captureGameRegion(); + let resList = captureRegion.findMulti(RecognitionObject.ocr(250, 120, 500, 840)); + for (let i = 0; i < resList.count; i++) { + let res = resList[i]; + if (res.text.includes(settingsAppointFriendName)) { + if (settings.enableDebug) { + log.info("指定好友名字位置:({x},{y},{w},{h}), 识别内容:{text}", res.x, res.y, res.Width, res.Height, res.text); + } + click(res.x - 100, res.y + 50); + await sleep(1000); + + // 申请造访尘歌壶 + let captureRegion = captureGameRegion(); + let resList = captureRegion.findMulti(RecognitionObject.ocr(250, 220, 425, 380)); + for (let i = 0; i < resList.count; i++) { + let res = resList[i]; + if (res.text.includes("申请造访") || res.text.includes("visit Serenitea Pot") || res.text.includes("申請造訪")) { + if (settings.enableDebug) { + log.info("申请造访尘歌壶位置:({x},{y},{w},{h}), 识别内容:{text}", res.x, res.y, res.Width, res.Height, res.text); + } + res.click(); + } + } + } + } + await sleep(1000); + // 翻页继续尝试&模板匹配的方式等待加载 + let SliderBottom = captureGameRegion().find(RightSliderBottomRo); + if (SliderBottom.isExist()) { + await pageDown(RightSliderBottomRo); + } else { + for (let i = 0; i < 10; i++) { + let captureRegion = captureGameRegion(); + let paimonMenu = captureRegion.Find(paimonMenuRo); + let CoOpMode = captureRegion.Find(CoOpModeRo); + let MyFriends = captureRegion.Find(MyFriendsRo); + if (CoOpMode.isExist() || MyFriends.isExist()) { + log.info("继续申请"); + break; + } else if (paimonMenu.isEmpty() && (CoOpMode.isEmpty() || MyFriends.isEmpty())) { + log.info("正在等待加载"); + await click(960, 540); + for (let i = 0; i < 30; i++) { + let captureRegion = captureGameRegion(); + let paimonMenu = captureRegion.Find(paimonMenuRo); + if (paimonMenu.isExist()) { + break; + } + await sleep(1000); + } + } else if (paimonMenu.isExist()) { + log.info("已进入联机模式"); + enterStatus = true; + break; + } else { + log.warn("出现异常情况,请检查"); + enterStatus = false; + } + } + break; + } + } + return enterStatus; + } + + // 好友列表递增坐标进尘歌壶(仅第一页) + async function RequestToVisitSereniteaPot(total_clicks) { + let enterStatus = false; + keyPress("VK_ESCAPE"); + await sleep(2000); + let FriendsBotton = captureGameRegion().find(FriendsButtonRo); + if (FriendsBotton.isExist()) { + log.info("识别到好友按钮"); + FriendsBotton.click(); + await sleep(2000); + } else { + log.warn("未识别到按钮,使用坐标点击"); + // click(1020,840); + click(680, 550); + await sleep(2000); + } + + let y_avatar = 178; //好友头像按钮起始Y坐标 + let y_request = 245; //申请造访按钮起始Y坐标 + const x_avatar = 208; + const x_request = 460; + const avatar_increment = 125; //两按钮相隔坐标 + const request_increment = 124; //两按钮相隔坐标 + const request_fixed_value = 560; //第四~七位好友申请造访按钮Y坐标 + let request_count = 0; + + // 先申请造访首位好友的尘歌壶 + log.info("正在申请造访第 1 位好友尘歌壶"); + click(x_avatar, y_avatar); + await sleep(750); + click(x_request, y_request); + await sleep(750); + + // 依次申请造访第 2 ~ 7 位好友的尘歌壶 + for (let i = 2; i < total_clicks; i++) { + if (i % 2 === 0) { + // 偶数索引,递增 y_avatar + y_avatar += avatar_increment; + log.info(`正在申请造访第 ${i / 2 + 1} 位好友尘歌壶`); + click(x_avatar, y_avatar); + await sleep(250); + click(x_avatar, y_avatar); + await sleep(750); + } else { + // 奇数索引,递增 y_request + if (request_count < 2) { + // 前 3 位好友递增 249 + y_request += request_increment; + } else { + // 第 4 位及以后设为 1118 + y_request = request_fixed_value; + } + request_count++; + click(x_request, y_request); + await sleep(750); + } + } + // 模板匹配的方式等待加载 + log.info("等待界面响应"); + for (let i = 0; i < 30; i++) { + let captureRegion = captureGameRegion(); + let res = captureRegion.Find(paimonMenuRo); + if (res.isEmpty()) { + await click(960, 540); + } else if (res.isExist()) { + log.info("已进入好友尘歌壶"); + enterStatus = true; + break; + } else { + log.warn("出现异常情况,请检查"); + enterStatus = false; + } + await sleep(500); + } + return enterStatus; + } + + // 模板匹配领取历练点奖励 + async function claimEncounterPointsRewards() { + + await sleep(2000); + log.info("正在打开冒险之证领取历练点奖励"); + await sleep(2000); + keyPress("VK_ESCAPE"); + + await sleep(2000); + let AdventurerHandbookButton = captureGameRegion().find(AdventurerHandbookButtonRo); + if (AdventurerHandbookButton.isExist()) { + log.info("识别到冒险之证按钮"); + AdventurerHandbookButton.click(); + + await sleep(2000) + let captureRegion = captureGameRegion(); + let resList = captureRegion.findMulti(RecognitionObject.ocr(200, 300, 200, 100)); + for (let i = 0; i < resList.count; i++) { + let res = resList[i]; + if (res.text.includes("委托") || res.text.includes("委託") || res.text.includes("Commissions") || res.text.includes("委")) { + if (settings.enableDebug) { + log.info("识别到委托选项卡位置:({x},{y},{w},{h}), 识别内容:{text}", res.x, res.y, res.Width, res.Height, res.text); + } + res.click(); + } else { + log.info("未识别到识别到委托选项卡"); + } + } + + await sleep(2000) + let EncounterPointsStageRewardsButton = captureGameRegion().find(EncounterPointsStageRewardsRo); + if (EncounterPointsStageRewardsButton.isExist()) { + log.info("识别到历练点领取按钮"); + EncounterPointsStageRewardsButton.click(); + await sleep(2000); + log.info("已领取历练点奖励"); + keyPress("VK_ESCAPE"); + } else if (EncounterPointsStageRewardsButton.isEmpty()) { + log.warn("未识别到历练点领取奖励按钮,可能是已领取或未完成"); + } + await genshin.returnMainUi(); + await sleep(2000); + } + } + + // 模板匹配退出尘歌壶回到大世界 + async function ReturnToBigWorld() { + log.info("正在返回大世界"); + keyPress("VK_F2"); + await sleep(2000); + let CoOpModeButton = captureGameRegion().find(CoOpModeRo); + if (CoOpModeButton.isExist()) { + log.info("识别到多人游戏页面"); + // + let LeaveButton = captureGameRegion().find(LeaveButtonRo); + if (LeaveButton.isExist()) { + log.info("识别到离开尘歌壶按钮"); + LeaveButton.click(); + await sleep(2000); + } + // 模板匹配的方式等待加载 + log.info("等待界面响应"); + for (let i = 0; i < 10; i++) { + let captureRegion = captureGameRegion(); + let res = captureRegion.Find(paimonMenuRo); + if (res.isEmpty()) { + await click(960, 540); + } else if (res.isExist()) { + log.info("已离开尘歌壶"); + break; + } else { + log.warn("出现异常情况或超时,请检查"); + } + await sleep(2000); + } + } + } + + // 让指定位置角色离队 + async function removeSpecifiedRole() { + try { + if (removedCharacters1 || removedCharacters2 || removedCharacters3 || removedCharacters4) { + // 打開配隊介面 + keyPress("l"); + await sleep(3500); + + // 让4号位角色离队 + if (removedCharacters4) { + // 第4名角色位置 + click(1460, 600); + await sleep(750); + click(430, 1020); + await sleep(750); + log.info("4号位角色已离队"); + + } + + // 让3号位角色离队 + if (removedCharacters3) { + // 第3名角色位置 + click(1130, 600); + await sleep(750); + click(430, 1020); + await sleep(750); + log.info("3号位角色已离队"); + } + + // 让2号位角色离队 + if (removedCharacters2) { + // 第2名角色位置 + click(790, 600); + await sleep(750); + click(430, 1020); + await sleep(750); + log.info("2号位角色已离队"); + } + + // 让1号位角色离队 + if (removedCharacters1) { + if (removedCharacters4 && removedCharacters3 && removedCharacters2) { + log.warn("2,3,4号位已离队,1号位角色不能离队"); + } else { + // 第1名角色位置 + click(480, 600); + await sleep(750); + click(430, 1020); + await sleep(750); + log.info("1号位角色已离队"); + } + } + + // 返回主界面 + await genshin.returnMainUi(); + } else { + log.info("无需让角色离队"); + } + } catch (error) { + log.error("出错: {0}", error); + } + } + + // 向下一页 + async function pageDown(SliderBottomRo) { + let SliderBottom = captureGameRegion().find(SliderBottomRo); + if (SliderBottom.isExist()) { + log.info("当前页面已点击完毕,向下滑动"); + if (settings.enableDebug) { + 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 * 3.5)); + await moveMouseTo(0, 0); + await sleep(100); + } + } + + // 回到页面顶部 + async function pageTop(SliderTopRo) { + let SliderTop = captureGameRegion().find(SliderTopRo); + if (SliderTop.isExist()) { + if (settings.enableDebug) { + 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.5)); + leftButtonDown(); + await sleep(500); + leftButtonUp(); + await moveMouseTo(0, 0); + await sleep(1000); + } + } + + // 获取用戶定義的星期几才執行 + function validateAndStoreNumbers(input) { + // 定义存储结果的数组 + let storedNumbers = []; + + // 使用正则表达式检测是否符合期望格式 + const regex = /^(\b([1-7])\b)(,(\b([1-7])\b))*$/; + + // 检测输入字符串是否符合正则表达式 + if (regex.test(input)) { + // 将输入字符串按逗号分割成数组 + const numbers = input.split(','); + + // 将分割后的数字字符串转换为整数并存储到数组中 + storedNumbers = numbers.map(Number); + + return storedNumbers; + } else { + return false + } + } + + // 获取调整后的星期几(考虑00:00~04:00视为前一天) + function getAdjustedDayOfWeek() { + const now = new Date(); + let dayOfWeek = now.getDay(); // 0-6 (0是周日) + const hours = now.getHours(); + + // 如果时间在00:00~04:00之间,视为前一天 + if (hours < 4) { + dayOfWeek = dayOfWeek === 0 ? 6 : dayOfWeek - 1; // 前一天 + log.info(`当前时间 ${now.getHours()}:${now.getMinutes()},视为前一天(星期 ${dayOfWeek === 0 ? 7 : dayOfWeek})`); + } else { + log.info(`当前时间 ${now.getHours()}:${now.getMinutes()},使用当天(星期 ${dayOfWeek === 0 ? 7 : dayOfWeek})`); + } + + // 转换为1-7格式(7代表周日) + return dayOfWeek === 0 ? 7 : dayOfWeek; + } +})(); \ No newline at end of file diff --git a/repo/js/使用历练点完成每日委托/manifest.json b/repo/js/使用历练点完成每日委托/manifest.json new file mode 100644 index 00000000..3b7f4762 --- /dev/null +++ b/repo/js/使用历练点完成每日委托/manifest.json @@ -0,0 +1,19 @@ +{ + "manifest_version": 1, + "name": "使用历练点完成每日委托", + "version": "1", + "bgi_version": "0.44.1", + "description": "使用历练点完成每日委托:\n支持进入好友尘歌壶,使用历练点领取双倍好感(队伍中小于等于两人时,能使队伍中两人获得双倍好感)\n支持进入好友尘歌壶后,让指定位置角色离队\n能指定星期几执行,星期几不执行", + "authors": [ + { + "name": "起个名字好难的喵", + "links": "https://github.com/MisakaAldrich" + }, + { + "name": "蜜柑魚", + "links": "https://github.com/this-Fish" + } + ], + "settings_ui": "settings.json", + "main": "main.js" +} \ No newline at end of file diff --git a/repo/js/使用历练点完成每日委托/settings.json b/repo/js/使用历练点完成每日委托/settings.json new file mode 100644 index 00000000..23f14f3e --- /dev/null +++ b/repo/js/使用历练点完成每日委托/settings.json @@ -0,0 +1,59 @@ +[ + { + "name": "partyName", + "type": "input-text", + "label": "需要领取好感的队伍名称(不填写则不切换队伍)" + }, + { + "name": "disableGoStatue", + "type": "checkbox", + "label": "关闭前往七天神像" + }, + { + "name": "week", + "type": "input-text", + "label": "指定星期几执行\n(使用\",\"分割多个星期几)\n例:输入\"2,3,4,5,6,7\"\n⠀⠀⠀会在星期2,3,4,5,6,日才执行使用历练点完成每日委托\n输入\"0\"则为每天执行", + "default": "0" + }, + { + "name": "notDoublePoints", + "type": "checkbox", + "label": "直接使用历练点完成每日委托 (推荐全角色满好感时启用)\n启用后无视下方 好友尘歌壶双倍好感设置", + "default": true + }, + { + "name": "appointFriendName", + "type": "input-text", + "label": "---好友尘歌壶双倍好感设置---\n\n(选填)指定好友名称" + }, + { + "name": "request_times", + "type": "input-text", + "label": "(选填)申请好友数,需小于等于7,不支持翻页" + }, + { + "name": "removedCharacters1", + "type": "checkbox", + "label": "让1号位角色离队" + }, + { + "name": "removedCharacters2", + "type": "checkbox", + "label": "让2号位角色离队" + }, + { + "name": "removedCharacters3", + "type": "checkbox", + "label": "让3号位角色离队" + }, + { + "name": "removedCharacters4", + "type": "checkbox", + "label": "让4号位角色离队" + }, + { + "name": "enableDebug", + "type": "checkbox", + "label": "开启Debug模式(队伍识别输出所有内容)" + } +] \ No newline at end of file