mirror of
https://github.com/babalae/bettergi-scripts-list.git
synced 2026-03-16 03:33:25 +08:00
795 lines
31 KiB
JavaScript
795 lines
31 KiB
JavaScript
// ======================================================
|
||
// 切换账号(OCR)版本
|
||
const author = "彩虹QQ人";
|
||
const script_name = "切换账号(OCR)版本";
|
||
// 图像识别资源
|
||
const pm_out = {
|
||
template: RecognitionObject.TemplateMatch(file.ReadImageMatSync("Assets/RecognitionObject/pm_out.png")),
|
||
name: "pm_out.png"
|
||
};
|
||
const out_to_login = {
|
||
template: RecognitionObject.TemplateMatch(file.ReadImageMatSync("Assets/RecognitionObject/out_to_login.png")),
|
||
name: "out_to_login.png"
|
||
};
|
||
const login_out_account = {
|
||
template: RecognitionObject.TemplateMatch(file.ReadImageMatSync("Assets/RecognitionObject/login_out_account.png")),
|
||
name: "login_out_account.png"
|
||
};
|
||
const out_account = {
|
||
template: RecognitionObject.TemplateMatch(file.ReadImageMatSync("Assets/RecognitionObject/out_account.png")),
|
||
name: "out_account.png"
|
||
};
|
||
const login_other_account = {
|
||
template: RecognitionObject.TemplateMatch(file.ReadImageMatSync("Assets/RecognitionObject/login_other_account_1.png")),
|
||
name: "login_other_account.png"
|
||
};
|
||
const input_phone_or_email = {
|
||
template: RecognitionObject.TemplateMatch(file.ReadImageMatSync("Assets/RecognitionObject/input_phone_or_email.png")),
|
||
name: "input_phone_or_email.png"
|
||
};
|
||
const input_password = {
|
||
template: RecognitionObject.TemplateMatch(file.ReadImageMatSync("Assets/RecognitionObject/input_password.png")),
|
||
name: "input_password.png"
|
||
};
|
||
const agree = {
|
||
template: RecognitionObject.TemplateMatch(file.ReadImageMatSync("Assets/RecognitionObject/agree.png")),
|
||
name: "agree.png"
|
||
};
|
||
// 人机验证识别图片
|
||
const login_verification = {
|
||
template: RecognitionObject.TemplateMatch(file.ReadImageMatSync("Assets/RecognitionObject/verification.png")),
|
||
name: "verification.png"
|
||
};
|
||
// 判断temporaryAccount是否为空,如果为空则赋值‘否’
|
||
const Account = settings.temporaryAccount || "否";
|
||
|
||
eval(file.readTextSync('utils/uid.js'))
|
||
// 点击区域中心
|
||
async function clickCenter(x, y, width, height) {
|
||
let centerX = Math.round(x + width / 2);
|
||
let centerY = Math.round(y + height / 2);
|
||
await click(centerX, centerY);
|
||
await sleep(500); // 确保点击后有足够的时间等待
|
||
return { success: true, x: centerX, y: centerY };
|
||
}
|
||
// 匹配图像并点击
|
||
async function matchImgAndClick(obj, desc, timeout = 8000) {
|
||
const start = Date.now();
|
||
let retryCount = 0; // 识别次数计数
|
||
let status = false; // 用于记录是否匹配成功
|
||
try {
|
||
while (Date.now() - start < timeout && !status) {
|
||
await sleep(300);
|
||
const ro = captureGameRegion();
|
||
let result = ro.Find(obj.template);
|
||
ro.dispose();
|
||
await sleep(500); // 短暂延迟,避免过快循环
|
||
if (result.isExist()) {
|
||
let clickResult = await clickCenter(result.x, result.y, result.width, result.height);
|
||
log.info(`【IMG】成功识别并点击 ${desc}| 耗时: ${Date.now() - start}ms`);
|
||
status = true; // 设置匹配成功状态
|
||
return { success: true, x: clickResult.x, y: clickResult.y };
|
||
}
|
||
// await sleep(200); // 短暂延迟,避免过快循环
|
||
log.info(`【IMG】第${retryCount++}次识别并点击 ${desc} 失败 | 耗时: ${Date.now() - start}ms`);
|
||
}
|
||
} catch (error) {
|
||
log.error(`【IMG】${script_name}等待超时,请人工介入。===待切换账号:${settings.username}===超时原因:未找到目标 [${desc}] | 文件:${obj.name}`);
|
||
//如果有配置通知……
|
||
notification.error(`【IMG】${script_name}等待超时,请人工介入。===待切换账号:${settings.username}===超时原因:未找到目标 [${desc}] | 文件:${obj.name}`);
|
||
throw new Error(`【IMG】识别图像时发生异常: ${error.message}`);
|
||
}
|
||
return { success: false };
|
||
}
|
||
// 文字识别并点击
|
||
async function recognizeTextAndClick(targetText, ocrRegion, timeout = 8000) {
|
||
let start = Date.now();
|
||
let retryCount = 0; // 重试计数
|
||
let status = false; // 用于记录是否匹配成功
|
||
try {
|
||
while (Date.now() - start < timeout && !status) {
|
||
const ro = captureGameRegion();
|
||
let resultList = ro.findMulti(ocrRegion);
|
||
ro.dispose();
|
||
await sleep(500); // 短暂延迟,避免过快循环
|
||
for (let result of resultList) {
|
||
if (result.text.includes(targetText)) {
|
||
let clickResult = await clickCenter(result.x, result.y, result.width, result.height);
|
||
log.info(`【OCR】成功识别并点击 ${targetText}| 耗时: ${Date.now() - start}ms`);
|
||
status = true; // 设置匹配成功状态
|
||
return { success: true, x: clickResult.x, y: clickResult.y };
|
||
}
|
||
}
|
||
// await sleep(200); // 短暂延迟,避免过快循环
|
||
log.info(`【OCR】${targetText}失败,正在进行第 ${retryCount++} 次重试...`);
|
||
}
|
||
} catch (error) {
|
||
log.warn(`【OCR】经过多次尝试,仍然无法识别文字: ”${targetText}“,尝试点击默认中心位置`);
|
||
await clickCenter(result.x, result.y, result.width, result.height);
|
||
//如果有配置通知……
|
||
notification.error(`【OCR】识别文字: “${targetText}”,发生异常`);
|
||
throw new Error(`【OCR】识别文字时发生异常: ${error.message}`);
|
||
}
|
||
return { success: false };
|
||
}
|
||
// 切换账号(OCR)版本
|
||
// ======================================================
|
||
|
||
// ======================================================
|
||
//切换账号DropDown
|
||
|
||
|
||
//切换账号DropDown
|
||
// ======================================================
|
||
|
||
(async function () {
|
||
// ======================================================
|
||
// Library functions
|
||
|
||
var u = {}; // utilities 工具函数集合
|
||
u.logi = function (message, args) { log.info("[切换账号]" + message, args) };
|
||
u.logw = function (message, args) { log.warn("[切换账号]" + message, args) };
|
||
u.loadTemplate = function (filePath, x /* 0 if omit */, y /* 0 if omit */, w /* maxWidth if omit */, h /* maxHeight if omit */) {
|
||
return RecognitionObject.TemplateMatch(file.ReadImageMatSync(filePath), x, y, w, h);
|
||
};
|
||
u.findText = function (resList, text) {
|
||
for (let i = 0; i < resList.count; i++) {
|
||
let res = resList[i];
|
||
if (res.text == text) {
|
||
return res;
|
||
}
|
||
}
|
||
return null;
|
||
};
|
||
u.matchUser = function (text, username) {
|
||
if (typeof text !== "string" || typeof username !== "string") return false;
|
||
if (text.length !== username.length) return false;
|
||
for (let i = 0; i < text.length; i++) {
|
||
const a = text[i];
|
||
const b = username[i];
|
||
if (a === '*' || b === '*') continue;
|
||
if (a !== b) return false;
|
||
}
|
||
return true;
|
||
};
|
||
u.matchUserRelaxed = function (text, username) {
|
||
if (typeof text !== "string" || typeof username !== "string") return false;
|
||
// Check the head
|
||
for (let i = 0; i < text.length; i++) {
|
||
const a = text[i];
|
||
const b = username[i];
|
||
if (a === '*') break; // Stop checking when a '*' is found in text.
|
||
if (a !== b) return false;
|
||
}
|
||
// Check the tail
|
||
for (let i = 0; i < text.length; i++) {
|
||
const a = text[text.length - 1 - i];
|
||
const b = username[username.length - 1 - i];
|
||
if (a === '*') break; // Stop checking when a '*' is found in text.
|
||
if (a !== b) return false;
|
||
}
|
||
return true;
|
||
};
|
||
u.waitAndFindImage = async function (asset, internal = 500, timeout = 60000) {
|
||
const start = Date.now();
|
||
let lastLog = start;
|
||
let endTime = start + timeout;
|
||
while (Date.now() < endTime) {
|
||
let captureRegion = captureGameRegion();
|
||
let res = captureRegion.Find(asset);
|
||
captureRegion.dispose();
|
||
if (!res.isEmpty()) {
|
||
return res;
|
||
}
|
||
if (Date.now() - lastLog >= 10000) {
|
||
let elapsed = ((Date.now() - start) / 1000).toFixed(1);
|
||
u.logw("等待匹配图像已持续 {0} 秒,仍在尝试寻找图像:{1}", elapsed, asset.Name);
|
||
lastLog = Date.now();
|
||
}
|
||
await sleep(internal);
|
||
}
|
||
return null;
|
||
}
|
||
u.waitAndFindText = async function (text, x, y, w, h, internal = 500) {
|
||
const start = Date.now();
|
||
let lastLog = start;
|
||
while (true) {
|
||
let captureRegion = captureGameRegion();
|
||
let resList = captureRegion.findMulti(RecognitionObject.ocr(x, y, w, h));
|
||
captureRegion.dispose();
|
||
if (typeof text === "string") {
|
||
let textFound = u.findText(resList, text);
|
||
if (textFound) {
|
||
return textFound;
|
||
}
|
||
} else if (text instanceof Array) {
|
||
var textFound = null;
|
||
for (let i = 0; i < text.length; i++) {
|
||
let textItem = text[i];
|
||
textFound = u.findText(resList, textItem);
|
||
if (!textFound) {
|
||
break;
|
||
}
|
||
}
|
||
if (textFound) {
|
||
return textFound;
|
||
}
|
||
}
|
||
|
||
if (Date.now() - lastLog >= 10000) {
|
||
let elapsed = ((Date.now() - start) / 1000).toFixed(1);
|
||
u.logw("等待匹配图像已持续 {0} 秒,仍在尝试寻找文字:{1}", elapsed, text.toString());
|
||
lastLog = Date.now();
|
||
}
|
||
await sleep(internal);
|
||
}
|
||
}
|
||
|
||
// ======================================================
|
||
// Setup
|
||
|
||
const targetUser = settings.username;
|
||
|
||
const assetLogoutIcon = u.loadTemplate("Assets/RecognitionObject/logout.png", 1750, 900, 170, 180);
|
||
const assetPaimonMenuIcon = u.loadTemplate("Assets/RecognitionObject/paimon_menu.png", 0, 0, 150, 150);
|
||
|
||
// Check current state
|
||
|
||
/**
|
||
* 领取空月祝福
|
||
*/
|
||
async function useBlessingOfTheWelkinMoon() {
|
||
u.logi("开始尝试领取空月祝福");
|
||
|
||
let captureRegion = captureGameRegion();
|
||
let resList = captureRegion.findMulti(RecognitionObject.ocrThis);
|
||
captureRegion.dispose();
|
||
|
||
for (let i = 0; i < resList.count; i++) {
|
||
let res = resList[i];
|
||
if (res.text.includes("点击领取") || res.text.includes("空月祝福")) {
|
||
res.click();
|
||
await sleep(500);
|
||
res.click();
|
||
res.click();
|
||
await sleep(500);
|
||
}
|
||
}
|
||
|
||
let captureRegionGetReward = captureGameRegion();
|
||
let resGetReward = captureRegionGetReward.findMulti(RecognitionObject.ocrThis);
|
||
captureRegionGetReward.dispose();
|
||
for (let i = 0; i < resGetReward.count; i++) {
|
||
let res = resGetReward[i];
|
||
if (res.text.includes("点击") || res.text.includes("空白") || res.text.includes("获得")) {
|
||
res.click();
|
||
await sleep(500);
|
||
}
|
||
}
|
||
|
||
u.logi("空月祝福领取成功");
|
||
}
|
||
|
||
async function waitAndDetermineCurrentView() {
|
||
u.logi("开始判断当前画面状态");
|
||
while (true) {
|
||
let captureRegion = captureGameRegion();
|
||
let res = captureRegion.Find(assetLogoutIcon);
|
||
let logoutIconFound = !res.isEmpty();
|
||
|
||
if (logoutIconFound) {
|
||
let resList = captureRegion.findMulti(RecognitionObject.ocr(850, 970, 220, 100));
|
||
captureRegion.dispose();
|
||
if (u.findText(resList, "点击进入")) {
|
||
u.logi("检测到目前处于登录界面");
|
||
return false;
|
||
}
|
||
}
|
||
|
||
// 尝试领取空月祝福
|
||
await useBlessingOfTheWelkinMoon();
|
||
|
||
// Not in the login screen, check if is in the game main menu.
|
||
let paimonIcon = captureRegion.Find(assetPaimonMenuIcon);
|
||
captureRegion.dispose();
|
||
if (!paimonIcon.isEmpty()) {
|
||
u.logi("检测到目前处于游戏主界面");
|
||
return true;
|
||
}
|
||
|
||
// Not in the main game screen either, wait and try again.
|
||
u.logi("未检测到登出按钮或派蒙菜单图标,可能处于游戏中,等待状态变化");
|
||
genshin.blessingOfTheWelkinMoon();
|
||
moveMouseTo(960, 0);
|
||
await sleep(100);
|
||
middleButtonClick();
|
||
genshin.returnMainUi();
|
||
await sleep(4900);
|
||
}
|
||
}
|
||
|
||
async function stateReturnToGenshinGate() {
|
||
const assetPaimonCancelIcon = u.loadTemplate("Assets/RecognitionObject/paimon_cancel.png", 0, 0, 100, 100);
|
||
|
||
while (true) {
|
||
let paimonIcon = await u.waitAndFindImage(assetPaimonMenuIcon, 500, 1000);
|
||
if (!paimonIcon) {
|
||
u.logi("检测到派蒙菜单图标不存在,可能已开启菜单,进入登出按钮识别流程");
|
||
break;
|
||
}
|
||
moveMouseTo(960, 0);
|
||
await sleep(100);
|
||
middleButtonClick();
|
||
keyPress("VK_ESCAPE");
|
||
u.logi("已按下ESC键,打开派蒙菜单");
|
||
await sleep(1000);
|
||
}
|
||
|
||
// 识别派蒙菜单,点击登出按钮
|
||
await u.waitAndFindImage(assetPaimonCancelIcon);
|
||
// u.logi("点击登出按钮");
|
||
click(50, 1024);
|
||
|
||
// 退出至登录界面
|
||
let btnExitToLogin = await u.waitAndFindText("退出至登录界面", 680, 380, 540, 340);
|
||
// u.logi("检测到\"退出至登录界面\"按钮,点击");
|
||
// btnExitToLogin.DrawSelf("ExitToLoginBtn");
|
||
btnExitToLogin.Click();
|
||
}
|
||
|
||
async function stateLogout() {
|
||
u.logi("开始登出");
|
||
|
||
let btnLogout = await u.waitAndFindImage(assetLogoutIcon);
|
||
// u.logi("识别到登出按钮,点击");
|
||
btnLogout.DrawSelf("LogoutBtn");
|
||
btnLogout.Click();
|
||
|
||
const assetQuitTextButton = u.loadTemplate("Assets/RecognitionObject/quit.png", 680, 380, 1220, 700);
|
||
let btnQuit = await u.waitAndFindImage(assetQuitTextButton, 200);
|
||
// u.logi("识别到退出按钮,点击");
|
||
// btnQuit.DrawSelf("QuitBtn");
|
||
btnQuit.Click();
|
||
};
|
||
|
||
async function stateChangeUser() {
|
||
u.logi("开始切换账号");
|
||
await u.waitAndFindText(["进入游戏", "登录其他账号"], 680, 380, 540, 340, 200);
|
||
|
||
const assetSelectUserDropDownIcon = u.loadTemplate("Assets/RecognitionObject/caret.png", 680, 380, 1220, 700);
|
||
let captureRegion = captureGameRegion();
|
||
let res = captureRegion.Find(assetSelectUserDropDownIcon);
|
||
captureRegion.dispose();
|
||
if (res.isEmpty()) {
|
||
u.logi("未找到下拉菜单图标,点击硬编码的坐标(960, 500)展开菜单");
|
||
click(960, 500);
|
||
} else {
|
||
// u.logi("识别到下拉菜单,点击");
|
||
// res.DrawSelf("UserDropdown");
|
||
res.Click();
|
||
}
|
||
|
||
u.logi("开始从下拉列表选择账号");
|
||
var selectedUser = null;
|
||
{
|
||
const start = Date.now();
|
||
let lastLog = start;
|
||
while (selectedUser == null) {
|
||
await sleep(200);
|
||
|
||
let captureRegion = captureGameRegion();
|
||
let resList = captureRegion.findMulti(RecognitionObject.ocr(680, 540, 540, 500));
|
||
captureRegion.dispose();
|
||
for (let i = 0; i < resList.count; i++) {
|
||
let res = resList[i];
|
||
let user = lastLog > start ? u.matchUserRelaxed(res.text, targetUser) : u.matchUser(res.text, targetUser);
|
||
if (user) {
|
||
selectedUser = res;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (Date.now() - lastLog >= 10000) {
|
||
let elapsed = ((Date.now() - start) / 1000).toFixed(1);
|
||
u.logw("等待匹配图像已持续 {0} 秒,仍在尝试寻找账号文本:{1}", elapsed, targetUser);
|
||
lastLog = Date.now();
|
||
for (let i = 0; i < resList.count; i++) {
|
||
let res = resList[i];
|
||
u.logw("账户文本:{0}", res.text);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
u.logi("识别到目标账号:{0}", selectedUser.text);
|
||
selectedUser.DrawSelf("SelectUser");
|
||
selectedUser.Click();
|
||
|
||
await sleep(500);
|
||
{
|
||
let captureRegion = captureGameRegion();
|
||
let btnEnterGame = captureRegion.DeriveCrop(684, 598, 552, 66);
|
||
btnEnterGame.Click();
|
||
captureRegion.dispose();
|
||
btnEnterGame.dispose();
|
||
// btnEnterGame.DrawSelf("EnterGameBtn");
|
||
// u.logi("已点击\"进入游戏\"按钮,完成账号选择。");
|
||
}
|
||
}
|
||
|
||
async function stateEnterGame() {
|
||
// u.logi("开始进入游戏,等待游戏加载。");
|
||
let textClickToStart = await u.waitAndFindText("点击进入", 850, 970, 220, 100);
|
||
// u.logi("已识别到\"点击进入\"文本,点击鼠标进入游戏。");
|
||
textClickToStart.DrawSelf("ClickToStart");
|
||
textClickToStart.Click();
|
||
}
|
||
|
||
// ======================================================
|
||
// Main flow
|
||
|
||
if (await uidUtil.check()) {
|
||
log.info("当前UID与设置UID相同,无需切换账号。");
|
||
return
|
||
}
|
||
if (settings.Modes == "下拉列表") {
|
||
await DropDownMode();
|
||
} else if (settings.Modes == "账号+密码") {
|
||
await KeyboardMouseMode();
|
||
} else if (settings.Modes == "账号+密码+OCR") {
|
||
await OcrMode();
|
||
} else if (settings.Modes == "B服切换另一个账号纯键鼠") {
|
||
await BilibiliKeyboardMouseMode();
|
||
} else if (settings.Modes == "B服切换另一个账号匹配+键鼠") {
|
||
await BilibiliMatchAndKeyboardMouseMode();
|
||
} else {
|
||
log.info("尖尖哇嘎乃")
|
||
}
|
||
|
||
// 下拉列表模式
|
||
async function DropDownMode() {
|
||
const isInGame = await waitAndDetermineCurrentView();
|
||
if (isInGame) {
|
||
await stateReturnToGenshinGate();
|
||
await sleep(1000);
|
||
}
|
||
await stateLogout();
|
||
await sleep(500);
|
||
await stateChangeUser();
|
||
await sleep(500);
|
||
await stateEnterGame();
|
||
await sleep(20000);
|
||
await waitAndDetermineCurrentView();
|
||
|
||
}
|
||
|
||
// 纯键鼠模式 对应:账号+密码(根据分辨率确定鼠标位置)
|
||
async function KeyboardMouseMode() {
|
||
setGameMetrics(1920, 1080, 2.0);
|
||
//到达主页面
|
||
await genshin.returnMainUi();//使用新号(无派蒙)测试,请注释掉这一行
|
||
await sleep(1000);
|
||
|
||
//打开派蒙页面
|
||
keyPress("VK_ESCAPE");
|
||
await sleep(1000);
|
||
|
||
//退出门图标
|
||
click(50, 1030);
|
||
await sleep(1000);
|
||
|
||
//退出至登录页面
|
||
click(978, 540);
|
||
await sleep(15000);
|
||
|
||
//登录页面退出当前账号的小门图标
|
||
click(1828, 985);
|
||
await sleep(1000);
|
||
|
||
//点击退出当前账号
|
||
if (Account == "否") {
|
||
//长期账号->勾选:退出并保留登录记录
|
||
click(698, 568);
|
||
} else {
|
||
//临时账号->勾选:退出并清除登录记录
|
||
click(698, 476);
|
||
}
|
||
await sleep(1000);
|
||
|
||
//点击退出大按钮
|
||
click(1107, 684);
|
||
await sleep(1500);
|
||
|
||
//登录其他账号
|
||
click(946, 703);
|
||
await sleep(1000);
|
||
|
||
//点击用户名输入框
|
||
click(815, 400);
|
||
//如果有文本,清除
|
||
await keyPress("VK_DELETE");
|
||
// 输入文本
|
||
await inputText(settings.username);
|
||
await sleep(500);
|
||
|
||
//点击密码输入框
|
||
click(815, 480);
|
||
//如果有文本,清除
|
||
await keyPress("VK_DELETE");
|
||
// 输入文本
|
||
await inputText(settings.password);
|
||
await sleep(500);
|
||
|
||
//回车弹出协议确定框(如果有的话)
|
||
for (let i = 0; i < 3; i++) {
|
||
//三次回车,规避强制点击进入游戏(如果开启了自动开门功能,这一步是必须的,后续维护者须知0.54.0版本对开门的“进入游戏”识别是和配置组同时进行的。多次回车+短时间点击,可以规避掉鼠标乱点的问题。彩虹QQ人于2026年1月5日留。)
|
||
keyPress("VK_RETURN");
|
||
await sleep(500);
|
||
//用户协议弹窗,点击同意,等待8.5s,增加容错
|
||
click(1093, 593);
|
||
await sleep(500);
|
||
}
|
||
await sleep(8000);//这一步根据各自网络环境和主机配置可以适当增减
|
||
|
||
//进入世界循环点击,增加容错
|
||
for (let i = 5; i > 0; i--) {
|
||
click(960, 540);
|
||
await sleep(1200);//增加容错(例如进入人机验证时)
|
||
}
|
||
//确保进入主页面
|
||
await sleep(12000);
|
||
//点击领月卡
|
||
await genshin.blessingOfTheWelkinMoon();
|
||
}
|
||
|
||
// OCR模式 对应:账号+密码+OCR
|
||
async function OcrMode() {
|
||
setGameMetrics(1920, 1080, 1);
|
||
// 如果切换账号是第一个脚本,则有可能出现月卡选项
|
||
//防止genshin.blessingOfTheWelkinMoon();方法失效,先使用物理点击。
|
||
try {
|
||
keyDown("VK_MENU");
|
||
await sleep(500);
|
||
for (let i = 0; i <= 4; i++) {
|
||
await click(960, 864);
|
||
await sleep(1000);
|
||
}
|
||
} finally {
|
||
keyUp("VK_MENU");
|
||
}
|
||
//await genshin.blessingOfTheWelkinMoon();
|
||
//await sleep(1000);
|
||
//await genshin.blessingOfTheWelkinMoon();
|
||
//await sleep(1000);
|
||
await genshin.returnMainUi();
|
||
|
||
await keyPress("VK_ESCAPE");
|
||
await sleep(500);
|
||
try {
|
||
await matchImgAndClick(pm_out, "左下角退出门");
|
||
await matchImgAndClick(out_to_login, "退出至登陆页面");
|
||
//这一步根据 电脑配置和当前网络情况不同休眠时间不同,建议实际运行之后,如果有日志 : 第x次 识别失败,就适当增加休眠时间
|
||
await sleep(9000);
|
||
await matchImgAndClick(login_out_account, "登录页的右下角退出按钮");
|
||
await matchImgAndClick(out_account, "退出当前账号");
|
||
await recognizeTextAndClick("登录其他账号", RecognitionObject.Ocr(300, 200, 1200, 800), 5000);
|
||
await sleep(1000);
|
||
await matchImgAndClick(input_phone_or_email, "填写邮箱/手机号");
|
||
await inputText(settings.username);
|
||
await sleep(1000);
|
||
await matchImgAndClick(input_password, "填写密码");
|
||
await inputText(settings.password);
|
||
await sleep(1000);
|
||
//按下回车登录账号,弹出用户协议对话框
|
||
await keyPress("VK_RETURN");
|
||
//点击回车后,等待特瓦特大门加载
|
||
await matchImgAndClick(agree, "同意用户协议");
|
||
//如果当天上下线次数过于频繁
|
||
for (let i = 1; i <= 2; i++) {
|
||
const ro = captureGameRegion();
|
||
let verify = ro.Find(login_verification.template);
|
||
ro.dispose();
|
||
//等待1s避免循环速度过快
|
||
await sleep(1000);
|
||
if (verify.isExist()) {
|
||
//这里可配置通知方法
|
||
notification.error(`${script_name}触发人机验证,请手动登录。===待切换账号:${settings.username}`);
|
||
log.error(`${script_name}触发人机验证,请手动登录。===待切换账号:${settings.username}`);
|
||
}
|
||
}
|
||
/**
|
||
* 根据不同网络环境和电脑配置,此操作可能会将领取月卡操作取代,但是不影响使用
|
||
* 如果发现卡在这一步,请适当延长sleep时间
|
||
*/
|
||
await sleep(8000);
|
||
await recognizeTextAndClick("点击进入", RecognitionObject.Ocr(862, 966, 206, 104), 5000);
|
||
await sleep(15000);
|
||
|
||
//可能登录账号的时候出现月卡提醒,则先点击一次月卡。
|
||
//await genshin.blessingOfTheWelkinMoon();
|
||
//await sleep(1000);
|
||
//await genshin.blessingOfTheWelkinMoon();
|
||
//await sleep(1000);
|
||
//防止genshin.blessingOfTheWelkinMoon();方法失效,先使用物理点击。
|
||
await sleep(2000);
|
||
keyDown("VK_MENU");
|
||
await sleep(500);
|
||
for (let i = 0; i <= 4; i++) {
|
||
await click(960, 864);
|
||
await sleep(1000);
|
||
}
|
||
//keyUp("VK_MENU");
|
||
await genshin.returnMainUi();
|
||
await sleep(1000);
|
||
// 如果配置了通知
|
||
notification.send("账号【" + settings.username + "】切换成功");
|
||
} catch (error) {
|
||
log.error(`${script_name}脚本执行过程中发生错误:${error.message}`);
|
||
//如果发生错误,则发送通知
|
||
notification.error(`${script_name}脚本执行过程中发生错误:${error.message}`);
|
||
throw new Error(`${script_name}脚本执行过程中发生错误:${error.message}`);
|
||
} finally {
|
||
keyUp("VK_MENU");
|
||
}
|
||
}
|
||
|
||
// B服切换纯键鼠模式 对应:B服切换另一个账号纯键鼠(根据分辨率确定鼠标位置)
|
||
async function BilibiliKeyboardMouseMode() {
|
||
setGameMetrics(1920, 1080, 2.0);
|
||
//到达主页面
|
||
await genshin.returnMainUi();//使用新号(无派蒙)测试,请注释掉这一行
|
||
await sleep(1000);
|
||
|
||
//打开派蒙页面
|
||
keyPress("VK_ESCAPE");
|
||
await sleep(1000);
|
||
|
||
//退出门图标
|
||
click(50, 1030);
|
||
await sleep(1000);
|
||
|
||
//退出至登录页面
|
||
click(978, 540);
|
||
await sleep(7000);
|
||
|
||
//登录其他账号
|
||
click(1135, 478);
|
||
await sleep(1000);
|
||
|
||
//点击用户名
|
||
click(963, 635);
|
||
await sleep(500);
|
||
|
||
//点击登录
|
||
click(963, 635);
|
||
await sleep(500);
|
||
|
||
//登录其他账号
|
||
click(1135, 478);
|
||
await sleep(1000);
|
||
|
||
//取消点击用户名(确保能登录)
|
||
click(963, 400);
|
||
await sleep(500);
|
||
|
||
//点击登录
|
||
click(963, 635);
|
||
await sleep(500);
|
||
|
||
//这一步根据各自网络环境和主机配置可以适当增减
|
||
await sleep(6000);
|
||
|
||
//进入世界循环点击,增加容错
|
||
for (let i = 5; i > 0; i--) {
|
||
click(960, 540);
|
||
await sleep(1200);//增加容错(例如进入人机验证时)
|
||
}
|
||
//确保进入主页面
|
||
await sleep(12000);
|
||
//点击领月卡
|
||
await genshin.blessingOfTheWelkinMoon();
|
||
}
|
||
|
||
// B服切换匹配+键鼠模式 对应:B服切换另一个账号匹配+键鼠
|
||
async function BilibiliMatchAndKeyboardMouseMode() {
|
||
setGameMetrics(1920, 1080, 1);
|
||
// 如果切换账号是第一个脚本,则有可能出现月卡选项
|
||
//防止genshin.blessingOfTheWelkinMoon();方法失效,先使用物理点击。
|
||
try {
|
||
keyDown("VK_MENU");
|
||
await sleep(500);
|
||
for (let i = 0; i <= 4; i++) {
|
||
await click(960, 864);
|
||
await sleep(1000);
|
||
}
|
||
} finally {
|
||
keyUp("VK_MENU");
|
||
}
|
||
//await genshin.blessingOfTheWelkinMoon();
|
||
//await sleep(1000);
|
||
//await genshin.blessingOfTheWelkinMoon();
|
||
//await sleep(1000);
|
||
await genshin.returnMainUi();
|
||
|
||
await keyPress("VK_ESCAPE");
|
||
await sleep(500);
|
||
try {
|
||
await matchImgAndClick(pm_out, "左下角退出门");
|
||
await matchImgAndClick(out_to_login, "退出至登陆页面");
|
||
//这一步根据 电脑配置和当前网络情况不同休眠时间不同,建议实际运行之后,如果有日志 : 第x次 识别失败,就适当增加休眠时间
|
||
await sleep(7000);
|
||
|
||
//登录其他账号
|
||
click(1135, 478);
|
||
await sleep(1000);
|
||
|
||
//点击用户名
|
||
click(963, 635);
|
||
await sleep(500);
|
||
|
||
//点击登录
|
||
click(963, 635);
|
||
await sleep(500);
|
||
|
||
//登录其他账号
|
||
click(1135, 478);
|
||
await sleep(1000);
|
||
|
||
//取消点击用户名(确保能登录)
|
||
click(963, 400);
|
||
await sleep(500);
|
||
|
||
//点击登录
|
||
click(963, 635);
|
||
await sleep(500);
|
||
|
||
//如果当天上下线次数过于频繁
|
||
for (let i = 1; i <= 2; i++) {
|
||
const ro = captureGameRegion();
|
||
let verify = ro.Find(login_verification.template);
|
||
ro.dispose();
|
||
//等待1s避免循环速度过快
|
||
await sleep(1000);
|
||
if (verify.isExist()) {
|
||
//这里可配置通知方法
|
||
notification.error(`${script_name}触发人机验证,请手动登录。===待切换账号:${settings.username}`);
|
||
log.error(`${script_name}触发人机验证,请手动登录。===待切换账号:${settings.username}`);
|
||
}
|
||
}
|
||
/**
|
||
* 根据不同网络环境和电脑配置,此操作可能会将领取月卡操作取代,但是不影响使用
|
||
* 如果发现卡在这一步,请适当延长sleep时间
|
||
*/
|
||
await sleep(6500);
|
||
await recognizeTextAndClick("点击进入", RecognitionObject.Ocr(862, 966, 206, 104), 5000);
|
||
await sleep(12000);
|
||
|
||
//可能登录账号的时候出现月卡提醒,则先点击一次月卡。
|
||
//await genshin.blessingOfTheWelkinMoon();
|
||
//await sleep(1000);
|
||
//await genshin.blessingOfTheWelkinMoon();
|
||
//await sleep(1000);
|
||
//防止genshin.blessingOfTheWelkinMoon();方法失效,先使用物理点击。
|
||
await sleep(2000);
|
||
keyDown("VK_MENU");
|
||
await sleep(500);
|
||
for (let i = 0; i <= 4; i++) {
|
||
await click(960, 864);
|
||
await sleep(1000);
|
||
}
|
||
//keyUp("VK_MENU");
|
||
await genshin.returnMainUi();
|
||
await sleep(1000);
|
||
// 如果配置了通知
|
||
notification.send("账号【" + settings.username + "】切换成功");
|
||
} catch (error) {
|
||
log.error(`${script_name}脚本执行过程中发生错误:${error.message}`);
|
||
//如果发生错误,则发送通知
|
||
notification.error(`${script_name}脚本执行过程中发生错误:${error.message}`);
|
||
throw new Error(`${script_name}脚本执行过程中发生错误:${error.message}`);
|
||
} finally {
|
||
keyUp("VK_MENU");
|
||
}
|
||
}
|
||
})();
|