mirror of
https://github.com/babalae/bettergi-scripts-list.git
synced 2026-03-19 03:59:51 +08:00
JS脚本购买狗粮更新 (#2084)
* Update settings.json * Update manifest.json * Update main.js * Update 挪德卡莱购买狗粮.json * Update 璃月购买狗粮1.json * Update 璃月购买狗粮2.json * Add files via upload
This commit is contained in:
8
repo/js/PurchaseArtifacts/README.md
Normal file
8
repo/js/PurchaseArtifacts/README.md
Normal file
@@ -0,0 +1,8 @@
|
||||
商店狗粮周四凌晨4点刷新,可以自行选择想买的商人(默认全选)
|
||||
|
||||
根据体力代换计算,买完8个商人相当于用价值26体力的摩拉换取了43体力的狗粮,
|
||||
|
||||
所以真的不建议将狗粮分解成摩拉,如果你真的很缺。
|
||||
|
||||
此外脚本完整运行后会记录本次的时间,没有刷新时运行脚本会自动跳过。
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
"x": 9367.1484375,
|
||||
"y": 1435.6484375,
|
||||
"type": "teleport",
|
||||
"move_mode": "run",
|
||||
"move_mode": "dash",
|
||||
"action": ""
|
||||
},
|
||||
{
|
||||
@@ -21,7 +21,7 @@
|
||||
"x": 9396.775390625,
|
||||
"y": 1486.4755859375,
|
||||
"type": "path",
|
||||
"move_mode": "run",
|
||||
"move_mode": "dash",
|
||||
"action": ""
|
||||
},
|
||||
{
|
||||
@@ -29,7 +29,7 @@
|
||||
"x": 9381.6875,
|
||||
"y": 1561.802734375,
|
||||
"type": "path",
|
||||
"move_mode": "run",
|
||||
"move_mode": "dash",
|
||||
"action": ""
|
||||
},
|
||||
{
|
||||
@@ -37,8 +37,8 @@
|
||||
"x": 9389.0546,
|
||||
"y": 1566.3916,
|
||||
"type": "target",
|
||||
"move_mode": "walk",
|
||||
"move_mode": "dash",
|
||||
"action": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,16 +18,7 @@
|
||||
"action_params": ""
|
||||
},
|
||||
{
|
||||
"action": "set_time",
|
||||
"action_params": "19:00",
|
||||
"id": 2,
|
||||
"move_mode": "walk",
|
||||
"type": "path",
|
||||
"x": 366.74609375,
|
||||
"y": -502.52587890625
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"x": 360.026171875,
|
||||
"y": -491.16474609375,
|
||||
"type": "path",
|
||||
@@ -36,7 +27,7 @@
|
||||
"action_params": ""
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"id": 3,
|
||||
"x": 340.1712890625,
|
||||
"y": -471.7400390625,
|
||||
"type": "target",
|
||||
@@ -45,4 +36,4 @@
|
||||
"action_params": ""
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,24 +19,33 @@
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"x": 378.5673828125,
|
||||
"y": -532.35009765625,
|
||||
"type": "path",
|
||||
"action": "set_time",
|
||||
"action_params": "19:00",
|
||||
"move_mode": "walk",
|
||||
"action": "",
|
||||
"action_params": ""
|
||||
"type": "path",
|
||||
"x": 366.748046875,
|
||||
"y": -502.51904296875,
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"x": 330.466796875,
|
||||
"y": -585.69921875,
|
||||
"x": 378.5673828125,
|
||||
"y": -532.35009765625,
|
||||
"type": "path",
|
||||
"move_mode": "run",
|
||||
"move_mode": "dash",
|
||||
"action": "",
|
||||
"action_params": ""
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"x": 330.466796875,
|
||||
"y": -585.69921875,
|
||||
"type": "path",
|
||||
"move_mode": "dash",
|
||||
"action": "",
|
||||
"action_params": ""
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"x": 340.091796875,
|
||||
"y": -593.6611328125,
|
||||
"type": "path",
|
||||
@@ -45,4 +54,4 @@
|
||||
"action_params": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,221 @@
|
||||
await pathingScript.runFile(filePath);
|
||||
}
|
||||
|
||||
//读取配置
|
||||
let holdingState = settings.holdingState ?? 0;
|
||||
/**
|
||||
* 在指定区域内查找并点击指定文字
|
||||
* @param {string} targetText - 要点击的目标文字
|
||||
* @param {number} x - 识别区域的左上角X坐标
|
||||
* @param {number} y - 识别区域的左上角Y坐标
|
||||
* @param {number} width - 识别区域的宽度
|
||||
* @param {number} height - 识别区域的高度
|
||||
* @param {object} options - 可选参数
|
||||
* @param {boolean} options.trimText - 是否对OCR结果进行trim处理,默认true
|
||||
* @param {boolean} options.clickCenter - 是否点击文字区域中心,默认true
|
||||
* @param {number} options.retryCount - 重试次数,默认1(不重试)
|
||||
* @param {number} options.retryInterval - 重试间隔(毫秒),默认500
|
||||
* @returns {Promise<boolean>} 是否找到并点击了文字
|
||||
*/
|
||||
async function clickTextInRegion(targetText, x, y, width, height, options = {}) {
|
||||
const {
|
||||
trimText = true,
|
||||
clickCenter = true,
|
||||
retryCount = 1,
|
||||
retryInterval = 500
|
||||
} = options;
|
||||
|
||||
for (let attempt = 0; attempt <= retryCount; attempt++) {
|
||||
try {
|
||||
// 获取游戏区域截图
|
||||
const captureRegion = captureGameRegion();
|
||||
|
||||
// 创建OCR识别对象,限定识别区域
|
||||
const ocrRo = RecognitionObject.ocr(x, y, width, height);
|
||||
|
||||
// 在限定区域内进行OCR识别
|
||||
const results = captureRegion.findMulti(ocrRo);
|
||||
|
||||
// 遍历OCR结果
|
||||
for (let i = 0; i < results.count; i++) {
|
||||
const res = results[i];
|
||||
let detectedText = res.text;
|
||||
|
||||
// 可选:去除前后空白字符
|
||||
if (trimText) {
|
||||
detectedText = detectedText.trim();
|
||||
}
|
||||
|
||||
// 检查是否匹配目标文字
|
||||
if (detectedText === targetText) {
|
||||
log.info(`找到目标文字: "${targetText}",位置: (${res.x}, ${res.y}, ${res.width}, ${res.height})`);
|
||||
|
||||
if (clickCenter) {
|
||||
// 点击文字区域中心
|
||||
await sleep(200);
|
||||
keyDown("VK_LMENU");
|
||||
await sleep(500);
|
||||
res.click();
|
||||
await sleep(100);
|
||||
keyUp("VK_LMENU");
|
||||
log.info(`已点击文字中心: "${targetText}"`);
|
||||
|
||||
} else {
|
||||
// 点击文字区域的左上角
|
||||
res.clickTo(0, 0);
|
||||
log.info(`已点击文字偏移位置: "${targetText}"`);
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果当前尝试未找到,且还有重试机会,则等待后重试
|
||||
if (attempt < retryCount) {
|
||||
log.info(`第${attempt + 1}次尝试未找到文字"${targetText}",${retryInterval}ms后重试...`);
|
||||
await sleep(retryInterval);
|
||||
}
|
||||
} catch (error) {
|
||||
log.error(`点击文字"${targetText}"时发生错误: ${error.message}`);
|
||||
if (attempt < retryCount) {
|
||||
await sleep(retryInterval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log.info(`未找到文字: "${targetText}",已尝试${retryCount + 1}次`);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 判断任务是否已刷新
|
||||
* @param {string} filePath - 存储最后完成时间的文件路径
|
||||
* @param {object} options - 配置选项
|
||||
* @param {string} [options.refreshType] - 刷新类型: 'hourly'|'daily'|'weekly'|'monthly'|'custom'
|
||||
* @param {number} [options.customHours] - 自定义小时数(用于'custom'类型)
|
||||
* @param {number} [options.dailyHour=4] - 每日刷新的小时(0-23)
|
||||
* @param {number} [options.weeklyDay=1] - 每周刷新的星期(0-6, 0是周日)
|
||||
* @param {number} [options.weeklyHour=4] - 每周刷新的小时(0-23)
|
||||
* @param {number} [options.monthlyDay=1] - 每月刷新的日期(1-31)
|
||||
* @param {number} [options.monthlyHour=4] - 每月刷新的小时(0-23)
|
||||
* @returns {Promise<boolean>} - 是否已刷新
|
||||
*/
|
||||
async function isTaskRefreshed(filePath, options = {}) {
|
||||
const {
|
||||
refreshType = 'hourly', // 默认每小时刷新
|
||||
customHours = 24, // 自定义刷新小时数默认24
|
||||
dailyHour = 4, // 每日刷新默认凌晨4点
|
||||
weeklyDay = 1, // 每周刷新默认周一(0是周日)
|
||||
weeklyHour = 4, // 每周刷新默认凌晨4点
|
||||
monthlyDay = 1, // 每月刷新默认第1天
|
||||
monthlyHour = 4 // 每月刷新默认凌晨4点
|
||||
} = options;
|
||||
|
||||
try {
|
||||
// 读取文件内容
|
||||
let content = await file.readText(filePath);
|
||||
const lastTime = new Date(content);
|
||||
const nowTime = new Date();
|
||||
|
||||
|
||||
let shouldRefresh = false;
|
||||
|
||||
|
||||
switch (refreshType) {
|
||||
case 'hourly': // 每小时刷新
|
||||
shouldRefresh = (nowTime - lastTime) >= 3600 * 1000;
|
||||
break;
|
||||
|
||||
case 'daily': // 每天固定时间刷新
|
||||
// 检查是否已经过了当天的刷新时间
|
||||
const todayRefresh = new Date(nowTime);
|
||||
todayRefresh.setHours(dailyHour, 0, 0, 0);
|
||||
|
||||
// 如果当前时间已经过了今天的刷新时间,检查上次完成时间是否在今天刷新之前
|
||||
if (nowTime >= todayRefresh) {
|
||||
shouldRefresh = lastTime < todayRefresh;
|
||||
} else {
|
||||
// 否则检查上次完成时间是否在昨天刷新之前
|
||||
const yesterdayRefresh = new Date(todayRefresh);
|
||||
yesterdayRefresh.setDate(yesterdayRefresh.getDate() - 1);
|
||||
shouldRefresh = lastTime < yesterdayRefresh;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'weekly': // 每周固定时间刷新
|
||||
// 获取本周的刷新时间
|
||||
const thisWeekRefresh = new Date(nowTime);
|
||||
// 计算与本周指定星期几的差值
|
||||
const dayDiff = (thisWeekRefresh.getDay() - weeklyDay + 7) % 7;
|
||||
thisWeekRefresh.setDate(thisWeekRefresh.getDate() - dayDiff);
|
||||
thisWeekRefresh.setHours(weeklyHour, 0, 0, 0);
|
||||
|
||||
// 如果当前时间已经过了本周的刷新时间
|
||||
if (nowTime >= thisWeekRefresh) {
|
||||
shouldRefresh = lastTime < thisWeekRefresh;
|
||||
} else {
|
||||
// 否则检查上次完成时间是否在上周刷新之前
|
||||
const lastWeekRefresh = new Date(thisWeekRefresh);
|
||||
lastWeekRefresh.setDate(lastWeekRefresh.getDate() - 7);
|
||||
shouldRefresh = lastTime < lastWeekRefresh;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'monthly': // 每月固定时间刷新
|
||||
// 获取本月的刷新时间
|
||||
const thisMonthRefresh = new Date(nowTime);
|
||||
// 设置为本月指定日期的凌晨
|
||||
thisMonthRefresh.setDate(monthlyDay);
|
||||
thisMonthRefresh.setHours(monthlyHour, 0, 0, 0);
|
||||
|
||||
// 如果当前时间已经过了本月的刷新时间
|
||||
if (nowTime >= thisMonthRefresh) {
|
||||
shouldRefresh = lastTime < thisMonthRefresh;
|
||||
} else {
|
||||
// 否则检查上次完成时间是否在上月刷新之前
|
||||
const lastMonthRefresh = new Date(thisMonthRefresh);
|
||||
lastMonthRefresh.setMonth(lastMonthRefresh.getMonth() - 1);
|
||||
shouldRefresh = lastTime < lastMonthRefresh;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'custom': // 自定义小时数刷新
|
||||
shouldRefresh = (nowTime - lastTime) >= customHours * 3600 * 1000;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error(`未知的刷新类型: ${refreshType}`);
|
||||
}
|
||||
|
||||
// 如果文件内容无效或不存在,视为需要刷新
|
||||
if (!content || isNaN(lastTime.getTime())) {
|
||||
await file.writeText(filePath, '');
|
||||
shouldRefresh = true;
|
||||
}
|
||||
|
||||
if (shouldRefresh) {
|
||||
notification.send(`购买狗粮已经刷新,执行脚本`);
|
||||
|
||||
|
||||
return true;
|
||||
} else {
|
||||
log.info(`购买狗粮未刷新`);
|
||||
return false;
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
// 如果文件不存在,创建新文件并返回true(视为需要刷新)
|
||||
const createResult = await file.writeText(filePath, '');
|
||||
if (createResult) {
|
||||
log.info("创建新时间记录文件成功,执行脚本");
|
||||
return true;
|
||||
}
|
||||
else throw new Error(`创建新文件失败`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//基本购买流程
|
||||
async function Shopping() {
|
||||
@@ -22,12 +235,18 @@ let holdingState = settings.holdingState ?? 0;
|
||||
keyPress("ESCAPE"); await sleep(2000);
|
||||
}
|
||||
|
||||
async function main() {
|
||||
if(settings.select1){
|
||||
await Purchase('蒙德购买狗粮');
|
||||
await Shopping();
|
||||
}
|
||||
|
||||
if(settings.select2){
|
||||
await Purchase('璃月购买狗粮1');
|
||||
await Shopping();
|
||||
}
|
||||
|
||||
if(settings.select3){
|
||||
await Purchase('璃月购买狗粮2');
|
||||
await sleep(1000);
|
||||
keyDown("w");
|
||||
@@ -36,7 +255,7 @@ let holdingState = settings.holdingState ?? 0;
|
||||
await sleep(1000);
|
||||
keyPress("F"); await sleep(1200);
|
||||
keyPress("F"); await sleep(1800);
|
||||
if (holdingState) keyPress("s");
|
||||
await clickTextInRegion("我想买些古董。", 1264, 532, 370, 160);
|
||||
await sleep(500);
|
||||
keyPress("F"); await sleep(1200);
|
||||
keyPress("F"); await sleep(1800);
|
||||
@@ -46,7 +265,9 @@ let holdingState = settings.holdingState ?? 0;
|
||||
click(1690, 1020); await sleep(200); // 点击空白处
|
||||
}
|
||||
keyPress("ESCAPE"); await sleep(2000);
|
||||
}
|
||||
|
||||
if(settings.select4){
|
||||
await Purchase('稻妻购买狗粮');
|
||||
await sleep(1500);
|
||||
for (let j = 0; j < 5; j++) {
|
||||
@@ -59,20 +280,41 @@ let holdingState = settings.holdingState ?? 0;
|
||||
click(1690, 1020); await sleep(200); // 点击空白处
|
||||
}
|
||||
keyPress("ESCAPE"); await sleep(2000);
|
||||
|
||||
}
|
||||
if(settings.select5){
|
||||
await Purchase('须弥购买狗粮');
|
||||
await Shopping();
|
||||
}
|
||||
|
||||
if(settings.select6){
|
||||
await Purchase('枫丹购买狗粮');
|
||||
await Shopping();
|
||||
}
|
||||
|
||||
if(settings.select7){
|
||||
await Purchase('纳塔购买狗粮');
|
||||
await sleep(1000);
|
||||
keyDown("a");
|
||||
await sleep(500);
|
||||
keyUp("a");
|
||||
await Shopping();
|
||||
}
|
||||
|
||||
if(settings.select8){
|
||||
await Purchase('挪德卡莱购买狗粮');
|
||||
await Shopping();
|
||||
}
|
||||
|
||||
await file.writeText("assets/weekly.txt", new Date().toISOString());
|
||||
}
|
||||
|
||||
//每周四4点刷新
|
||||
if( await isTaskRefreshed("assets/weekly.txt", {
|
||||
refreshType: 'weekly',
|
||||
weeklyDay: 4, // 周一
|
||||
weeklyHour: 4 // 凌晨4点
|
||||
})){
|
||||
await main();
|
||||
}
|
||||
|
||||
})();
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"manifest_version": 1,
|
||||
"name": "自动购买狗粮(8点位)",
|
||||
"version": "1.1.3",
|
||||
"version": "2.0",
|
||||
"bgi_version": "0.50",
|
||||
"description": "狗粮周3刷新,价值23体力的摩拉换38体力的狗粮,血赚。龙骨花凝珠没出售,需额外设置。强烈建议使用固定队伍(双风成女行走)",
|
||||
"description": "自动购买狗粮",
|
||||
"authors": [
|
||||
{
|
||||
"name": "柒叶子",
|
||||
@@ -16,4 +16,4 @@
|
||||
],
|
||||
"settings_ui": "settings.json",
|
||||
"main": "main.js"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,51 @@
|
||||
[
|
||||
{
|
||||
"name": "holdingState",
|
||||
"type": "select",
|
||||
"label": "(有无龙骨花凝珠?默认NO)",
|
||||
"options": [
|
||||
"YES",
|
||||
"NO"
|
||||
]
|
||||
}
|
||||
]
|
||||
"name": "select1",
|
||||
"type": "checkbox",
|
||||
"label": "蒙德商人",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"name": "select2",
|
||||
"type": "checkbox",
|
||||
"label": "璃月商人1",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"name": "select3",
|
||||
"type": "checkbox",
|
||||
"label": "璃月商人2",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"name": "select4",
|
||||
"type": "checkbox",
|
||||
"label": "稻妻商人",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"name": "select5",
|
||||
"type": "checkbox",
|
||||
"label": "须弥商人",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"name": "select6",
|
||||
"type": "checkbox",
|
||||
"label": "枫丹商人",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"name": "select7",
|
||||
"type": "checkbox",
|
||||
"label": "纳塔商人",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"name": "select8",
|
||||
"type": "checkbox",
|
||||
"label": "挪德卡莱商人",
|
||||
"default": true
|
||||
},
|
||||
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user