历练点双倍好感、使用历练点完成每日委托 - 支持指定多个好友名称,尝试进入各好友尘歌壶 (#3145)

* 历练点双倍好感 - 支持指定多个好友名称,尝试进入各好友尘歌壶

* 使用历练点完成每日委托 - 支持指定多个好友名称,尝试进入各好友尘歌壶

* Add files via upload
This commit is contained in:
this-Fish
2026-04-20 16:12:40 +08:00
committed by GitHub
parent dd986bbc33
commit 0f698e1872
6 changed files with 132 additions and 111 deletions

View File

@@ -70,6 +70,7 @@ const removedCharacters4 = typeof (settings.removedCharacters4) === 'undefined'
await ReturnToBigWorld();
} else {
log.warn("好友列表未能识别出设置的好友名称");
log.info(`交互或拾取:"无法进入所有指定好友尘歌壶"`);
log.info("尝试依次进入");
await pageTop(RightSliderTopRo);
let enterStatus = await RequestToVisitSereniteaPot(total_clicks);
@@ -191,6 +192,16 @@ const removedCharacters4 = typeof (settings.removedCharacters4) === 'undefined'
// 模板匹配&OCR进指定好友尘歌壶
async function AppointFriendRequestToVisitSereniteaPot() {
// 解析多个好友名称(支持 "aaa,bbb,ccc" 或 "aaa, bbb, ccc"
const rawNames = settings.appointFriendName.split(',');
const friendNames = rawNames.map(name => name.trim()).filter(name => name !== "");
//没有有效的指定好友名称
if (friendNames.length === 0) {
log.warn("指定的好友名称为空(如仅逗号或空白),将回退到「依次进入」模式");
return false;
}
let enterStatus = false;
await sleep(2000);
keyPress("VK_ESCAPE");
@@ -209,73 +220,73 @@ const removedCharacters4 = typeof (settings.removedCharacters4) === 'undefined'
await sleep(2000);
}
for (let p = 0; p < 5; p++) {
// 一頁7個好友、假定200好友位全滿、指定好友在第200位、得翻29次頁面
for (let p = 0; p < 29; p++) {
// 点击好友头像
let captureRegion = captureGameRegion();
let resList = captureRegion.findMulti(RecognitionObject.ocr(250, 120, 500, 840));
captureRegion.dispose();
for (let i = 0; i < resList.count; i++) {
let res = resList[i];
if (res.text.includes(settings.appointFriendName)) {
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));
captureRegion.dispose();
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();
}
// 检查当前好友名字是否匹配任意一个指定名称
let matched = false;
for (let name of friendNames) {
if (res.text.includes(name)) {
matched = true;
break;
}
}
if (!matched) continue;
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 resList2 = captureRegion.findMulti(RecognitionObject.ocr(250, 220, 425, 380));
captureRegion.dispose();
for (let i = 0; i < resList2.count; i++) {
let res = resList2[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(200);
}
}
// 等待进入尘歌壶最多等待15秒
for (let wait = 0; wait < 30; wait++) {
const roCheck = captureGameRegion();
let paimonMenu = roCheck.find(paimonMenuRo);
roCheck.dispose();
if (paimonMenu.isExist()) {
log.info("已进入联机模式");
enterStatus = true;
return enterStatus; // 成功进入,直接返回
}
await sleep(500);
}
log.warn(`进入好友 [${res.text}] 的尘歌壶失败,尝试下一个指定好友`);
log.info(`交互或拾取:"无法进入 [${res.text}] 的尘歌壶"`);
keyPress("VK_ESCAPE");
await sleep(200);
}
await sleep(1000);
// 翻页继续尝试&模板匹配的方式等待加载
// 翻页继续尝试
let captureRegion_2 = captureGameRegion();
let SliderBottom = captureRegion_2.find(RightSliderBottomRo);
captureRegion_2.dispose();
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);
captureRegion.dispose();
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);
captureRegion.dispose();
if (paimonMenu.isExist()) {
break;
}
await sleep(1000);
}
} else if (paimonMenu.isExist()) {
log.info("已进入联机模式");
enterStatus = true;
break;
} else {
log.warn("出现异常情况,请检查");
enterStatus = false;
}
}
// 没有滑块时可能已到末尾,跳出翻页循环
break;
}
}
@@ -518,7 +529,7 @@ const removedCharacters4 = typeof (settings.removedCharacters4) === 'undefined'
// 向下一页
async function pageDown(SliderBottomRo) {
let captureRegion = captureGameRegion();
let SliderBottom = captureGameRegion().find(SliderBottomRo);
let SliderBottom = captureRegion.find(SliderBottomRo);
captureRegion.dispose();
if (SliderBottom.isExist()) {
log.info("当前页面已点击完毕,向下滑动");
@@ -548,4 +559,4 @@ const removedCharacters4 = typeof (settings.removedCharacters4) === 'undefined'
await sleep(1000);
}
}
})();
})();

