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