mirror of
https://github.com/babalae/bettergi-scripts-list.git
synced 2026-03-21 04:19:51 +08:00
remove: 回退超时取消特性 移除卡时间功能
This commit is contained in:
@@ -1,7 +1,4 @@
|
||||
const DEFAULT_RUNS = 10;
|
||||
const DEFAULT_PERIOD = 25;
|
||||
const DEFAULT_BASE_RUNS = 50;
|
||||
const BENCHMARK_HOUR = "T04:00:00";
|
||||
const DEFAULT_OCR_TIMEOUT_SECONDS = 10;
|
||||
const DEFAULT_FIGHT_TIMEOUT_SECONDS = 120;
|
||||
|
||||
@@ -9,6 +6,46 @@ let detectedExpOrMora = true;
|
||||
let NoExpOrMoraCount = 0;
|
||||
let running = true;
|
||||
|
||||
const DEFAULT_OCR_KEYWORDS = ["突发", "任务", "打倒", "消灭", "敌人", "所有"];
|
||||
|
||||
const ENEMY_CONFIG = {
|
||||
"愚人众": {
|
||||
ocrKeywords: ["买卖", "不成", "正义存", "愚人众", "禁止", "危险", "运输", "打倒", "盗宝团", "丘丘人", "今晚", "伙食", "所有人"],
|
||||
targetCoords: { x: 4840.55, y: -3078.01 },
|
||||
triggerPoint: { x: 4783.79, y: -3065.62 },
|
||||
preparePath: "愚人众-准备",
|
||||
failReturnPath: "愚人众-准备",
|
||||
},
|
||||
"盗宝团": {
|
||||
ocrKeywords: ["岛上", "无贼", "消灭", "鬼鬼祟祟", "盗宝团"],
|
||||
targetCoords: { x: -2753.04, y: -3459.3025 },
|
||||
triggerPoint: { x: -2736.60, y: -3415.44 },
|
||||
},
|
||||
"鳄鱼": {
|
||||
ocrKeywords: ["张牙", "舞爪", "恶党", "鳄鱼", "打倒", "所有", "鳄鱼"],
|
||||
targetCoords: { x: 3578.08, y: -500.75 },
|
||||
triggerPoint: { x: 3614.63, y: -521.60 },
|
||||
preparePath: "鳄鱼-准备",
|
||||
failReturnPath: "鳄鱼-准备",
|
||||
failReturnSleepMs: 5000,
|
||||
initialDelayMs: 5000,
|
||||
postBattlePath: "鳄鱼-拾取",
|
||||
},
|
||||
"蕈兽": {
|
||||
ocrKeywords: ["实验家", "变成", "实验品", "击败", "所有", "魔物"],
|
||||
targetCoords: { x: 3794.55, y: -350.60 },
|
||||
triggerPoint: { x: 3749.38, y: -391.91 },
|
||||
preparePath: "蕈兽-准备",
|
||||
postBattlePath: "蕈兽-对话",
|
||||
},
|
||||
"雷萤术士": {
|
||||
ocrKeywords: ["雷萤", "术士", "圆滚滚", "不可食用", "威撼", "攀岩", "消灭", "准备", "打倒", "所有", "魔物", "盗宝团", "击败", "成员", "盗亦无道"],
|
||||
targetCoords: { x: 883.91, y: 656.63 },
|
||||
triggerPoint: { x: 881.92, y: 616.85 },
|
||||
preparePath: "雷萤术士-准备",
|
||||
},
|
||||
};
|
||||
|
||||
const expRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("assets/exp.png"), 74, 341, 207 - 74, 803 - 341);
|
||||
expRo.Threshold = 0.85;
|
||||
expRo.Use3Channels = true;
|
||||
@@ -36,27 +73,7 @@ moraRo.InitTemplate();
|
||||
log.info(`当前选择的敌人类型: ${enemyType}`);
|
||||
log.info(`${enemyType}好感开始...`);
|
||||
|
||||
// 清理丘丘人(仅盗宝团需要)
|
||||
if (settings.qiuQiuRen && enemyType === "盗宝团") {
|
||||
log.info(`清理原住民...`);
|
||||
await AutoPath('盗宝团-准备');
|
||||
}
|
||||
if (enemyType === "愚人众") {
|
||||
log.info(`导航到愚人众触发点...`);
|
||||
await AutoPath('愚人众-准备');
|
||||
}
|
||||
if (enemyType === "鳄鱼") {
|
||||
log.info(`导航到鳄鱼触发点...`);
|
||||
await AutoPath('鳄鱼-准备');
|
||||
}
|
||||
if (enemyType === "蕈兽") {
|
||||
log.info(`导航到蕈兽触发点...`);
|
||||
await AutoPath('蕈兽-准备');
|
||||
}
|
||||
if (enemyType === "雷萤术士") {
|
||||
log.info(`导航到雷萤术士触发点...`);
|
||||
await AutoPath('雷萤术士-准备');
|
||||
}
|
||||
await prepareForEnemy(enemyType);
|
||||
// 验证超时设置
|
||||
const ocrTimeout = validateTimeoutSetting(settings.ocrTimeout, DEFAULT_OCR_TIMEOUT_SECONDS, "OCR");
|
||||
const fightTimeout = validateTimeoutSetting(settings.fightTimeout, DEFAULT_FIGHT_TIMEOUT_SECONDS, "战斗");
|
||||
@@ -69,6 +86,41 @@ moraRo.InitTemplate();
|
||||
function convertToTrueIfNotBoolean(value) {
|
||||
return typeof value === 'boolean' ? value : true;
|
||||
}
|
||||
|
||||
function getEnemyConfig(enemyType) {
|
||||
return ENEMY_CONFIG[enemyType] || {};
|
||||
}
|
||||
|
||||
async function prepareForEnemy(enemyType) {
|
||||
// 清理丘丘人(仅盗宝团需要)
|
||||
if (settings.qiuQiuRen && enemyType === "盗宝团") {
|
||||
log.info("清理原住民...");
|
||||
await AutoPath("盗宝团-准备");
|
||||
}
|
||||
|
||||
const { preparePath } = getEnemyConfig(enemyType);
|
||||
if (preparePath) {
|
||||
log.info(`导航到${enemyType}触发点...`);
|
||||
await AutoPath(preparePath);
|
||||
}
|
||||
}
|
||||
|
||||
async function runPostBattle(enemyType) {
|
||||
const { postBattlePath } = getEnemyConfig(enemyType);
|
||||
if (postBattlePath) {
|
||||
await AutoPath(postBattlePath);
|
||||
}
|
||||
|
||||
if (enemyType === "蕈兽") {
|
||||
await sleep(50);
|
||||
keyPress("F");
|
||||
await sleep(50);
|
||||
keyPress("F");
|
||||
await sleep(500);
|
||||
await genshin.chooseTalkOption("下次");
|
||||
await sleep(500);
|
||||
}
|
||||
}
|
||||
// 执行 path 任务
|
||||
async function AutoPath(locationName) {
|
||||
try {
|
||||
@@ -248,8 +300,9 @@ async function executeBattleTasks(fightTimeout, enemyType, cts) {
|
||||
async function executeSingleFriendshipRound(roundIndex, ocrTimeout, fightTimeout, enemyType) {
|
||||
// 导航到触发点
|
||||
await navigateToTriggerPoint(enemyType);
|
||||
if (roundIndex === 0 && enemyType === "鳄鱼") {
|
||||
await sleep(5000);
|
||||
const { initialDelayMs } = getEnemyConfig(enemyType);
|
||||
if (roundIndex === 0 && initialDelayMs) {
|
||||
await sleep(initialDelayMs);
|
||||
}
|
||||
let initialDetected = false;
|
||||
if (roundIndex === 0) {
|
||||
@@ -288,20 +341,7 @@ async function executeSingleFriendshipRound(roundIndex, ocrTimeout, fightTimeout
|
||||
await executeBattleTasks(fightTimeout, enemyType, cts);
|
||||
await pathTask;
|
||||
|
||||
// 特殊处理:鳄鱼战斗后需要拾取
|
||||
if (enemyType === "鳄鱼") {
|
||||
await AutoPath('鳄鱼-拾取');
|
||||
}
|
||||
if (enemyType === "蕈兽") {
|
||||
await AutoPath('蕈兽-对话');
|
||||
await sleep(50);
|
||||
keyPress("F");
|
||||
await sleep(50);
|
||||
keyPress("F");
|
||||
await sleep(500);
|
||||
await genshin.chooseTalkOption("下次");
|
||||
await sleep(500);
|
||||
}
|
||||
await runPostBattle(enemyType);
|
||||
|
||||
// 返回 true 表示成功完成这一轮
|
||||
return true;
|
||||
@@ -333,11 +373,9 @@ async function AutoFriendshipDev(times, ocrTimeout, fightTimeout, enemyType = "
|
||||
} catch (error) {
|
||||
log.error(`第 ${i + 1} 轮好感任务失败: ${error.message}`);
|
||||
// 如果是战斗超时错误,直接终止整个任务
|
||||
/*
|
||||
if (error.message && error.message.includes("战斗超时")) {
|
||||
throw error;
|
||||
}
|
||||
*/
|
||||
} // 战斗超时就是需要取消任务
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -345,7 +383,7 @@ async function AutoFriendshipDev(times, ocrTimeout, fightTimeout, enemyType = "
|
||||
if (settings.loopTillNoExpOrMora) {
|
||||
await detectExpOrMoraTask;
|
||||
}
|
||||
log.info(`${enemyType}好感已完成`);
|
||||
log.info(`${enemyType} 好感已完成`);
|
||||
}
|
||||
|
||||
async function detectExpOrMora() {
|
||||
@@ -384,43 +422,13 @@ async function calulateRunTimes() {
|
||||
log.info(`'请确保队伍满员,并为队伍配置相应的战斗策略'`);
|
||||
// 计算运行次数
|
||||
let runTimes = Number(settings.runTimes);
|
||||
if (!isPositiveInteger(runTimes) && !settings.waitTimeMode) {
|
||||
if (!isPositiveInteger(runTimes)) {
|
||||
log.warn("请输入正确的次数,必须是正整数!");
|
||||
log.warn(`运行次数重置为 ${DEFAULT_RUNS} 次!`);
|
||||
runTimes = DEFAULT_RUNS;
|
||||
}
|
||||
|
||||
if (settings.waitTimeMode) {
|
||||
if (!isPositiveInteger(runTimes)) {
|
||||
log.warn("运行次数必须是正整数,使用默认基准次数");
|
||||
log.warn(`运行次数重置为 ${DEFAULT_BASE_RUNS} 次!`);
|
||||
runTimes = DEFAULT_BASE_RUNS;
|
||||
}
|
||||
|
||||
// 验证日期格式
|
||||
const waitTimeModeDay = settings.waitTimeModeDay;
|
||||
if (!isValidDateFormat(waitTimeModeDay)) {
|
||||
log.error("基准日期格式错误,请检查后重试!");
|
||||
log.error("参考格式:2025-01-01");
|
||||
log.error(`错误输入:${waitTimeModeDay}`);
|
||||
await sleep(5000);
|
||||
return;
|
||||
}
|
||||
|
||||
let period = Number(settings.waitTimeModePeriod);
|
||||
if (!isPositiveInteger(period) || period > runTimes) {
|
||||
period = DEFAULT_PERIOD < runTimes ? DEFAULT_PERIOD : runTimes;
|
||||
log.warn(`卡时间模式周期必须是 1-${runTimes} 之间的正整数!使用 ${period} 作为周期`);
|
||||
}
|
||||
runTimes = calculateWaitModeRuns(runTimes, waitTimeModeDay, period);
|
||||
|
||||
// 添加日志输出,提醒用户当前使用的基准日期和周期
|
||||
log.info(`当前使用的基准日期: ${waitTimeModeDay}`);
|
||||
log.info(`当前使用的周期: ${period} 天`);
|
||||
log.info(`根据基准日期和周期计算,今日运行次数: ${runTimes}`);
|
||||
} else {
|
||||
log.info(`当前设置的运行次数: ${runTimes}`);
|
||||
}
|
||||
log.info(`当前设置的运行次数: ${runTimes}`);
|
||||
return runTimes;
|
||||
}
|
||||
|
||||
@@ -431,83 +439,22 @@ function isPositiveInteger(value) {
|
||||
|
||||
// 根据敌人类型获取OCR关键词
|
||||
function getOcrKeywords(enemyType) {
|
||||
if (enemyType === "愚人众") {
|
||||
return ["买卖", "不成", "正义存", "愚人众", "禁止", "危险", "运输", "打倒", "盗宝团", "丘丘人", "今晚", "伙食", "所有人"];
|
||||
}
|
||||
else if (enemyType === "盗宝团") {
|
||||
return ["岛上", "无贼", "消灭", "鬼鬼祟祟", "盗宝团"];
|
||||
}
|
||||
else if (enemyType === "鳄鱼") {
|
||||
return ["张牙", "舞爪", "恶党", "鳄鱼", "打倒", "所有", "鳄鱼"];
|
||||
}
|
||||
else if (enemyType === "蕈兽") {
|
||||
return ["实验家", "变成", "实验品", "击败", "所有", "魔物"];
|
||||
}
|
||||
else if (enemyType === "雷萤术士") {
|
||||
return ["雷萤", "术士", "圆滚滚", "不可食用", "威撼", "攀岩", "消灭", "准备", "打倒", "所有", "魔物", "盗宝团", "击败", "成员", "盗亦无道"];
|
||||
}
|
||||
else {
|
||||
return ["突发", "任务", "打倒", "消灭", "敌人", "所有"]; // 兜底关键词
|
||||
}
|
||||
const { ocrKeywords } = getEnemyConfig(enemyType);
|
||||
return ocrKeywords || DEFAULT_OCR_KEYWORDS;
|
||||
}
|
||||
|
||||
// 根据敌人类型获取目标战斗点坐标
|
||||
function getTargetCoordinates(enemyType) {
|
||||
if (enemyType === "愚人众") {
|
||||
return { x: 4840.55, y: -3078.01 };
|
||||
} else if (enemyType === "盗宝团") {
|
||||
// 盗宝团战斗点坐标
|
||||
return { x: -2753.04, y: -3459.3025 };
|
||||
} else if (enemyType === "鳄鱼") {
|
||||
// 鳄鱼战斗点坐标
|
||||
return { x: 3578.08, y: -500.75 };
|
||||
} else if (enemyType === "蕈兽") {
|
||||
return { x: 3794.55, y: -350.60 };
|
||||
} else if (enemyType === "雷萤术士") {
|
||||
return { x: 883.91, y: 656.63 };
|
||||
}
|
||||
const { targetCoords } = getEnemyConfig(enemyType);
|
||||
return targetCoords;
|
||||
}
|
||||
|
||||
function getTriggerPoint(enemyType) {
|
||||
if (enemyType === "愚人众") {
|
||||
return { x: 4783.79, y: -3065.62 }; // 愚人众触发点坐标
|
||||
}
|
||||
else if (enemyType === "盗宝团") {
|
||||
return { x: -2736.60, y: -3415.44 }; // 盗宝团触发点坐标
|
||||
}
|
||||
else if (enemyType === "鳄鱼") {
|
||||
return { x: 3614.63, y: -521.60 }; // 鳄鱼触发点坐标
|
||||
} else if (enemyType === "蕈兽") {
|
||||
return { x: 3749.38, y: -391.91 }; // 蕈兽触发点坐标
|
||||
} else if (enemyType === "雷萤术士") {
|
||||
return { x: 881.92, y: 616.85 }; // 雷萤术士触发点坐标
|
||||
}
|
||||
const { triggerPoint } = getEnemyConfig(enemyType);
|
||||
return triggerPoint;
|
||||
}
|
||||
|
||||
// 验证日期格式
|
||||
function isValidDateFormat(dateStr) {
|
||||
if (!dateStr) return false;
|
||||
|
||||
// 检查格式是否为 YYYY-MM-DD
|
||||
const regex = /^\d{4}-\d{2}-\d{2}$/;
|
||||
if (!regex.test(dateStr)) return false;
|
||||
|
||||
// 检查是否为有效日期
|
||||
const date = new Date(dateStr);
|
||||
return !isNaN(date.getTime());
|
||||
}
|
||||
|
||||
function calculateWaitModeRuns(baseRuns, waitTimeModeDay, period) {
|
||||
const now = new Date();
|
||||
const benchmark = new Date(waitTimeModeDay + BENCHMARK_HOUR);
|
||||
const timeDiff = now.getTime() - benchmark.getTime();
|
||||
const daysDiff = Math.floor(timeDiff / (1000 * 60 * 60 * 24));
|
||||
const daysNormalized = daysDiff >= 0 ? daysDiff : period - (Math.abs(daysDiff) % period);
|
||||
const dayInCycle = (daysNormalized % period) + 1;
|
||||
const baseRunsPerDay = Math.ceil(baseRuns / period);
|
||||
return baseRunsPerDay * dayInCycle;
|
||||
}
|
||||
|
||||
async function switchPartyIfNeeded(partyName) {
|
||||
if (!partyName) {
|
||||
await genshin.returnMainUi();
|
||||
@@ -543,6 +490,12 @@ async function waitForBattleResult(timeout = 2 * 60 * 1000, enemyType = "盗宝
|
||||
let text = result.text;
|
||||
let text2 = result2.text;
|
||||
capture.dispose();
|
||||
if (enemyType === "蕈兽" && text2.includes("维沙瓦")) {
|
||||
log.info("战斗结果:成功");
|
||||
cts.cancel();
|
||||
return true;
|
||||
}
|
||||
|
||||
// 检查成功关键词
|
||||
for (let keyword of successKeywords) {
|
||||
if (text.includes(keyword)) {
|
||||
@@ -551,11 +504,6 @@ async function waitForBattleResult(timeout = 2 * 60 * 1000, enemyType = "盗宝
|
||||
cts.cancel(); // 取消任务
|
||||
return true;
|
||||
}
|
||||
if (enemyType == "蕈兽" && text2.includes("维沙瓦")) {
|
||||
log.info("战斗结果:成功");
|
||||
cts.cancel();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// 检查失败关键词
|
||||
@@ -565,8 +513,9 @@ async function waitForBattleResult(timeout = 2 * 60 * 1000, enemyType = "盗宝
|
||||
log.warn("战斗结果:失败,回到七天神像重试");
|
||||
cts.cancel(); // 取消任务
|
||||
await genshin.tpToStatueOfTheSeven();
|
||||
if (enemyType === "愚人众") {
|
||||
await AutoPath('愚人众-准备');
|
||||
const { failReturnPath } = getEnemyConfig(enemyType);
|
||||
if (failReturnPath) {
|
||||
await AutoPath(failReturnPath);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -590,14 +539,13 @@ async function waitForBattleResult(timeout = 2 * 60 * 1000, enemyType = "盗宝
|
||||
if (notFind > 10) {
|
||||
log.warn("不在任务触发区域,战斗失败");
|
||||
cts.cancel(); // 取消任务
|
||||
if (enemyType === "愚人众") {
|
||||
log.warn("回到愚人众准备点");
|
||||
await AutoPath('愚人众-准备');
|
||||
const { failReturnPath, failReturnSleepMs } = getEnemyConfig(enemyType);
|
||||
if (failReturnPath) {
|
||||
log.warn(`回到${enemyType}准备点`);
|
||||
await AutoPath(failReturnPath);
|
||||
}
|
||||
if (enemyType === "鳄鱼") {
|
||||
log.warn("回到鳄鱼准备点");
|
||||
await AutoPath('鳄鱼-准备');
|
||||
await sleep(5000);
|
||||
if (failReturnSleepMs) {
|
||||
await sleep(failReturnSleepMs);
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -631,7 +579,7 @@ function validateTimeoutSetting(value, defaultValue, timeoutType) {
|
||||
|
||||
// 检查是否为有效数字且大于0
|
||||
if (!isFinite(timeout) || timeout <= 0) {
|
||||
log.warn(`${timeoutType}超时设置无效,必须是大于0的数字,将使用默认值 ${defaultValue} 秒`);
|
||||
log.warn(`${timeoutType} 超时设置无效,必须是大于0的数字,将使用默认值 ${defaultValue} 秒`);
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
|
||||
@@ -43,21 +43,6 @@
|
||||
"type": "input-text",
|
||||
"label": "(选填)运行次数\n【默认10次,卡时间模式默认50次】"
|
||||
},
|
||||
{
|
||||
"name": "waitTimeMode",
|
||||
"type": "checkbox",
|
||||
"label": "卡时间模式\n【基于运行次数、基准日期、周期确定需要运行次数】"
|
||||
},
|
||||
{
|
||||
"name": "waitTimeModeDay",
|
||||
"type": "input-text",
|
||||
"label": "卡时间模式基准日期\n【格式参考:2025-01-01】"
|
||||
},
|
||||
{
|
||||
"name": "waitTimeModePeriod",
|
||||
"type": "input-text",
|
||||
"label": "(选填)卡时间模式周期\n【默认:25天】"
|
||||
},
|
||||
{
|
||||
"name": "ocrTimeout",
|
||||
"type": "input-text",
|
||||
|
||||
Reference in New Issue
Block a user