View File

@@ -1,7 +1,7 @@
{
"manifest_version": 1,
"name": "历练点双倍好感",
"version": "2.1.4",
"version": "2.1.5",
"bgi_version": "0.53.1",
"description": "进入好友尘歌壶,用历练点领取双倍好感\n目前支持游戏语言简体、繁体中文、英文\n支持进入好友尘歌壶后让指定位置角色离队",
"authors": [

View File

@@ -7,7 +7,7 @@
{
"name": "appointFriendName",
"type": "input-text",
"label": "(选填)指定好友名称"
"label": "(选填)指定好友名称,多个用英文逗号分隔,如: 张三,李四,王五"
},
{
"name": "request_times",

View File

@@ -1,4 +1,4 @@
// 當前版本2.2.0
// 當前版本2.2.1
// 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);
@@ -95,6 +95,7 @@ const adventurePath = settings.adventurePath || '蒙德'; // 若未定义,用
if (!enterStatus) {
log.warn("无法进入指定好友尘歌壶,可能原因:未开放/识别失败");
log.info(`交互或拾取:"无法进入所有指定好友的尘歌壶"`);
log.info("尝试改为「依次进入」模式...");
await pageTop(RightSliderTopRo);
enterStatus = await RequestToVisitSereniteaPot(total_clicks);
@@ -228,6 +229,16 @@ const adventurePath = settings.adventurePath || '蒙德'; // 若未定义,用
// 模板匹配&OCR进指定好友尘歌壶
async function AppointFriendRequestToVisitSereniteaPot() {
// 解析多个好友名称(支持 "aaa,bbb,ccc" 或 "aaa, bbb, ccc"
const rawNames = settingsAppointFriendName.split(',');
const friendNames = rawNames.map(name => name.trim()).filter(name => name !== "");
//没有有效的指定好友名称
if (friendNames.length === 0) {
log.warn("指定的好友名称为空(如仅逗号或空白),将回退到「依次进入」模式");
return false;
}
let enterStatus = false;
await sleep(2000);
keyPress("VK_ESCAPE");
@@ -252,69 +263,68 @@ const adventurePath = settings.adventurePath || '蒙德'; // 若未定义,用
let captureRegion = captureGameRegion();
let resList = captureRegion.findMulti(RecognitionObject.ocr(250, 120, 500, 840));
captureRegion.dispose();
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);
// 申请造访尘歌壶
const ro6 = captureGameRegion();
let resList2 = ro6.findMulti(RecognitionObject.ocr(250, 220, 425, 380));
ro6.dispose();
for (let i = 0; i < resList2.count; i++) {
let res = resList2[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(200);
}
// 检查当前好友名字是否匹配任意一个指定名称
let matched = false;
for (let name of friendNames) {
if (res.text.includes(name)) {
matched = true;
break;
}
}
if (!matched) continue;
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);
// 申请造访尘歌壶
const ro6 = captureGameRegion();
let resList2 = ro6.findMulti(RecognitionObject.ocr(250, 220, 425, 380));
ro6.dispose();
for (let i = 0; i < resList2.count; i++) {
let res = resList2[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(200);
}
}
// 等待进入尘歌壶最多等待15秒
for (let wait = 0; wait < 30; wait++) {
const roCheck = captureGameRegion();
let paimonMenu = roCheck.find(paimonMenuRo);
roCheck.dispose();
if (paimonMenu.isExist()) {
log.info("已进入联机模式");
enterStatus = true;
return enterStatus; // 成功进入,直接返回
}
await sleep(500);
}
log.warn(`进入好友 [${res.text}] 的尘歌壶失败,尝试下一个指定好友`);
log.info(`交互或拾取:"无法进入 [${res.text}] 的尘歌壶"`);
keyPress("VK_ESCAPE");
await sleep(200);
}
await sleep(1000);
// 翻页继续尝试&模板匹配的方式等待加载
// 翻页继续尝试
const ro7 = captureGameRegion();
let SliderBottom = ro7.find(RightSliderBottomRo);
ro7.dispose();
if (SliderBottom.isExist()) {
await pageDown(RightSliderBottomRo);
} else {
for (let i = 0; i < 10; i++) {
const ro8 = captureGameRegion();
let paimonMenu = ro8.find(paimonMenuRo);
let CoOpMode = ro8.find(CoOpModeRo);
let MyFriends = ro8.find(MyFriendsRo);
ro8.dispose();
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++) {
const ro9 = captureGameRegion();
let paimonMenu = ro9.find(paimonMenuRo);
ro9.dispose();
if (paimonMenu.isExist()) {
break;
}
await sleep(1000);
}
} else if (paimonMenu.isExist()) {
log.info("已进入联机模式");
enterStatus = true;
break;
} else {
log.warn("出现异常情况,请检查");
enterStatus = false;
}
}
// 没有滑块时可能已到末尾,跳出翻页循环
break;
}
}
@@ -493,7 +503,7 @@ const adventurePath = settings.adventurePath || '蒙德'; // 若未定义,用
let EncounterPointsStageRewardsButton = ro28.find(Cannot_receive);
let ClaimRewards_cn_Button = ro28.find(ClaimRewards_cn_Ro);
ro28.dispose();
if (EncounterPointsStageRewardsButton.isExist() ||ClaimRewards_cn_Button.isExist()) {
if (EncounterPointsStageRewardsButton.isExist() || ClaimRewards_cn_Button.isExist()) {
log.info("识别到 完成所有任務");
returnValue = true;
@@ -713,7 +723,7 @@ const adventurePath = settings.adventurePath || '蒙德'; // 若未定义,用
let config = new AutoSkipConfig();
config.AutoGetDailyRewardsEnabled = true;
config.AutoReExploreEnabled = true;
dispatcher.addTimer(new RealtimeTimer("AutoSkip", config));
await sleep(10000);
await genshin.returnMainUi();

View File

@@ -1,7 +1,7 @@
{
"manifest_version": 1,
"name": "使用历练点完成每日委托",
"version": "2.2.0",
"version": "2.2.1",
"bgi_version": "0.44.1",
"description": "使用历练点完成每日委托:\n支持进入好友尘歌壶使用历练点领取双倍好感(队伍中小于等于两人时,能使队伍中两人获得双倍好感)\n支持进入好友尘歌壶后让指定位置角色离队\n能指定星期几执行星期几不执行\n前往冒险家协会领取奖励",
"authors": [

View File

@@ -18,7 +18,7 @@
{
"name": "appointFriendName",
"type": "input-text",
"label": "---好友尘歌壶双倍好感设置---\n\n(选填)指定好友名称"
"label": "---好友尘歌壶双倍好感设置---\n\n(选填)指定好友名称,多个用英文逗号分隔,如: 张三,李四,王五"
},
{
"name": "request_times",