Files
2025-07-23 17:07:09 +08:00

516 lines
18 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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 = typeof (settings.removedCharacters1) === 'undefined' ? false : settings.removedCharacters1;
const removedCharacters2 = typeof (settings.removedCharacters2) === 'undefined' ? false : settings.removedCharacters2;
const removedCharacters3 = typeof (settings.removedCharacters3) === 'undefined' ? false : settings.removedCharacters3;
const removedCharacters4 = typeof (settings.removedCharacters4) === 'undefined' ? false : settings.removedCharacters4;
/**
* @returns {Promise<void>}
*/
(async function () {
// 切换队伍
if (!settings.disableNotice) {
for (let n = 0; n < 10; n++) {
log.warn("提示:队伍中小于等于两人时,才会触发双倍奖励");
}
await sleep(1000);
}
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();
}
// 进尘歌壶领历练点奖励后返回大世界
let request_times = settings.request_times * 2;
let total_clicks = request_times ? request_times : 14;
if (!!settings.appointFriendName) {
let enterStatus = await AppointFriendRequestToVisitSereniteaPot();
if (enterStatus) {
await claimEncounterPointsRewards();
await ReturnToBigWorld();
} else {
log.warn("好友列表未能识别出设置的好友名称");
log.info("尝试依次进入");
await pageTop(RightSliderTopRo);
let enterStatus = await RequestToVisitSereniteaPot(total_clicks);
if (enterStatus) {
await claimEncounterPointsRewards();
await ReturnToBigWorld();
}
}
} else if (!settings.appointFriendName) {
log.warn("未设置指定好友,执行依次进入");
let enterStatus = await RequestToVisitSereniteaPot(total_clicks);
if (enterStatus) {
await claimEncounterPointsRewards();
await ReturnToBigWorld();
}
} else {
log.warn("出现异常,请检查自定义参数和日志,也可能是没有好友开放尘歌壶");
}
// 以下为可供调用的函数部分
// 切换队伍
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(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));
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 removeSpecifiedRole();
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);
}
}
})();