尘歌壶一条龙 (#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>
This commit is contained in:
413
repo/js/尘歌壶一条龙/main.js
Normal file
413
repo/js/尘歌壶一条龙/main.js
Normal file
@@ -0,0 +1,413 @@
|
||||
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();
|
||||
14
repo/js/尘歌壶一条龙/manifest.json
Normal file
14
repo/js/尘歌壶一条龙/manifest.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"manifest_version": 1,
|
||||
"name": "尘歌壶一条龙",
|
||||
"version": "1.0",
|
||||
"description": "自动放置并进入尘歌壶,寻找阿圆,领取洞天宝钱和好感,做饭,锻造(需要配置进入尘歌壶以后的路线),支持自动购买指定物品。推荐洞天摹数81708444664",
|
||||
"authors": [
|
||||
{
|
||||
"name": "miludelongwang",
|
||||
"link": "https://github.com/miludelongwang/GI-Model-Importer"
|
||||
}
|
||||
],
|
||||
"settings_ui": "settings.json",
|
||||
"main": "main.js"
|
||||
}
|
||||
22
repo/js/尘歌壶一条龙/settings.json
Normal file
22
repo/js/尘歌壶一条龙/settings.json
Normal file
@@ -0,0 +1,22 @@
|
||||
[
|
||||
{
|
||||
"name": "route",
|
||||
"type": "input-text",
|
||||
"label": "进入尘歌壶以后寻找阿圆的路径\n填写规则:方向键+空格+时间(单位:毫秒)\n多个路径用英文逗号隔开,示例:A 1800,S 1300\n示例配套洞天摹数81708444664"
|
||||
},
|
||||
{
|
||||
"name": "itemsToBuy",
|
||||
"type": "input-text",
|
||||
"label": "想要购买的物品名称,支持只填写部分文字\n多个物品用英文逗号隔开,例如:祝圣精华,树脂"
|
||||
},
|
||||
{
|
||||
"name": "forgingRoute",
|
||||
"type": "input-text",
|
||||
"label": "锻造路径(格式同上),示例:D 2000\n周一自动执行"
|
||||
},
|
||||
{
|
||||
"name": "cookingRoute",
|
||||
"type": "input-text",
|
||||
"label": "烹饪路径(格式同上),示例:W 1000\n周一自动执行"
|
||||
}
|
||||
]
|
||||
Reference in New Issue
Block a user