JS脚本:一只爱可菲(厨娘版)【更新】 (#1159)

* 适应性更新

* 修复了已知问题(无法制作特色料理)
This commit is contained in:
提瓦特钓鱼玳师
2025-06-21 22:08:20 +08:00
committed by GitHub
parent 5752f63db3
commit ccc85a254b
4 changed files with 986 additions and 881 deletions

View File

@@ -46,6 +46,54 @@
// 食物数据
const food_dic = JSON.parse(file.readTextSync("assets/food_dic.json"));
/**
* 供 findClosestMatch 调用
*/
function levenshteinDistance(a, b) {
const matrix = [];
for (let i = 0; i <= b.length; i++) {
matrix[i] = [i];
}
for (let j = 0; j <= a.length; j++) {
matrix[0][j] = j;
}
for (let i = 1; i <= b.length; i++) {
for (let j = 1; j <= a.length; j++) {
if (b.charAt(i - 1) === a.charAt(j - 1)) {
matrix[i][j] = matrix[i - 1][j - 1];
} else {
matrix[i][j] = Math.min(
matrix[i - 1][j - 1] + 1, // 替换
matrix[i][j - 1] + 1, // 插入
matrix[i - 1][j] + 1 // 删除
);
}
}
}
return matrix[b.length][a.length];
}
/**
*
* 查找最相似的字符串用于查找料理最大限度避免OCR偏差导致的异常
*
* @param target 目标字符串
* @param candidates 字符串数组
* @returns {null}
*/
function findClosestMatch(target, candidates) {
let closest = null;
let minDistance = Infinity;
for (const candidate of candidates) {
const distance = levenshteinDistance(target, candidate);
if (distance < minDistance) {
minDistance = distance;
closest = candidate;
}
}
return closest;
}
/**
*
* 解析food_dic的食物数据
@@ -316,7 +364,10 @@
let ocr = captureGameRegion().FindMulti(ocrRo); // 当前页面OCR
if (ocr.count !== 0) {
for (let i = 0; i < ocr.count; i++) {
if (ocr[i].text === food_name) {
let food_name_deal = await Promise.all(
Object.keys(food_dic).map(async (x) => await deal_string(x))
);
if (findClosestMatch(ocr[i].text, food_name_deal) === food_name) { // 【DEBUG】
log.info(`找到了 ${food_name} `);
ocr[i].Click();
return true;
@@ -821,7 +872,7 @@
"food_character_num": food_character_num,
"select_cooking_mode": select_cooking_mode,
"extra_time": extraTime,
"check_quality": check_quality,
"check_quality": false, // 【DEBUG】禁用料理结果识别
"prime_cooking": prime_cooking
}
}
@@ -846,6 +897,8 @@
for (let i = 0; i < name_can_make.length; i++) {
task_dic["cooking"][name_can_make[i]] = setting_dic["food_num"];
}
} else if (setting_dic["food_choice_single_select"] === "无(默认)") {
task_dic["cooking"] = {};
} else {
task_dic["cooking"][setting_dic["food_choice_single_select"]] = setting_dic["food_num"];
}
@@ -983,12 +1036,12 @@
task_dic["character"] = {};
} else if (setting_dic["food_character_select"] === "全部角色") {
for (let i = 0; i < name_character_food.length; i++) {
task_dic["character"][name_character_food[i]] = setting_dic["food_character_num"];
task_dic["cooking"][name_character_food[i]] = setting_dic["food_character_num"];
}
} else {
for (const [name, detail] of Object.entries(food_dic)) {
if (detail["character"] === setting_dic["food_character_select"]) {
task_dic["character"][name] = setting_dic["food_character_num"];
task_dic["cooking"][name] = setting_dic["food_character_num"];
}
}
}
@@ -1009,7 +1062,7 @@
let all_character = Object.keys(character_detail_dic);
for (const [name, detail] of Object.entries(food_dic)) {
if (all_character.includes(detail["character"])) {
task_dic["character"][name] = character_detail_dic[detail["character"]];
task_dic["cooking"][name] = character_detail_dic[detail["character"]];
}
}
}
@@ -1152,10 +1205,16 @@
* @returns {Promise<boolean>} 成功返回true否则false
*/
async function auto_cooking(food_name, setting_dic) {
let current_item_name = await recognize_item_name();
food_name = findClosestMatch(food_name, Object.keys(food_dic)); // 【DEBUG】
let current_item_name = findClosestMatch(await recognize_item_name(), Object.keys(food_dic));
if (typeof(setting_dic["cooking"][food_name]) === "undefined") {
log.error(`请确保JS脚本配置中输入了正确的料理名称: ${food_name} 匹配错误`);
log.info(`${Object.keys(setting_dic["cooking"]).join("|")}`);
return false;
}
// 检测界面
if (!is_food_page()) return false;
// 二次验证食材名
// 二次验证食材名【DEBUG】经过先前的字符串距离筛选此处理应不可能找不到
if (!Object.keys(food_dic).includes(food_name)) {
log.warn(`food_dic内未找到名为-${food_name}-的料理,料理名称传入错误或料理数据需要更新`);
return false;
@@ -1308,8 +1367,8 @@
unlock = await is_unlock(); // 检测当前食材是否已经解锁
}
if (unlock_flag) {
const loop_time = Math.floor(cook_num / 99) + 1; // 总计循环数一次最大99
let cook_num = setting_dic["cooking"][food_name] + 0; // 设定的数量
const loop_time = Math.floor(cook_num / 99) + 1; // 总计循环数一次最大99
for (let i = 0; i < loop_time; i++) {
let cook_time = i !== loop_time - 1 ? 99: cook_num - i * 99; // 本次烹饪数
await click(890, 1016); // 点击自动烹饪