Files
迷路の龙王 866dc23a7e 尘歌壶一条龙 (#932)
* Update and rename readme.txt to readme.md

* Update readme.md

* Update and rename readme.md to README.md

* Update main.js

* Update manifest.json

* Update README.md

* Update README.md

* Add files via upload

* Add files via upload

* Add files via upload

* Update repo/js/尘歌壶一条龙/manifest.json

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: 秋云 <physligl@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-05-27 14:03:08 +08:00

414 lines
13 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.

async function main() {
const today = new Date().getDay();
const isMonday = today === 1;
// 检查是否为周一,周三或周六
if (!isScheduledDay()) {
log.info("今日非周一,周三或周六,脚本不执行");
return;
}
// 检查配置
checkSettings();
// 打开背包并切换到小道具
await openBackpack();
// 查找并使用尘歌壶
await findAndUseSereniteaPot();
// 等待进入尘歌壶
await waitForEnteringSereniteaPot();
// 找到阿圆
await moveToTarget(settings.route);
// 与阿圆对话
keyPress("F");
await sleep(2000);
click(960, 540);
await sleep(2000);
// 领取好感度以及洞天宝钱
await collectRewards();
if (isMonday) {
log.info("今天是周一,兑换物品");
// 兑换物品
await exchangeItems();
}
// 关闭与阿圆的对话
await sleep(1000)
click(1360, 800);
await sleep(1000);
click(960, 540);
// 周一执行锻造任务和烹饪任务
if (isMonday) {
log.info("今天是周一,执行锻造任务");
if (settings.forgingRoute) await handleForging();
log.info("今天是周一,执行烹饪任务");
if (settings.cookingRoute) await handleCooking();
keyDown("a");
await sleep(2000);
keyUp("a");
}
}
//============== 烹饪功能 ==============//
async function handleCooking() {
log.info("开始自动烹饪");
try {
// 移动到烹饪点
await moveToTarget(settings.cookingRoute);
// 执行烹饪操作序列
keyPress("F"); await sleep(1000);
click(1695, 1013); await sleep(1000); // 选择料理台
click(785, 1015); await sleep(500); // 选择自动制作
click(1018, 452); await sleep(500); // 选择制作
keyPress("2"); await sleep(200); // 选择数量
keyPress("0"); await sleep(200);
click(1159, 755); await sleep(2000); // 确认制作
// 关闭界面
for(let i=0; i<3; i++) {
keyPress("Escape"); await sleep(500);
}
log.info("烹饪完成");
} catch (e) {
log.info("烹饪失败: " + e.message);
}
}
//============== 锻造功能 ==============//
async function handleForging() {
log.info("开始自动锻造");
try {
// 移动到锻造点
await moveToTarget(settings.forgingRoute);
// 执行锻造操作序列
keyPress("F"); await sleep(1500);
// 完成材料
for(let i=0; i<6; i++) {
click(1745, 1019); await sleep(300);
}
click(217, 152); await sleep(800); // 选择条目
click(546, 288); await sleep(1000); // 选择矿产
// 确认锻造
for(let i=0; i<3; i++) {
click(1745, 1019); await sleep(300);
}
keyPress("Escape"); await sleep(1000); // 关闭界面
log.info("锻造完成");
} catch (e) {
log.info("锻造失败: " + e.message);
}
}
// 判断当前是否为周一,周三或周六
function isScheduledDay() {
const today = new Date().getDay(); // 0=周日, 1=周一, ..., 6=周六
return today === 1 || today === 3 || today === 6; // 周一,周三或周六
}
async function exchangeItems() {
if (!settings.itemsToBuy) {
log.warn("未配置要购买的物品");
return;
}
log.info("开始兑换物品");
// 点击洞天百宝
click(1386, 655);
await sleep(1000);
// 点击第一个选项卡
click(712, 50)
await sleep(1000);
// 获取用户想要购买的物品列表
const itemsToBuy = settings.itemsToBuy.split(',').map(item => item.trim());
log.info(`要购买的物品: ${itemsToBuy.join(', ')}`);
// 设置固定的坐标
const firstItemX = 193;
const firstItemY = 196;
const xOffset = 168; // 水平方向上的间距
const yOffset = 190; // 垂直方向上的间距
const itemsPerRow = 7; // 每行物品数量
// 临时变量,已找到的物品数组和上一个物品名称变量
const foundItems = [];
let lastItemName = "";
// 遍历所有物品
outerLoop: for (let row = 0; row < 3; row++) {
for (let col = 0; col < itemsPerRow; col++) {
// 计算当前物品中心点坐标
const centerX = firstItemX + (xOffset * col);
const centerY = firstItemY + (yOffset * row);
// 需要重复检查这个位置的物品
let keepCheckingCurrentPosition = true;
// 循环检查当前位置的物品,直到不再找到匹配的物品
while (keepCheckingCurrentPosition) {
// 点击物品中心
click(centerX, centerY);
await sleep(1000);
// 获取物品详情区域截图
let screen = captureGameRegion();
let targetRegion = screen.DeriveCrop(1308, 120, 491, 56);
// 使用OCR识别物品名称
let ocrRo = RecognitionObject.Ocr(0, 0, targetRegion.Width, targetRegion.Height);
let ocrResult = targetRegion.find(ocrRo);
if (ocrResult.isEmpty()) {
throw new Error("无法识别物品名称,请检查具体原因");
}
const itemName = ocrResult.Text.trim();
// 检查是否与上一个物品名称相同
if (itemName === lastItemName) {
break outerLoop;
} else {
lastItemName = itemName;
}
// 检查物品是否已售罄
let soldOutRegion = screen.DeriveCrop(1308, 403, 491, 100);
let soldOutOcrRo = RecognitionObject.Ocr(0, 0, soldOutRegion.Width, soldOutRegion.Height);
let soldOutResult = soldOutRegion.find(soldOutOcrRo);
// 如果发现任何已售罄的物品,就认为所有可购买的物品都已检查过,结束搜索
log.debug(`识别到的文字: ${soldOutResult.Text}`)
if (!soldOutResult.isEmpty() && soldOutResult.Text.includes("已售罄")) {
break outerLoop;
}
// 检查是否是用户想要购买的物品(使用包含关系)
let matchedItem = itemsToBuy.find(item => itemName.includes(item));
if (matchedItem) {
log.info(`找到要购买的物品: ${itemName} (匹配: ${matchedItem})`);
// 记录已找到的物品
if (!foundItems.includes(matchedItem)) {
foundItems.push(matchedItem);
}
log.info(`开始购买物品: ${itemName}`);
// 执行购买流程
// 1. 鼠标移动到起始位置
moveMouseTo(1448, 693);
await sleep(300);
// 2. 按下鼠标左键
leftButtonDown();
await sleep(300);
// 3. 移动到结束位置
moveMouseTo(1753, 693);
await sleep(300);
// 4. 松开鼠标左键
leftButtonUp();
await sleep(500);
// 5. 点击确认按钮
click(1698, 1022);
await sleep(1000);
// 6. 关闭弹窗
click(962, 763);
await sleep(1000);
log.info(`成功购买物品: ${itemName}`);
// 检查是否已找到所有物品
if (foundItems.length === itemsToBuy.length) {
log.info("已找到所有需要购买的物品,提前结束搜索");
break outerLoop;
}
} else {
// 如果不匹配,不继续检查当前位置
keepCheckingCurrentPosition = false;
}
}
}
}
// 如果浏览完所有格子后仍有未找到的物品
const notFound = itemsToBuy.filter(item => !foundItems.includes(item));
if (notFound.length > 0) {
log.warn(`浏览完所有物品后,以下物品未找到或已售罄: ${notFound.join(', ')}`);
}
// 关闭兑换页面
await sleep(1000);
click(1841, 47)
await sleep(1000);
}
// 检查配置
function checkSettings() {
if (!settings.route) {
log.warn("当前未配置进入尘歌壶以后的路线,脚本可能无法正常运行");
}
// 记录是否跳过领取角色好感和洞天宝钱
if (settings.skipCharacterReward) {
log.info("当前配置:不领取角色好感");
}
if (settings.skipTreasureReward) {
log.info("当前配置:不领取洞天宝钱");
}
}
// 打开背包并切换到小道具
async function openBackpack() {
keyPress("B");
await sleep(1000);
click(1048, 50);
await sleep(1000);
}
// 查找并使用尘歌壶
async function findAndUseSereniteaPot() {
await findSereniteaPot();
await sleep(1000);
keyPress("F");
}
// 等待进入尘歌壶
async function waitForEnteringSereniteaPot() {
// 先等待5秒应该不会比这快
await sleep(5000);
// 等待传送完成
let isEntering = true;
while (isEntering) {
let screen = captureGameRegion();
let targetRegion = screen.DeriveCrop(85, 1025, 69, 28);
let ocrRo = RecognitionObject.Ocr(0, 0, targetRegion.Width, targetRegion.Height);
let ocrResult = targetRegion.find(ocrRo);
if (ocrResult.Text.toLowerCase().includes("enter")) {
isEntering = false;
}
await sleep(1000);
}
// 进入尘歌壶以后等待1秒
await sleep(1000);
}
// 移动到阿圆并领取奖励
async function collectRewards() {
log.info("开始领取好感度以及洞天宝钱");
click(1370, 432);
await sleep(1000);
// 领取好感度
if (!settings.skipCharacterReward) {
log.info("领取角色好感度");
click(1810, 715);
await sleep(1000);
// 关闭洞天赠礼弹窗
click(1346, 300);
await sleep(1000);
} else {
log.info("根据自定义配置,跳过领取角色好感度");
}
// 领取洞天宝钱
if (!settings.skipTreasureReward) {
log.info("领取洞天宝钱");
click(1080, 929);
await sleep(1000);
// 关闭洞天财瓮弹窗
click(1346, 300);
await sleep(1000);
} else {
log.info("根据自定义配置,跳过领取洞天宝钱");
}
// 关闭对话
click(1864, 47);
await sleep(3000);
}
async function findSereniteaPot() {
let currentX = 178; // 起始X坐标
let searchCount = 0; // 添加查找次数计数器
const MAX_SEARCH_COUNT = 5; // 最大查找次数
while (searchCount < MAX_SEARCH_COUNT) {
searchCount++;
// 点击当前坐标的小道具
click(currentX, 188);
await sleep(1000);
// 获取游戏区域截图
let screen = captureGameRegion();
// 根据指定区域进行剪裁
let targetRegion = screen.DeriveCrop(1307, 119, 493, 55);
// 使用OCR识别
let ocrRo = RecognitionObject.Ocr(0, 0, targetRegion.Width, targetRegion.Height);
let ocrResult = targetRegion.find(ocrRo);
if (!ocrResult.isEmpty() && ocrResult.Text.includes("尘歌壶")) {
// 点击指定坐标
click(1690, 1020);
await sleep(1000);
// 检查一下背包页面是否退出了,有可能当前角色状态没法放置尘歌壶,直接再判断一次截图区域文本是不是尘歌壶就行
let screen = captureGameRegion();
// 根据指定区域进行剪裁
let targetRegion = screen.DeriveCrop(1307, 119, 493, 55);
let ocrRo = RecognitionObject.Ocr(0, 0, targetRegion.Width, targetRegion.Height);
let ocrResult = targetRegion.find(ocrRo);
if (!ocrResult.isEmpty() && ocrResult.Text.includes("尘歌壶")) {
throw new Error("当前无法放置尘歌壶,请检查具体原因");
}
return;
} else {
currentX += 145; // 向右移动145像素查找下一个格子的小道具
await sleep(100);
}
}
throw new Error(`查找尘歌壶次数超过${MAX_SEARCH_COUNT}次,请检查背包是否存在尘歌壶`);
}
async function moveToTarget(routeConfig) {
if (!routeConfig) return;
const routes = routeConfig.split(',').map(r => r.trim());
for (const route of routes) {
const [direction, time] = route.split(' ');
if (!direction || !time) continue;
keyDown(direction);
await sleep(parseInt(time));
keyUp(direction);
await sleep(500);
}
}
main();