mirror of
https://github.com/babalae/bettergi-scripts-list.git
synced 2026-04-04 06:46:19 +08:00
YNF-AutoEat-V1.4与AutoMonday-V1.1版本更新 (#1988)
* AutoMonday-V1.1 1. 修复了爱可菲在做菜过程中偶现的被电死的bug 2. 完善了拦截背包过期物品的功能,不用每次打开背包之后再重复点击了! 3. 添加了cd验证功能,无需每次运行再开地图识别,cd依靠Uid存在,相关数据储存留存在本地,不用担心id泄露风险,同时,保留了原来的诱捕完成提示作为二级验证,识别有误也不用担心! 4. 进一步修改了cd一致的逻辑:当诱捕装置刷新但质变仪未刷新时不会干等质变仪刷新,而是会继续执行,等诱捕装置下次刷新之后再三者一起使用。 * YNF-AutoEat-V1.4 1. 修复了运行次数为某些值时运行结束前往神像之后还会回到秘境的bug 2. 添加了更为完善的过期物品拦截机制,不用再傻乎乎的每次点击同一位置了!(感谢糖雕老师以身殉道提供海量素材~)
This commit is contained in:
@@ -47,6 +47,11 @@
|
||||
2. 感谢茶包大佬,本脚本的框架、逻辑、以及部分代码都是从这位大佬的代码中获取的,甚至创作灵感也是(茶包老师还是太全面了~)
|
||||
---------------------------------------------------------------------------------------------------------------------------------
|
||||
## 更新日志
|
||||
### 1.1(2025.09.24)
|
||||
1. 修复了爱可菲在做菜过程中偶现的被电死的bug(做菜做到一半人没了?别担心,后续不会再有这种情况了!!!)
|
||||
2. 完善了拦截背包过期物品的功能,不用每次打开背包之后再重复点击了!
|
||||
3. 添加了cd验证功能,无需每次运行再开地图识别,cd依靠Uid存在,相关数据储存留存在本地,不用担心id泄露风险,同时,保留了原来的诱捕完成提示作为二级验证,识别有误也不用担心!
|
||||
4. 进一步修改了cd一致的逻辑:当诱捕装置刷新但质变仪未刷新时不会干等质变仪刷新,而是会继续执行,等诱捕装置下次刷新之后再三者一起使用。
|
||||
### 1.0(2025.09.20)
|
||||
1. 酱酱!“全自动周一(AutoMonday) V1.0”闪亮登场!
|
||||
1. 你还在为每周的爱可菲做菜而痛苦吗?你每周的质变仪又忘记用了吗?你每周的晶蝶诱捕装置又忘记收取了吗?
|
||||
|
||||
@@ -21,10 +21,10 @@
|
||||
}
|
||||
],
|
||||
"bgi_version": "0.45.0",
|
||||
"description": "基于电气水晶的全自动爱可菲",
|
||||
"description": "基于电气水晶的全自动爱可菲做菜",
|
||||
"enable_monster_loot_split": false,
|
||||
"items": [],
|
||||
"last_modified_time": 1758269208975,
|
||||
"last_modified_time": 1758611009216,
|
||||
"map_match_method": "",
|
||||
"map_name": "Teyvat",
|
||||
"name": "全自动爱可菲",
|
||||
@@ -36,6 +36,7 @@
|
||||
"positions": [
|
||||
{
|
||||
"action": "",
|
||||
"action_params": "",
|
||||
"id": 1,
|
||||
"move_mode": "walk",
|
||||
"point_ext_params": {
|
||||
@@ -55,7 +56,7 @@
|
||||
},
|
||||
{
|
||||
"action": "combat_script",
|
||||
"action_params": "爱可菲 e(hold)",
|
||||
"action_params": "爱可菲 e(hold),s(0.75)",
|
||||
"id": 2,
|
||||
"move_mode": "walk",
|
||||
"point_ext_params": {
|
||||
|
||||
@@ -7,15 +7,15 @@
|
||||
}
|
||||
],
|
||||
"bgi_version": "0.45.0",
|
||||
"description": "",
|
||||
"description": "诱捕位置:枫丹合成台旁边巷子口",
|
||||
"enable_monster_loot_split": false,
|
||||
"last_modified_time": 1756715619864,
|
||||
"map_match_method": "SIFT",
|
||||
"last_modified_time": 1758611261871,
|
||||
"map_match_method": "",
|
||||
"map_name": "Teyvat",
|
||||
"name": "晶蝶诱捕装置",
|
||||
"tags": [],
|
||||
"type": "collect",
|
||||
"version": "0.1"
|
||||
"version": "1.0"
|
||||
},
|
||||
"positions": [
|
||||
{
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
}
|
||||
|
||||
// 等待质变仪完成提示出现。 若超时则强制结束流程。
|
||||
async function waitTransformer() {
|
||||
async function waitTransformer(deployed) {
|
||||
var startTime = new Date();
|
||||
await sleep(500);
|
||||
var NowTime = new Date();
|
||||
@@ -96,15 +96,17 @@
|
||||
const intervalTime = 3000; // 3秒的时间间隔,单位为毫秒
|
||||
|
||||
// 质变仪判断逻辑
|
||||
while ((NowTime - startTime) < actiontime * 1000) {
|
||||
await textOCR("质变产生了以下物质", 0.7, 1, 0, 539, 251, 800, 425);
|
||||
if (result.found) {
|
||||
click(970, 760);
|
||||
if (!ifAkf) { return true; }
|
||||
await sleep(150);
|
||||
break;
|
||||
if (deployed) {
|
||||
while ((NowTime - startTime) < actiontime * 1000) {
|
||||
await textOCR("质变产生了以下物质", 0.7, 1, 0, 539, 251, 800, 425);
|
||||
if (result.found) {
|
||||
click(970, 760);
|
||||
if (!ifAkf) { return true; }
|
||||
await sleep(150);
|
||||
break;
|
||||
}
|
||||
NowTime = new Date();
|
||||
}
|
||||
NowTime = new Date();
|
||||
}
|
||||
|
||||
// 厨艺机关判断逻辑
|
||||
@@ -140,12 +142,7 @@
|
||||
await keyPress("B");
|
||||
await sleep(1000);
|
||||
|
||||
//连续点击三次防止过期道具卡背包
|
||||
await click(970, 760);
|
||||
await sleep(100);
|
||||
await click(970, 760);
|
||||
await sleep(100);
|
||||
await click(970, 760);
|
||||
await handleExpiredItems(); //处理过期物品
|
||||
|
||||
await sleep(1000);
|
||||
await click(1067, 57);//点开背包,可做图像识别优化
|
||||
@@ -272,6 +269,114 @@
|
||||
}
|
||||
}
|
||||
|
||||
// 背包过期物品识别,需要在背包界面,并且是1920x1080分辨率下使用
|
||||
async function handleExpiredItems() {
|
||||
const ifGuoqi = await textOCR("物品过期", 5, 0, 0, 870, 280, 170, 40);
|
||||
if (ifGuoqi.found) {
|
||||
log.info("检测到过期物品,正在处理...");
|
||||
await sleep(500);
|
||||
await click(980, 750); // 点击确认按钮,关闭提示
|
||||
} else {
|
||||
log.info("未检测到过期物品");
|
||||
}
|
||||
}
|
||||
|
||||
// 获取当前时间七天后的时间戳
|
||||
function getSevenDaysLater() {
|
||||
const now = new Date();
|
||||
const sevenDaysLater = new Date(now.getTime() + 7 * 24 * 60 * 60 * 1000); // 当前时间 + 7天
|
||||
return sevenDaysLater.toISOString();
|
||||
}
|
||||
|
||||
// 检查文件是否存在
|
||||
async function checkFileExists(filePath) {
|
||||
try {
|
||||
// 尝试读取文件,如果成功则文件存在
|
||||
await file.readText(filePath);
|
||||
return true;
|
||||
} catch (e) {
|
||||
// 如果读取失败,则文件可能不存在
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 读取CD记录
|
||||
async function readCDRecords() {
|
||||
let records = {};
|
||||
|
||||
// 使用基础方法检查文件是否存在
|
||||
const fileExists = await checkFileExists(cdRecordPath);
|
||||
if (fileExists) {
|
||||
try {
|
||||
const content = await file.readText(cdRecordPath);
|
||||
const lines = content.split('\n');
|
||||
|
||||
for (const line of lines) {
|
||||
if (line.trim()) {
|
||||
const [name, timestamp] = line.split('::');
|
||||
records[name] = timestamp;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
log.error(`读取CD记录失败: ${e}`);
|
||||
}
|
||||
}
|
||||
|
||||
return records;
|
||||
}
|
||||
|
||||
// 写入CD记录
|
||||
async function writeCDRecords(records) {
|
||||
let content = '';
|
||||
|
||||
for (const name in records) {
|
||||
content += `${name}::${records[name]}\n`;
|
||||
}
|
||||
|
||||
try {
|
||||
// 尝试创建目录(如果环境支持)
|
||||
try {
|
||||
if (typeof file.mkdir === 'function') {
|
||||
file.mkdir('record');
|
||||
}
|
||||
} catch (e) {
|
||||
// 忽略目录创建错误
|
||||
}
|
||||
|
||||
await file.writeText(cdRecordPath, content);
|
||||
} catch (e) {
|
||||
log.error(`写入CD记录失败: ${e}`);
|
||||
}
|
||||
}
|
||||
|
||||
// 检查路线是否可执行(CD是否已刷新)
|
||||
function isRouteAvailable(routeName, cdRecords) {
|
||||
const now = new Date();
|
||||
|
||||
// 如果记录中没有该路线,说明是第一次执行,可以执行
|
||||
if (!cdRecords[routeName]) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 检查CD时间是否已过
|
||||
const cdTime = new Date(cdRecords[routeName]);
|
||||
return now >= cdTime;
|
||||
}
|
||||
|
||||
// 获取当前账户id
|
||||
async function getCurrentUsername() {
|
||||
await genshin.returnMainUi();
|
||||
const texts = await textOCR("", 0.3, 0, 2, 1755, 1050, 110, 20);
|
||||
if (result.found) {
|
||||
log.debug("当前用户:" + texts.text);
|
||||
await genshin.returnMainUi();
|
||||
return texts.text;
|
||||
}
|
||||
log.info("未找到用户名");
|
||||
await genshin.returnMainUi();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
//main/======================================================================================
|
||||
|
||||
@@ -279,7 +384,7 @@
|
||||
if (!settings.ifCheck) { log.error("请阅读readme文件并做好相关设置后再运行此脚本!"); return; }
|
||||
|
||||
//初始化配置
|
||||
var actiontime = settings.actiontime != undefined && ~~settings.actiontime > 0 ? ~~settings.actiontime : 180;
|
||||
var actiontime = 180;//最大等待时间,单位秒
|
||||
var TEAM;
|
||||
var Material = settings.Material;
|
||||
var BH = `assets/RecognitionObject/${Material}.png`;
|
||||
@@ -300,6 +405,9 @@
|
||||
// 直接通过映射获取ITEM值(未匹配时默认0)
|
||||
ITEM = materialToItemMap[Material] || 0;
|
||||
|
||||
const routeName = "下次刷新时间";
|
||||
const username = await getCurrentUsername();
|
||||
const cdRecordPath = `record/${username}_cd.txt`;// 修改CD记录文件路径,包含用户名
|
||||
|
||||
//检查用户是否配置队伍
|
||||
if (ifAkf && settings.TEAMname === undefined) {
|
||||
@@ -314,6 +422,16 @@
|
||||
setGameMetrics(1920, 1080, 1);
|
||||
await genshin.returnMainUi();
|
||||
|
||||
// 读取CD记录
|
||||
const cdRecords = await readCDRecords();
|
||||
let updatedRecords = { ...cdRecords };
|
||||
|
||||
// 检查CD
|
||||
if (!isRouteAvailable(routeName, cdRecords)) {
|
||||
log.info("CD未刷新,跳过本次执行");
|
||||
return;
|
||||
}
|
||||
|
||||
// 打开地图
|
||||
keyPress("M");
|
||||
await sleep(1000);
|
||||
@@ -331,13 +449,14 @@
|
||||
await switchPartyIfNeeded(TEAM); //切换到指定队伍
|
||||
await AutoPath("全自动质变仪");
|
||||
|
||||
if (!await deployTransformer()) {
|
||||
throw new Error("质变仪未找到或在cd中");
|
||||
};//部署质变仪
|
||||
const deployed = await deployTransformer();//部署质变仪
|
||||
if (!deployed) {
|
||||
log.error("质变仪未找到或在cd中");
|
||||
} else {
|
||||
await insertMaterial();//放入材料并开始质变流程
|
||||
}
|
||||
|
||||
await insertMaterial()//放入材料并开始质变流程
|
||||
|
||||
await waitTransformer()//等待质变完成
|
||||
await waitTransformer(deployed)//等待质变完成
|
||||
log.info("任务执行完成!!!");
|
||||
|
||||
|
||||
@@ -360,6 +479,10 @@
|
||||
|
||||
log.info("已完成 领取晶蝶诱捕装置");
|
||||
await sleep(1000);
|
||||
|
||||
// 更新CD记录(设置为七天后)
|
||||
updatedRecords[routeName] = getSevenDaysLater();
|
||||
await writeCDRecords(updatedRecords);
|
||||
} catch (error) {
|
||||
log.error(`执行过程中发生错误:${error.message}`);
|
||||
} finally {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"manifest_version": 1,
|
||||
"name": "全自动周一",
|
||||
"version": "1.0",
|
||||
"version": "1.1",
|
||||
"tags": [
|
||||
"爱可菲",
|
||||
"质变仪",
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
2. 感谢氨气老师和秋秋云老师,在审核时提供了宝贵的意见和建议。
|
||||
---------------------------------------------------------------------------------------------------------------------------------
|
||||
## 更新日志
|
||||
### 1.4(2025.09.24)
|
||||
1. 修复了运行次数为某些值时运行结束前往神像之后还会回到秘境的bug
|
||||
2. 添加了更为完善的过期物品拦截机制,不用再傻乎乎的每次点击同一位置了!(感谢糖雕老师以身殉道提供海量素材~)
|
||||
### 1.3(2025.09.21)
|
||||
1. 添加了保证队友状态的逻辑:(队友:我有什么错!我又没有这个天赋! 伊涅芙:那我就有错了嘛!?)
|
||||
1. 运行脚本时会先去一次神像,确保满状态进副本
|
||||
|
||||
@@ -128,6 +128,59 @@
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 文字OCR识别封装函数(测试中,未封装完成,后续会优化逻辑)
|
||||
* @param text 要识别的文字,默认为"空参数"
|
||||
* @param timeout 超时时间,单位为秒,默认为10秒
|
||||
* @param afterBehavior 点击模式,0表示不点击,1表示点击识别到文字的位置,2表示输出模式,默认为0
|
||||
* @param debugmodel 调试代码,0表示输入判断模式,1表示输出位置信息,2表示输出判断模式,默认为0
|
||||
* @param x OCR识别区域的起始X坐标,默认为0
|
||||
* @param y OCR识别区域的起始Y坐标,默认为0
|
||||
* @param w OCR识别区域的宽度,默认为1920
|
||||
* @param h OCR识别区域的高度,默认为1080
|
||||
* @returns 包含识别结果的对象,包括识别的文字、坐标和是否找到的结果
|
||||
*/
|
||||
async function textOCR(text = "空参数", timeout = 10, afterBehavior = 0, debugmodel = 0, x = 0, y = 0, w = 1920, h = 1080) {
|
||||
const startTime = new Date();
|
||||
var Outcheak = 0
|
||||
for (var ii = 0; ii < 10; ii++) {
|
||||
// 获取一张截图
|
||||
var captureRegion = captureGameRegion();
|
||||
var res1
|
||||
var res2
|
||||
var conuntcottimecot = 1;
|
||||
var conuntcottimecomp = 1;
|
||||
// 对整个区域进行 OCR
|
||||
var resList = captureRegion.findMulti(RecognitionObject.ocr(x, y, w, h));
|
||||
//log.info("OCR 全区域识别结果数量 {len}", resList.count);
|
||||
if (resList.count !== 0) {
|
||||
for (let i = 0; i < resList.count; i++) { // 遍历的是 C# 的 List 对象,所以要用 count,而不是 length
|
||||
let res = resList[i];
|
||||
res1 = res.text
|
||||
conuntcottimecomp++;
|
||||
if (res.text.includes(text) && debugmodel == 3) { return result = { text: res.text, x: res.x, y: res.y, found: true }; }
|
||||
if (res.text.includes(text) && debugmodel !== 2) {
|
||||
conuntcottimecot++;
|
||||
log.info(`“${res1}”找到`);
|
||||
if (debugmodel === 1 & x === 0 & y === 0) { log.info("全图代码位置:({x},{y},{h},{w})", res.x - 10, res.y - 10, res.width + 10, res.Height + 10); } else { log.info("文本OCR完成'{text}'", res.text); }
|
||||
if (afterBehavior === 1) { log.info("点击模式:开"); await sleep(1000); click(res.x, res.y); } else { if (debugmodel === 1 & x === 0 & y === 0) { log.info("点击模式:关") } }
|
||||
if (afterBehavior === 2) { log.info("F模式:开"); await sleep(100); keyPress("F"); } else { if (debugmodel === 1 & x === 0 & y === 0) { log.info("F模式:关"); } }
|
||||
if (conuntcottimecot >= conuntcottimecomp / 2) { return result = { text: res.text, x: res.x, y: res.y, found: true }; } else { return result = { found: false }; }
|
||||
}
|
||||
if (debugmodel === 2) {
|
||||
if (res1 === res2) { conuntcottimecot++; res2 = res1; }
|
||||
//log.info("输出模式:全图代码位置:({x},{y},{h},{w},{string})", res.x-10, res.y-10, res.width+10, res.Height+10, res.text);
|
||||
if (Outcheak === 1) { if (conuntcottimecot >= conuntcottimecomp / 2) { return result = { text: res.text, x: res.x, y: res.y, found: true }; } else { return result = { found: false }; } }
|
||||
}
|
||||
}
|
||||
}
|
||||
const NowTime = new Date();
|
||||
if ((NowTime - startTime) > timeout * 1000) { if (debugmodel === 2) { if (resList.count === 0) { return result = { found: false }; } else { Outcheak = 1; ii = 2; } } else { Outcheak = 0; if (debugmodel === 1 & x === 0 & y === 0) { log.info(`${timeout}秒超时退出,"${text}"未找到`) }; return result = { found: false }; } }
|
||||
else { ii = 2; if (debugmodel === 1 & x === 0 & y === 0) { log.info(`"${text}"识别中……`); } }
|
||||
await sleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
//判断队内角色
|
||||
async function includes(characterName) {
|
||||
var avatars = getAvatars();
|
||||
@@ -193,6 +246,7 @@
|
||||
await sleep(5000);
|
||||
|
||||
await keyPress("B");
|
||||
await handleExpiredItems();//处理过期物品弹窗
|
||||
await sleep(1000);
|
||||
await click(860, 50);
|
||||
await sleep(1000);
|
||||
@@ -238,6 +292,19 @@
|
||||
|
||||
}
|
||||
|
||||
// 背包过期物品识别,需要在背包界面,并且是1920x1080分辨率下使用
|
||||
async function handleExpiredItems() {
|
||||
const ifGuoqi = await textOCR("物品过期", 1, 0, 0, 870, 280, 170, 40);
|
||||
if (ifGuoqi.found) {
|
||||
log.info("检测到过期物品,正在处理...");
|
||||
await sleep(500);
|
||||
await click(980, 750); // 点击确认按钮,关闭提示
|
||||
} else {
|
||||
log.info("未检测到过期物品");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ===== MAIN EXECUTION =====
|
||||
|
||||
@@ -285,7 +352,7 @@
|
||||
for (let i = 0; i < n; i++) {
|
||||
await doit();
|
||||
dieCount++;
|
||||
if (dieCount % 8 === 0) { //每8次回一次神像
|
||||
if (dieCount % 8 === 0 && dieCount != n) { //每8次回一次神像
|
||||
log.info("队友们的血量好像有点不太健康欸……先回去补一补!");
|
||||
await genshin.tpToStatueOfTheSeven();
|
||||
await sleep(500);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"manifest_version": 1,
|
||||
"name": "伊涅芙の自助餐",
|
||||
"version": "1.3",
|
||||
"version": "1.4",
|
||||
"tags": [
|
||||
"伊涅芙",
|
||||
"调味品"
|
||||
|
||||
Reference in New Issue
Block a user