铁匠铺2.00523 (#908)
* Update and rename readme(25.05.22).md to readme(25.05.23).md * 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:
@@ -1,62 +1,64 @@
|
|||||||
//锻造按钮模板
|
/*********************** 配置与常量 ***********************/
|
||||||
const ConfirmDeployButtonRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("Assets/RecognitionObject/Confirm Deploy Button.png"), 0, 870, 1920, 210);
|
|
||||||
const ForgingInterfaceRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("Assets/RecognitionObject/ForgingInterface.png"), 0, 0, 140, 100);
|
|
||||||
const ForgeRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("Assets/RecognitionObject/Forge.png"), 1260, 300, 600, 600);
|
|
||||||
|
|
||||||
|
// 用户配置
|
||||||
|
let smithyName = settings.smithyName || "枫丹铁匠铺"; // 铁匠铺地区
|
||||||
|
let primaryOre = settings.ore || "水晶块"; // 主选矿石
|
||||||
|
let secondaryOre = settings.secondaryOre || "萃凝晶"; // 备选矿石1
|
||||||
|
let tertiaryOre = settings.tertiaryOre || "紫晶块"; // 备选矿石2
|
||||||
|
let notice = settings.notice ?? false; // 通知状态
|
||||||
|
let forgedOrNot = (settings.forgedOrNot && settings.forgedOrNot.trim() !== "") ? settings.forgedOrNot : "是"; // 是否锻造
|
||||||
|
|
||||||
|
// 矿石图像与中文名称映射
|
||||||
(async function () {
|
const ingredientImageMap = {
|
||||||
// 设置通知状态
|
|
||||||
let notice = settings.notice ?? false;
|
|
||||||
|
|
||||||
// 设置游戏基础参数/初始化
|
|
||||||
setGameMetrics(1920, 1080, 1.25);
|
|
||||||
await genshin.returnMainUi();
|
|
||||||
if (notice) {
|
|
||||||
notification.send("自动锻造矿石脚本开始");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 读取用户配置
|
|
||||||
let smithyName = settings.smithyName || "枫丹铁匠铺";
|
|
||||||
let primaryOre = settings.ore || "水晶块";
|
|
||||||
let secondaryOre = settings.secondaryOre || "萃凝晶";
|
|
||||||
let tertiaryOre = settings.tertiaryOre || "紫晶块";
|
|
||||||
|
|
||||||
// 定义矿物名称和图片文件名的映射表
|
|
||||||
const ingredientImageMap = {
|
|
||||||
萃凝晶: "assets/Picture/CondessenceCrystal.png",
|
萃凝晶: "assets/Picture/CondessenceCrystal.png",
|
||||||
紫晶块: "assets/Picture/AmethystLump.png",
|
紫晶块: "assets/Picture/AmethystLump.png",
|
||||||
水晶块: "assets/Picture/CrystalChunk.png",
|
水晶块: "assets/Picture/CrystalChunk.png",
|
||||||
星银矿石: "assets/Picture/Starsilver.png",
|
星银矿石: "assets/Picture/Starsilver.png",
|
||||||
白铁块: "assets/Picture/WhiteIronChunk.png",
|
白铁块: "assets/Picture/WhiteIronChunk.png",
|
||||||
铁块: "assets/Picture/IronChunk.png",
|
铁块: "assets/Picture/IronChunk.png",
|
||||||
};
|
};
|
||||||
|
|
||||||
// Ore 映射为中文
|
const OreChineseMap = {
|
||||||
const OreChineseMap = {
|
|
||||||
萃凝晶: "萃凝晶",
|
萃凝晶: "萃凝晶",
|
||||||
紫晶块: "紫晶块",
|
紫晶块: "紫晶块",
|
||||||
水晶块: "水晶块",
|
水晶块: "水晶块",
|
||||||
星银矿石: "星银矿石",
|
星银矿石: "星银矿石",
|
||||||
白铁块: "白铁块",
|
白铁块: "白铁块",
|
||||||
铁块: "铁块",
|
铁块: "铁块",
|
||||||
};
|
};
|
||||||
|
|
||||||
// 行列数的排列组合
|
// 模板识别对象
|
||||||
const rows = [1, 2, 3]; // 行数
|
const ConfirmDeployButtonRo = RecognitionObject.TemplateMatch(
|
||||||
const cols = [1, 2, 3, 4, 5]; // 列数
|
file.ReadImageMatSync("Assets/RecognitionObject/Confirm Deploy Button.png"),
|
||||||
const gridCoordinates = [];
|
0, 870, 1920, 210
|
||||||
|
); // 确定按钮
|
||||||
|
|
||||||
for (const row of rows) {
|
const ForgingInterfaceRo = RecognitionObject.TemplateMatch(
|
||||||
|
file.ReadImageMatSync("Assets/RecognitionObject/ForgingInterface.png"),
|
||||||
|
0, 0, 140, 100
|
||||||
|
); // 锻造界面图标
|
||||||
|
|
||||||
|
const ForgeRo = RecognitionObject.TemplateMatch(
|
||||||
|
file.ReadImageMatSync("Assets/RecognitionObject/Forge.png"),
|
||||||
|
1260, 300, 600, 600
|
||||||
|
); // 对话框中的锻造图标
|
||||||
|
|
||||||
|
// 计算矿物图标的坐标(行列排列)
|
||||||
|
const rows = [1, 2, 3];
|
||||||
|
const cols = [1, 2, 3, 4, 5];
|
||||||
|
const gridCoordinates = [];
|
||||||
|
for (const row of rows) {
|
||||||
for (const col of cols) {
|
for (const col of cols) {
|
||||||
const ProcessingX = Math.round(150 + (col - 1) * 145);
|
const ProcessingX = Math.round(150 + (col - 1) * 145);
|
||||||
const ProcessingY = Math.round(230 + (row - 1) * 170);
|
const ProcessingY = Math.round(230 + (row - 1) * 170);
|
||||||
gridCoordinates.push({ row, col, x: ProcessingX, y: ProcessingY });
|
gridCoordinates.push({ row, col, x: ProcessingX, y: ProcessingY });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 图像识别函数
|
/*********************** 工具函数 ***********************/
|
||||||
function recognizeImage(imagePath, x, y, searchWidth, searchHeight) {
|
|
||||||
|
// 图像识别函数
|
||||||
|
function recognizeImage(imagePath, x, y, searchWidth, searchHeight) {
|
||||||
try {
|
try {
|
||||||
let template = file.ReadImageMatSync(imagePath);
|
let template = file.ReadImageMatSync(imagePath);
|
||||||
let recognitionObject = RecognitionObject.TemplateMatch(template, x, y, searchWidth, searchHeight);
|
let recognitionObject = RecognitionObject.TemplateMatch(template, x, y, searchWidth, searchHeight);
|
||||||
@@ -72,10 +74,24 @@ const ForgeRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("Assets/Re
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 自动前往铁匠铺
|
// 检查是否需要跳过该矿石(若已属于备选中)
|
||||||
async function autoSmithy(smithyName) {
|
function shouldSkipOre(targetOre, compareOres) {
|
||||||
|
return compareOres.includes(targetOre);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 通知日志:使用矿石提示
|
||||||
|
function determineOre(oreType) {
|
||||||
|
let message = `将使用 ${OreChineseMap[oreType]} 锻造矿石`;
|
||||||
|
log.info(message);
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************** 主逻辑函数 ***********************/
|
||||||
|
|
||||||
|
// 自动前往铁匠铺
|
||||||
|
async function autoSmithy(smithyName) {
|
||||||
log.info(`自动前往 ${smithyName}`);
|
log.info(`自动前往 ${smithyName}`);
|
||||||
try {
|
try {
|
||||||
let filePath = `assets/Pathing/${smithyName}.json`;
|
let filePath = `assets/Pathing/${smithyName}.json`;
|
||||||
@@ -92,29 +108,19 @@ const ForgeRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("Assets/Re
|
|||||||
log.error(`执行 ${smithyName} 路径时发生错误: ${error.toString()}`);
|
log.error(`执行 ${smithyName} 路径时发生错误: ${error.toString()}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 确认使用矿石
|
// 尝试识别并锻造矿石
|
||||||
function determineOre(oreType) {
|
async function tryForgeOre(oreType, skipCheckOres = []) {
|
||||||
let message = `将使用 ${OreChineseMap[oreType]} 锻造矿石`;
|
// 若矿石在跳过列表中则直接返回
|
||||||
log.info(message);
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查是否需要跳过备选矿物
|
|
||||||
function shouldSkipOre(targetOre, compareOres) {
|
|
||||||
return compareOres.includes(targetOre);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 尝试识别并锻造矿石
|
|
||||||
async function tryForgeOre(oreType, skipCheckOres = []) {
|
|
||||||
if (shouldSkipOre(oreType, skipCheckOres)) {
|
if (shouldSkipOre(oreType, skipCheckOres)) {
|
||||||
if (notice) {
|
if (notice) {
|
||||||
notification.send(`跳过 ${OreChineseMap[oreType]},因为已存在于优先选择中`);
|
//notification.send(`跳过 ${OreChineseMap[oreType]},因为已存在于优先选择中`);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取矿石图像路径
|
||||||
const imagePath = ingredientImageMap[oreType];
|
const imagePath = ingredientImageMap[oreType];
|
||||||
if (!imagePath) {
|
if (!imagePath) {
|
||||||
if (notice) {
|
if (notice) {
|
||||||
@@ -127,50 +133,39 @@ const ForgeRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("Assets/Re
|
|||||||
|
|
||||||
log.info(`开始识别矿石: ${OreChineseMap[oreType]}`);
|
log.info(`开始识别矿石: ${OreChineseMap[oreType]}`);
|
||||||
const scanOffset = { x: -35, y: -35 };
|
const scanOffset = { x: -35, y: -35 };
|
||||||
|
|
||||||
|
|
||||||
// 最大尝试次数
|
|
||||||
const maxAttempts = 3;
|
const maxAttempts = 3;
|
||||||
|
|
||||||
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
||||||
let found = false;
|
let found = false;
|
||||||
for (const coordinate of gridCoordinates) {
|
for (const coordinate of gridCoordinates) {
|
||||||
const scanX = coordinate.x + scanOffset.x;
|
const scanX = coordinate.x + scanOffset.x;
|
||||||
const scanY = coordinate.y + scanOffset.y;
|
const scanY = coordinate.y + scanOffset.y;
|
||||||
const imageResult = recognizeImage(imagePath, scanX, scanY, 70, 70);
|
const imageResult = recognizeImage(imagePath, scanX, scanY, 70, 70);
|
||||||
|
|
||||||
if (imageResult) {
|
if (imageResult) {
|
||||||
found = true;
|
found = true;
|
||||||
imageResult.click();
|
imageResult.click();
|
||||||
await sleep(1000);
|
await sleep(1000);
|
||||||
|
|
||||||
if (notice) {
|
if (notice) {
|
||||||
notification.send(`通过图像识别找到矿石: ${OreChineseMap[oreType]}`);
|
notification.send(`找到矿石: ${OreChineseMap[oreType]}`);
|
||||||
|
} else {
|
||||||
|
log.info(`找到矿石: ${OreChineseMap[oreType]}`);
|
||||||
}
|
}
|
||||||
determineOre(oreType);
|
determineOre(oreType);
|
||||||
|
|
||||||
// 点击“开始锻造”按钮3次,每次点击后进行OCR识别提示
|
// 点击“开始锻造”按钮并进行OCR识别
|
||||||
const ocrRegion = { x: 660, y: 495, width: 1250 - 660, height: 550 - 495 };
|
const ocrRegion = { x: 660, y: 495, width: 1250 - 660, height: 550 - 495 };
|
||||||
|
|
||||||
// 内部点击循环——点击“开始锻造”按钮后,进行OCR识别
|
|
||||||
let clickAttempts = 0;
|
let clickAttempts = 0;
|
||||||
let forgingTriggered = false;
|
let forgingTriggered = false;
|
||||||
|
|
||||||
while (clickAttempts < 3 && !forgingTriggered) {
|
while (clickAttempts < 3 && !forgingTriggered) {
|
||||||
// 点击“开始锻造”
|
|
||||||
let ConfirmButton = captureGameRegion().find(ConfirmDeployButtonRo);
|
let ConfirmButton = captureGameRegion().find(ConfirmDeployButtonRo);
|
||||||
if (ConfirmButton.isExist()) {
|
if (ConfirmButton.isExist()) {
|
||||||
//log.info("识别到确定按钮:({x},{y},{w},{h})", ConfirmButton.x, ConfirmButton.y, ConfirmButton.Width, ConfirmButton.Height);
|
|
||||||
ConfirmButton.click();
|
ConfirmButton.click();
|
||||||
} else {
|
clickAttempts++;
|
||||||
//log.warn("未能识别到确定按钮");
|
|
||||||
}
|
}
|
||||||
await sleep(1500); // 等待提示出现
|
await sleep(1500);
|
||||||
|
|
||||||
// 执行OCR识别提示区域内的文字
|
|
||||||
let ocrResults = captureGameRegion().find(
|
let ocrResults = captureGameRegion().find(
|
||||||
RecognitionObject.ocr(ocrRegion.x, ocrRegion.y, ocrRegion.width, ocrRegion.height)
|
RecognitionObject.ocr(ocrRegion.x, ocrRegion.y, ocrRegion.width, ocrRegion.height)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (ocrResults) {
|
if (ocrResults) {
|
||||||
log.info(`${ocrResults.text}`);
|
log.info(`${ocrResults.text}`);
|
||||||
if (ocrResults.text.includes("今日已无法锻造")) {
|
if (ocrResults.text.includes("今日已无法锻造")) {
|
||||||
@@ -179,34 +174,30 @@ const ForgeRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("Assets/Re
|
|||||||
} else {
|
} else {
|
||||||
log.info("检测到 今日已无法锻造 停止脚本");
|
log.info("检测到 今日已无法锻造 停止脚本");
|
||||||
}
|
}
|
||||||
return true; // 完全终止锻造流程
|
await click(960, 800);
|
||||||
} else if (ocrResults.text.includes("材料不足")) {
|
await sleep(1000);
|
||||||
|
return true; // 终止锻造流程
|
||||||
|
}
|
||||||
|
else if (ocrResults.text.includes("材料不足")) {
|
||||||
if (notice) {
|
if (notice) {
|
||||||
notification.send("检测到 材料不足 跳过当前矿物。请检查背包,及时补充矿物。");
|
notification.send("检测到 材料不足 跳过当前矿物。请检查背包,及时补充矿物。");
|
||||||
} else {
|
} else {
|
||||||
log.info("检测到 材料不足 跳过当前矿物。请检查背包,及时补充矿物。");
|
log.info("检测到 材料不足 跳过当前矿物。请检查背包,及时补充矿物。");
|
||||||
}
|
}
|
||||||
await click(960, 800); // 点击确定关闭提示
|
clickAttempts--; // 出现材料不足时减去一次点击计数
|
||||||
|
await click(960, 800);
|
||||||
await sleep(1000);
|
await sleep(1000);
|
||||||
return false; // 直接返回,跳过识别当前矿物
|
return false; // 跳过当前矿石
|
||||||
} else {
|
|
||||||
// 如果OCR识别结果没有检测到错误提示,则认为本次锻造指令有效
|
|
||||||
forgingTriggered = true;
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
//log.warn("未能识别到任何文字");
|
|
||||||
}
|
}
|
||||||
clickAttempts++;
|
if (clickAttempts === 3) {
|
||||||
|
return true; // 达到点击上限,终止锻造流程
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 如果本次尝试未识别到矿石,则等待后重试
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
if (notice) {
|
|
||||||
//notification.error(`未能识别到矿石: ${OreChineseMap[oreType]},重试中... (${attempt + 1}/${maxAttempts})`);
|
|
||||||
}
|
|
||||||
log.error(`未能识别到矿石: ${OreChineseMap[oreType]},重试中... (${attempt + 1}/${maxAttempts})`);
|
log.error(`未能识别到矿石: ${OreChineseMap[oreType]},重试中... (${attempt + 1}/${maxAttempts})`);
|
||||||
|
|
||||||
await sleep(1000);
|
await sleep(1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -216,96 +207,142 @@ const ForgeRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("Assets/Re
|
|||||||
log.error(`未能识别到矿石: ${OreChineseMap[oreType]},停止尝试`);
|
log.error(`未能识别到矿石: ${OreChineseMap[oreType]},停止尝试`);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 锻造矿石操作
|
// 对话、领取、锻造操作
|
||||||
const forgeOre = async function (smithyName) {
|
async function forgeOre(smithyName) {
|
||||||
// 对话部分(如果需要可打开注释)
|
// 对话部分
|
||||||
await sleep(1000); keyPress("F");
|
await sleep(1000);
|
||||||
await sleep(1000); await click(960, 1042);
|
keyPress("F");
|
||||||
await sleep(1000); await click(960, 1042);
|
await sleep(1000);
|
||||||
|
await click(960, 1042);
|
||||||
|
await sleep(1000);
|
||||||
|
await click(960, 1042);
|
||||||
|
|
||||||
|
// 搜索对话界面中的锻造图标
|
||||||
|
const maxAttempts = 3;
|
||||||
|
let dialogFound = false;
|
||||||
|
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
||||||
|
for (let i = 0; i < 3; i++) {
|
||||||
let Forge = captureGameRegion().find(ForgeRo);
|
let Forge = captureGameRegion().find(ForgeRo);
|
||||||
if (Forge.isExist()) {
|
if (Forge.isExist()) {
|
||||||
//log.info("识别到锻造图标:({x},{y},{w},{h})", Forge.x, Forge.y, Forge.Width, Forge.Height);
|
log.info("已找到对话界面锻造图标");
|
||||||
await Forge.click();
|
Forge.click();
|
||||||
} else {
|
dialogFound = true;
|
||||||
log.warn("未能识别到锻造图标");
|
|
||||||
}
|
|
||||||
await sleep(1000); await click(960, 1042);
|
|
||||||
|
|
||||||
await sleep(1000); await click(960, 1042);
|
|
||||||
|
|
||||||
//检测到锻造界面
|
|
||||||
for (let i = 0; i < 3; i++) {
|
|
||||||
let ForgingInterface = captureGameRegion().find(ForgingInterfaceRo);
|
|
||||||
if (ForgingInterface.isExist()) {
|
|
||||||
log.info("已进入锻造界面,准备锻造");
|
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
await sleep(1000);
|
await sleep(1000);
|
||||||
|
await click(960, 1042);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (dialogFound) break;
|
||||||
|
}
|
||||||
|
|
||||||
// 锻造领取(如果需要可打开注释)
|
// 检测锻造界面是否出现
|
||||||
//领取全部
|
if (dialogFound) {
|
||||||
const ClaimAllRo = RecognitionObject.TemplateMatch(file.ReadImageMatSync("Assets/RecognitionObject/全部领取.png"), 0, 900, 1920, 180);
|
let interfaceFound = false;
|
||||||
|
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
||||||
|
const ocrRegion = { x: 185, y: 125, width: 670 - 185, height: 175 - 125 };
|
||||||
|
let ocrResults = captureGameRegion().find(
|
||||||
|
RecognitionObject.ocr(ocrRegion.x, ocrRegion.y, ocrRegion.width, ocrRegion.height)
|
||||||
|
);
|
||||||
|
let innerFound = false;
|
||||||
|
for (let i = 0; i < 3; i++) {
|
||||||
|
let ForgingInterface = captureGameRegion().find(ForgingInterfaceRo);
|
||||||
|
if (ForgingInterface.isExist()) {
|
||||||
|
log.info("已进入锻造界面");
|
||||||
|
innerFound = true;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
await sleep(1000);
|
||||||
|
await click(960, 1042);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (innerFound) {
|
||||||
|
interfaceFound = true;
|
||||||
|
|
||||||
|
// 领取操作:点击全部领取及确认领取
|
||||||
|
const ClaimAllRo = RecognitionObject.TemplateMatch(
|
||||||
|
file.ReadImageMatSync("Assets/RecognitionObject/全部领取.png"),
|
||||||
|
0, 900, 1920, 180
|
||||||
|
);
|
||||||
let ClaimAll = captureGameRegion().find(ClaimAllRo);
|
let ClaimAll = captureGameRegion().find(ClaimAllRo);
|
||||||
if (ClaimAll.isExist()) {
|
if (ClaimAll.isExist()) {
|
||||||
//log.info("识别到全部领取按钮:({x},{y},{w},{h})", ClaimAll.x, ClaimAll.y, ClaimAll.Width, ClaimAll.Height);
|
|
||||||
ClaimAll.click();
|
ClaimAll.click();
|
||||||
await sleep(1000); // 等待提示出现
|
await sleep(1000);
|
||||||
|
|
||||||
//确认领取
|
|
||||||
let ConfirmButton = captureGameRegion().find(ConfirmDeployButtonRo);
|
let ConfirmButton = captureGameRegion().find(ConfirmDeployButtonRo);
|
||||||
if (ConfirmButton.isExist()) {
|
if (ConfirmButton.isExist()) {
|
||||||
//log.info("识别到确定按钮:({x},{y},{w},{h})", ConfirmButton.x, ConfirmButton.y, ConfirmButton.Width, ConfirmButton.Height);
|
|
||||||
ConfirmButton.click();
|
ConfirmButton.click();
|
||||||
} else {
|
if (ocrResults.text.includes("配方")) {
|
||||||
//log.warn("未能识别到确定按钮");
|
ocrResults.click();
|
||||||
}
|
}
|
||||||
|
await click(220, 150);
|
||||||
|
await sleep(1000); // 点击进入锻造界面
|
||||||
} else {
|
} else {
|
||||||
//log.warn("未能识别到全部领取按钮");
|
log.warn("未能识别到确定按钮");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
click(220, 150); await sleep(1000);
|
// 若设置为锻造,则依次尝试主选及备选矿石
|
||||||
|
if (forgedOrNot === "是") {
|
||||||
let forgeSuccess = false;
|
let forgeSuccess = false;
|
||||||
// 尝试主选矿石
|
|
||||||
if (await tryForgeOre(primaryOre, [])) {
|
if (await tryForgeOre(primaryOre, [])) {
|
||||||
forgeSuccess = true;
|
forgeSuccess = true;
|
||||||
}
|
} else if (await tryForgeOre(secondaryOre, [primaryOre])) {
|
||||||
// 如果主选识别失败,尝试备选矿石2
|
|
||||||
else if (await tryForgeOre(secondaryOre, [primaryOre])) {
|
|
||||||
forgeSuccess = true;
|
forgeSuccess = true;
|
||||||
}
|
} else if (await tryForgeOre(tertiaryOre, [primaryOre, secondaryOre])) {
|
||||||
// 如果备选矿石2也失败,尝试备选矿石3
|
|
||||||
else if (await tryForgeOre(tertiaryOre, [primaryOre, secondaryOre])) {
|
|
||||||
forgeSuccess = true;
|
forgeSuccess = true;
|
||||||
}
|
} else {
|
||||||
// 所有备选矿石都未能识别,结束锻造
|
|
||||||
else {
|
|
||||||
if (notice) {
|
if (notice) {
|
||||||
notification.error("所有备选矿石都未能识别,结束锻造");
|
notification.error("所有备选矿石都未能识别,结束锻造");
|
||||||
} else {
|
} else {
|
||||||
log.error("所有备选矿石都未能识别,结束锻造");
|
log.error("所有备选矿石都未能识别,结束锻造");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 退出锻造界面(如果需要可打开注释)
|
// 退出锻造前判断配方,如果出现“锻造队列”则点击
|
||||||
await click(520, 140); await sleep(1000);
|
const ocrRegionAfter = { x: 185, y: 125, width: 670 - 185, height: 175 - 125 };
|
||||||
|
let ocrResultsAfter = captureGameRegion().find(
|
||||||
|
RecognitionObject.ocr(ocrRegionAfter.x, ocrRegionAfter.y, ocrRegionAfter.width, ocrRegionAfter.height)
|
||||||
|
);
|
||||||
|
if (ocrResultsAfter.text.includes("锻造队列")) {
|
||||||
|
ocrResultsAfter.click();
|
||||||
|
await sleep(1000);
|
||||||
|
}
|
||||||
|
break; // 退出锻造界面检测循环
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!interfaceFound) {
|
||||||
|
log.error("经过多次尝试,未能进入锻造界面");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.info("未能找到对话界面锻造图标,无法进入锻造流程");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 退出锻造界面并返回主界面
|
||||||
if (notice) {
|
if (notice) {
|
||||||
notification.send("锻造结束,退出界面");
|
notification.send("锻造结束,退出界面");
|
||||||
} else {
|
} else {
|
||||||
log.info("锻造结束,退出界面");
|
log.info("锻造结束,退出界面");
|
||||||
}
|
}
|
||||||
await genshin.returnMainUi();
|
await genshin.returnMainUi();
|
||||||
};
|
}
|
||||||
|
|
||||||
|
/*********************** 主执行入口 ***********************/
|
||||||
|
|
||||||
|
(async function () {
|
||||||
|
// 初始化及前往铁匠铺
|
||||||
|
setGameMetrics(1920, 1080, 1.25);
|
||||||
|
await genshin.returnMainUi();
|
||||||
|
if (notice) {
|
||||||
|
notification.send("自动锻造矿石脚本开始");
|
||||||
|
}
|
||||||
|
|
||||||
// 执行步骤
|
|
||||||
await autoSmithy(smithyName);
|
await autoSmithy(smithyName);
|
||||||
await forgeOre(smithyName);
|
await forgeOre(smithyName);
|
||||||
await genshin.returnMainUi();
|
await genshin.returnMainUi();
|
||||||
|
|
||||||
|
// 后退两步
|
||||||
{ keyDown("S"); await sleep(1000); keyUp("S"); await sleep(1000); }
|
{ keyDown("S"); await sleep(1000); keyUp("S"); await sleep(1000); }
|
||||||
|
|
||||||
if (notice) {
|
if (notice) {
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
"manifest_version": 1,
|
"manifest_version": 1,
|
||||||
"name": "自动锻造魔矿",
|
"name": "自动锻造魔矿",
|
||||||
"version": "2.0\n(2025.05.22版)",
|
"version": "2.00523\n(2025.05.23版)",
|
||||||
"bgi_version": "0.44.0",
|
"bgi_version": "0.44.0",
|
||||||
"description": "自动选择铁匠铺和使用矿物去锻造精锻矿。\n \n使用前请阅读“readme”文件。 \n---更新说明--- \n- 新增矿石不足时自动选择备用选矿",
|
"description": "自动选择铁匠铺和使用矿物去锻造精锻矿。\n新增功能:仅领取锻造 - 允许用户仅领取已完成的锻造物品,而不进行新的锻造。\n \n使用前请阅读“readme”文件以获取更多详细信息。 \n---更新说明--- \n- 请查阅readme",
|
||||||
"tags": ["铁匠铺", "锻造", "精锻用矿"],
|
"tags": ["铁匠铺", "锻造", "精锻用矿"],
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// ==UserScript==
|
// ==UserScript==
|
||||||
// @name 自动锻造魔矿脚本
|
// @name 自动锻造魔矿脚本
|
||||||
// @version 1.40521
|
// @version 2.00523
|
||||||
// @description 自动前往铁匠铺并锻造魔矿,通过识图模式自动选择矿石
|
// @description 自动前往铁匠铺并锻造魔矿,通过识图模式自动选择矿石
|
||||||
// @author 呱呱 z
|
// @author 呱呱 z
|
||||||
// @match 原神版本:5.6;BGI 版本:0.45.1
|
// @match 原神版本:5.6;BGI 版本:0.45.1
|
||||||
@@ -55,6 +55,11 @@
|
|||||||
|
|
||||||
## 更新日志
|
## 更新日志
|
||||||
|
|
||||||
|
### 2.00523(2025.05.23)
|
||||||
|
- 新增仅领取锻造
|
||||||
|
- 优化点击逻辑
|
||||||
|
- 修复点击锻造的次数超过3次的bug
|
||||||
|
|
||||||
### 2.0(2025.05.22)
|
### 2.0(2025.05.22)
|
||||||
- 新增矿石不足时自动选择备用选矿
|
- 新增矿石不足时自动选择备用选矿
|
||||||
|
|
||||||
@@ -16,6 +16,15 @@
|
|||||||
"枫丹铁匠铺"
|
"枫丹铁匠铺"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "forgedOrNot",
|
||||||
|
"type": "select",
|
||||||
|
"label": "是否进行锻造(默认:是)\n可用于仅领取锻造",
|
||||||
|
"options": [
|
||||||
|
"是",
|
||||||
|
"否"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "ore",
|
"name": "ore",
|
||||||
"type": "select",
|
"type": "select",
|
||||||
|
|||||||
Reference in New Issue
Block a user