From fb76d2b0fc863a2dc306d0a269867aa8566edb3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=89=E5=90=89=E5=96=B5?= Date: Wed, 28 Jan 2026 15:40:38 +0800 Subject: [PATCH] =?UTF-8?q?=E9=80=82=E9=85=8D=E8=AF=BA=E5=BE=B7=E5=8D=A1?= =?UTF-8?q?=E8=8E=B1=E6=AD=A6=E5=99=A8=20(#2799)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 适配诺德卡莱武器 * Add files via upload * Delete repo/js/OCR文字坐标/assets directory * Update manifest.json --- repo/js/OCR切换武器/assets/combat_avatar.json | 100 +++++++++++ repo/js/OCR切换武器/assets/weaponName.json | 46 ++--- repo/js/OCR切换武器/manifest.json | 6 +- repo/js/OCR文字坐标/main.js | 165 ++++++++++++++++++ repo/js/OCR文字坐标/manifest.json | 15 ++ repo/js/OCR文字坐标/settings.json | 7 + 6 files changed, 313 insertions(+), 26 deletions(-) create mode 100644 repo/js/OCR文字坐标/main.js create mode 100644 repo/js/OCR文字坐标/manifest.json create mode 100644 repo/js/OCR文字坐标/settings.json diff --git a/repo/js/OCR切换武器/assets/combat_avatar.json b/repo/js/OCR切换武器/assets/combat_avatar.json index 26610089d..743156077 100644 --- a/repo/js/OCR切换武器/assets/combat_avatar.json +++ b/repo/js/OCR切换武器/assets/combat_avatar.json @@ -47,6 +47,26 @@ "nameEn": "PlayerBoy", "weapon": "1" }, + { + "alias": [ + "奇偶(男)", + "MannequinBoy" + ], + "id": "10000117", + "name": "奇偶(男)", + "nameEn": "MannequinBoy", + "weapon": "1" + }, + { + "alias": [ + "奇偶(女)", + "MannequinGirl" + ], + "id": "10000118", + "name": "奇偶(女)", + "nameEn": "MannequinGirl", + "weapon": "1" + }, { "alias": [ "神里绫华", @@ -1949,5 +1969,85 @@ "nameEn": "Aino", "skillCD": 10, "weapon": "11" + }, + { + "alias": [ + "奈芙尔", + "Nefer" + ], + "burstCD": 15, + "id": "10000122", + "name": "奈芙尔", + "nameEn": "Nefer", + "skillCD": 9, + "weapon": "10" + }, + { + "alias": [ + "杜林", + "Durin" + ], + "burstCD": 18, + "id": "10000123", + "name": "杜林", + "nameEn": "Durin", + "skillCD": 12, + "weapon": "10" + }, + { + "alias": [ + "雅珂达", + "Jahoda" + ], + "burstCD": 18, + "id": "10000124", + "name": "雅珂达", + "nameEn": "Jahoda", + "skillCD": 15, + "weapon": "10" + }, + { + "alias": [ + "哥伦比娅", + "Columbina", + "少女", + "库塔尔", + "月神", + "月之少女" + ], + "burstCD": 15, + "id": "10000125", + "name": "哥伦比娅", + "nameEn": "Columbina", + "skillCD": 17, + "weapon": "10" + }, + { + "alias": [ + "兹白", + "Zibai", + "白马仙人", + "白马" + ], + "burstCD": 15, + "id": "10000126", + "name": "兹白", + "nameEn": "Zibai", + "skillCD": 18, + "weapon": "10" + }, + { + "alias": [ + "叶洛亚", + "Illuga", + "少爷", + "小少爷" + ], + "burstCD": 15, + "id": "10000127", + "name": "叶洛亚", + "nameEn": "Illuga", + "skillCD": 15, + "weapon": "10" } ] \ No newline at end of file diff --git a/repo/js/OCR切换武器/assets/weaponName.json b/repo/js/OCR切换武器/assets/weaponName.json index a1fb9121b..e9ac0dd65 100644 --- a/repo/js/OCR切换武器/assets/weaponName.json +++ b/repo/js/OCR切换武器/assets/weaponName.json @@ -1,23 +1,23 @@ -[ - { - "单手剑": ["无锋剑", "银剑", "冷刃", "黎明神剑", "旅行剑", "吃虎鱼刀", "飞天御剑", "暗铁剑", "笛剑", "西风剑", "匣里龙吟", "铁蜂刺", "试作斩岩", "祭礼剑", "宗室长剑", "黑岩长剑", "黑剑", "腐殖之剑", "降临之剑", "暗巷闪光", "天目影打刀", "东花坊时雨", "辰砂之纺锤", "原木刀", "西福斯的月光", "笼钓瓶一心", "狼牙", "海渊终曲", "船坞长剑", "灰河渡手", "息燧之笛", "弥坚骨", "厄水之祸", "斫峰之刃", "风鹰剑", "天空之刃", "磐岩结绿", "雾切之回光", "苍古自由之誓", "波乱月白经津", "圣显之钥", "裁叶萃光", "静水流涌之辉", "有乐御簾切", "赦罪", "岩峰巡歌"] - }, - { - "双手剑": ["训练大剑", "佣兵重剑", "以理服人", "铁影阔剑", "飞天大御剑", "白铁大剑", "沐浴龙血的剑", "祭礼大剑", "西风大剑", "钟剑", "试作古华", "黑岩斩刀", "宗室大剑", "白影剑", "雨裁", "螭骨剑", "雪葬的星银", "桂木斩长正", "衔珠海皇", "千岩古剑", "恶王丸", "玛海拉的水色", "饰铁之花", "聊聊棒", "森林王器", "浪影阔剑", "便携动力锯", "「究极霸王超级魔剑」", "撼地者", "硕果钩", "松籁响起之时", "狼的末路", "天空之傲", "赤角石溃杵", "无工之剑", "裁断", "山王长牙", "苇海信标", "焚曜干阳"] - }, - { - "长枪": ["新手长枪", "铁尖枪", "黑缨枪", "钺矛", "白缨枪", "匣里灭辰", "试作星镰", "决斗之枪", "流月针", "黑岩刺枪", "干岩长枪", "喜多院十文字", "西风长枪", "宗室猎枪", "龙脊长枪", "断浪长鳍", "风信之锋", "「渔获」", "贯月矢", "峡湾长歌", "沙中伟贤的对答", "勘探钻机", "虹的行迹", "公义的酬报", "镇山之钉", "且住亭御咄", "和璞鸢", "天空之脊", "贯虹之槊", "护摩之杖", "薙草之稻光", "息灾", "赤月之形", "柔灯挽歌", "赤沙之杖"] - }, - { - "弓箭": ["猎弓", "历练的猎弓", "鸦羽弓", "神射手之誓", "信使", "反曲弓", "弹弓", "绝弦", "西风猎弓", "弓藏", "试作澹月", "祭礼弓", "宗室长弓", "钢轮弓", "风花之颂", "幽夜华尔兹", "黑岩战弓", "暗巷猎手", "苍翠猎弓", "曚云之月", "破魔之弓", "落霞", "王下近侍", "竭泽", "烈阳之嗣", "测距规", "静谧之曲", "鹦穿之喙", "筑云", "缀花之翎", "碎链", "天空之翼", "阿莫斯之弓", "终末嗟叹之诗", "冬极白星", "猎人之径", "飞雷之弦振", "若水", "白雨心弦", "最初的大魔术", "星鹫赤羽"] - }, - { - "法器": ["学徒笔记", "口袋魔导书", "魔导绪论", "讨龙英杰谭", "翡玉法球", "甲级宝珏", "异世界行记", "西风秘典", "流浪乐章", "祭礼残章", "宗室秘法录", "匣里日月", "万国诸海图谱", "黑岩绯玉", "昭心", "试作金珀", "暗巷的酒与诗", "白辰之环", "忍冬之果", "嘟嘟可故事集", "证誓之明瞳", "盈满之实", "流浪的晚星", "纯水流华", "无垠蔚蓝之歌", "遗祀玉珑", "苍纹角杯", "木棉之环", "乘浪的回旋", "天空之卷", "四风原典", "不灭月华", "千夜浮梦", "尘世之锁", "神乐之真意", "图莱杜拉的回忆", "金流监督", "碧落之珑", "冲浪时光", "万世流涌大典", "鹤鸣余音", "寝正月初睛", "溢彩心念", "祭星者之望"] - }, - { - "低星": [ "无锋剑", "训练大剑", "学徒笔记", "新手长枪", "猎弓", "口袋魔导书", "银剑", "佣兵重剑", "铁尖枪", "历练的猎弓"] - }, - { - "三星": [ "冷刃", "飞天御剑", "黎明神剑", "旅行剑", "暗铁剑", "以理服人", "铁影阔剑", "白铁大剑", "钺矛", "魔导绪论", "黑缨枪", "讨龙英杰谭", "翡玉法球", "异世界行记", "鸦羽弓", "甲级宝珏", "神射手之誓", "信使", "反曲弓", "弹弓"] - } -] +[ + { + "单手剑": ["无锋剑", "银剑", "冷刃", "黎明神剑", "旅行剑", "吃虎鱼刀", "飞天御剑", "暗铁剑", "笛剑", "西风剑", "匣里龙吟", "铁蜂刺", "试作斩岩", "祭礼剑", "宗室长剑", "黑岩长剑", "黑剑", "腐殖之剑", "降临之剑", "暗巷闪光", "天目影打刀", "东花坊时雨", "辰砂之纺锤", "原木刀", "西福斯的月光", "笼钓瓶一心", "狼牙", "海渊终曲", "船坞长剑", "灰河渡手", "息燧之笛", "弥坚骨", "厄水之祸", "谧音吹哨", "织月者的曙色", "斫峰之刃", "风鹰剑", "天空之刃", "磐岩结绿", "雾切之回光", "苍古自由之誓", "波乱月白经津", "圣显之钥", "裁叶萃光", "静水流涌之辉", "有乐御簾切", "赦罪", "岩峰巡歌", "苍耀", "黑蚀", "朏魄含光"] + }, + { + "双手剑": ["训练大剑", "佣兵重剑", "以理服人", "铁影阔剑", "飞天大御剑", "白铁大剑", "沐浴龙血的剑", "祭礼大剑", "西风大剑", "钟剑", "试作古华", "黑岩斩刀", "宗室大剑", "白影剑", "雨裁", "螭骨剑", "雪葬的星银", "桂木斩长正", "衔珠海皇", "千岩古剑", "恶王丸", "玛海拉的水色", "饰铁之花", "聊聊棒", "森林王器", "浪影阔剑", "便携动力锯", "「究极霸王超级魔剑」", "撼地者", "硕果钩", "拾慧铸熔", "万能钥匙", "松籁响起之时", "狼的末路", "天空之傲", "赤角石溃杵", "无工之剑", "裁断", "山王长牙", "苇海信标", "焚曜干阳"] + }, + { + "长枪": ["新手长枪", "铁尖枪", "黑缨枪", "钺矛", "白缨枪", "匣里灭辰", "试作星镰", "决斗之枪", "流月针", "黑岩刺枪", "干岩长枪", "喜多院十文字", "西风长枪", "宗室猎枪", "龙脊长枪", "断浪长鳍", "风信之锋", "「渔获」", "贯月矢", "峡湾长歌", "沙中伟贤的对答", "勘探钻机", "虹的行迹", "公义的酬报", "镇山之钉", "且住亭御咄", "掘金之锹", "圣祭者的辉杖", "和璞鸢", "天空之脊", "贯虹之槊", "护摩之杖", "薙草之稻光", "息灾", "赤沙之杖", "赤月之形", "柔灯挽歌", "香韵奏者", "支离轮光", "血染荒城"] + }, + { + "弓箭": ["猎弓", "历练的猎弓", "鸦羽弓", "神射手之誓", "信使", "反曲弓", "弹弓", "绝弦", "西风猎弓", "弓藏", "试作澹月", "祭礼弓", "宗室长弓", "钢轮弓", "风花之颂", "幽夜华尔兹", "黑岩战弓", "暗巷猎手", "苍翠猎弓", "曚云之月", "破魔之弓", "落霞", "王下近侍", "竭泽", "烈阳之嗣", "测距规", "静谧之曲", "鹦穿之喙", "筑云", "缀花之翎", "碎链", "冷寂迸音", "罗网勾针", "虹蛇的雨弦", "天空之翼", "阿莫斯之弓", "终末嗟叹之诗", "冬极白星", "猎人之径", "飞雷之弦振", "若水", "白雨心弦", "最初的大魔术", "星鹫赤羽", "黎明破晓之史"] + }, + { + "法器": ["学徒笔记", "口袋魔导书", "魔导绪论", "讨龙英杰谭", "翡玉法球", "甲级宝珏", "异世界行记", "西风秘典", "流浪乐章", "祭礼残章", "宗室秘法录", "匣里日月", "万国诸海图谱", "黑岩绯玉", "昭心", "试作金珀", "暗巷的酒与诗", "白辰之环", "忍冬之果", "嘟嘟可故事集", "证誓之明瞳", "盈满之实", "流浪的晚星", "纯水流华", "无垠蔚蓝之歌", "遗祀玉珑", "苍纹角杯", "木棉之环", "乘浪的回旋", "天光的纺琴", "乌髓孑灯", "霜辰", "天空之卷", "四风原典", "不灭月华", "千夜浮梦", "尘世之锁", "神乐之真意", "图莱杜拉的回忆", "金流监督", "碧落之珑", "冲浪时光", "万世流涌大典", "鹤鸣余音", "寝正月初睛", "溢彩心念", "祭星者之望", "寝正月初晴", "溢彩心念", "纺夜天镜", "真语秘匣", "帷间夜曲"] + }, + { + "低星": [ "无锋剑", "训练大剑", "学徒笔记", "新手长枪", "猎弓", "口袋魔导书", "银剑", "佣兵重剑", "铁尖枪", "历练的猎弓"] + }, + { + "三星": [ "冷刃", "飞天御剑", "黎明神剑", "旅行剑", "暗铁剑", "以理服人", "铁影阔剑", "白铁大剑", "钺矛", "魔导绪论", "黑缨枪", "讨龙英杰谭", "翡玉法球", "异世界行记", "鸦羽弓", "甲级宝珏", "神射手之誓", "信使", "反曲弓", "弹弓"] + } +] diff --git a/repo/js/OCR切换武器/manifest.json b/repo/js/OCR切换武器/manifest.json index f7e7cd0a7..00ff87aa8 100644 --- a/repo/js/OCR切换武器/manifest.json +++ b/repo/js/OCR切换武器/manifest.json @@ -1,12 +1,12 @@ { "manifest_version": 1, "name": "选择角色和武器 ", - "version": "2.22", + "version": "2.23", "description": "OCR。默认四行为一页;v2.1增加模糊匹配,增加别名匹配。v2.22兼容未知角色、未知武器", "authors": [ { - "name": "吉吉喵", - "links": "https://github.com/JJMdzh" + "name": "吉吉喵", + "links": "https://github.com/JJMdzh" } ], "settings_ui": "settings.json", diff --git a/repo/js/OCR文字坐标/main.js b/repo/js/OCR文字坐标/main.js new file mode 100644 index 000000000..edacac012 --- /dev/null +++ b/repo/js/OCR文字坐标/main.js @@ -0,0 +1,165 @@ +// 核心控制变量 +let keyMouseHook = null; +let isAltPressed = false; +let firstPoint = null; +let isScriptRunning = true; + +// ===================== 红框绘制函数(精简日志)===================== +async function drawAndClearRedBox(searchRegion, ra, delay = 500) { + if (!isScriptRunning || !ra || !searchRegion || searchRegion.width <= 0 || searchRegion.height <= 0) return; + + let drawRegion = null; + try { + drawRegion = ra.DeriveCrop(searchRegion.x, searchRegion.y, searchRegion.width, searchRegion.height); + drawRegion.DrawSelf("rect"); + await sleep(delay); + ra.DeriveCrop(0, 0, 0, 0).DrawSelf("rect"); + } catch (e) { + if (!e.message.includes("task was canceled")) log.error(`红框绘制异常:${e.message}`); + } finally { + if (drawRegion && typeof drawRegion.dispose === 'function') drawRegion.dispose(); + } +} + +// ===================== OCR函数(指定XYWH格式+识图范围+两点坐标)===================== +async function performOcrOnce(x1, y1, x2, y2) { + if (!isScriptRunning) return; + + log.info(`===== 开始OCR识别 =====`); + log.info(`识别区域:左上(${x1},${y1}) → 右下(${x2},${y2})`); + + const ra = captureGameRegion(); + if (!ra) { + log.error("OCR失败:未捕获到游戏区域"); + log.info(`===== OCR识别结束 =====\n`); + return; + } + + const width = x2 - x1; + const height = y2 - y1; + if (width <= 0 || height <= 0) { + log.error(`OCR失败:无效区域(宽=${width},高=${height})`); + ra.dispose(); + log.info(`===== OCR识别结束 =====\n`); + return; + } + + let resList = ra.findMulti(RecognitionObject.ocr(x1, y1, width, height)); + log.info(`OCR识别完成,共识别到 ${resList.count} 段文本:`); + + if (resList.count === 0) { + log.info("识别结果:无文本"); + } else { + for (let i = 0; i < resList.count; i++) { + const res = resList[i]; + // 核心XYWH信息 + const xywh = `x: ${res.x}, y: ${res.y}, width: ${res.width}, height: ${res.height}`; + // 识图范围推荐(x-1, y-1, width+2, height+2) + const recommendRange = `识图范围推荐: ${res.x-1}, ${res.y-1}, ${res.width+2}, ${res.height+2}`; + // 两点坐标(左上/右下) + const leftTop = `(${res.x},${res.y})`; + const rightBottom = `(${res.x + res.width},${res.y + res.height})`; + const twoPoint = `坐标范围:左上${leftTop} → 右下${rightBottom}`; + + // 按指定格式输出完整信息 + log.info(`结果[${i+1}]:文字="${res.text}" | ${xywh} | ${recommendRange} | ${twoPoint}`); + } + } + + ra.dispose(); + log.info(`===== OCR识别结束 =====\n`); +} + +// ===================== 优雅退出 ===================== +function gracefulExit() { + isScriptRunning = false; + if (keyMouseHook && typeof keyMouseHook.dispose === 'function') { + keyMouseHook.dispose(); + } + log.info("脚本已终止,资源已释放"); +} + +// ===================== 主函数(修复语法错误+精简日志)===================== +async function main() { + log.info("========== OCR识别脚本启动 =========="); + log.info("操作说明:按住左Alt+右键选两点 → 触发OCR识别;Alt+左键重置"); + + // 创建键鼠钩子 + keyMouseHook = new KeyMouseHook(); + if (!keyMouseHook) { + log.error("键鼠钩子创建失败!请以管理员运行BGI"); + return; + } + + // 监听Alt键(LMenu/RMenu) + keyMouseHook.OnKeyDown((keyCode) => { + if (!isScriptRunning) return; + if (keyCode === "LMenu" || keyCode === "RMenu") { + isAltPressed = true; + } + }, true); + + keyMouseHook.OnKeyUp((keyCode) => { + if (!isScriptRunning) return; + if (keyCode === "LMenu" || keyCode === "RMenu") { + isAltPressed = false; + firstPoint = null; + log.info("Alt键释放,标记已重置"); + } + }, true); + + // 监听鼠标点击 + keyMouseHook.OnMouseDown(async (button, x, y) => { + if (!isScriptRunning || !isAltPressed) return; + + // Alt+右键:选点/触发OCR + if (button === "Right") { + if (!firstPoint) { + firstPoint = { x, y }; + log.info(`标记起点:(${x}, ${y})`); + const ra = captureGameRegion(); + await drawAndClearRedBox({ x: x - 1, y: y - 1, width: 2, height: 2 }, ra, 2000); + if (ra && typeof ra.dispose === 'function') ra.dispose(); + } else { + log.info(`标记终点:(${x}, ${y})`); + const newX1 = Math.min(firstPoint.x, x); + const newY1 = Math.min(firstPoint.y, y); + const newX2 = Math.max(firstPoint.x, x); + const newY2 = Math.max(firstPoint.y, y); + + // 绘制范围红框 + const ra = captureGameRegion(); + await drawAndClearRedBox({ x: newX1, y: newY1, width: newX2 - newX1, height: newY2 - newY1 }, ra, 3000); + if (ra && typeof ra.dispose === 'function') ra.dispose(); + + // 执行OCR + await performOcrOnce(newX1, newY1, newX2, newY2); + firstPoint = null; + } + } + // Alt+左键:重置 + else if (button === "Left") { + firstPoint = null; + log.info("标记状态已重置,可重新选点"); + } + }); + + // 常驻循环 + try { + while (isScriptRunning) { + await sleep(100); + } + } catch (e) { + if (!e.message.includes("task was canceled")) log.error(`脚本异常:${e.message}`); + } finally { + gracefulExit(); + } +} + +// 调用主函数并处理异常(修复.catch语法错误) +main().catch((e) => { + if (!e.message.includes("task was canceled")) { + log.error(`全局异常:${e.message}`); + } + gracefulExit(); +}); \ No newline at end of file diff --git a/repo/js/OCR文字坐标/manifest.json b/repo/js/OCR文字坐标/manifest.json new file mode 100644 index 000000000..88d61597d --- /dev/null +++ b/repo/js/OCR文字坐标/manifest.json @@ -0,0 +1,15 @@ +{ + "manifest_version": 1, + "name": "OCR文字坐标", + "version": "1.2", + "bgi_version": "0.55", + "description": "操作说明:按住左Alt+右键选两点 → 触发OCR识别;Alt+左键重置", + "authors": [ + { + "name": "吉吉喵", + "links": "https://github.com/JJMdzh" + } + ], + "settings_ui": "settings.json", + "main": "main.js" + } diff --git a/repo/js/OCR文字坐标/settings.json b/repo/js/OCR文字坐标/settings.json new file mode 100644 index 000000000..b3fbbcf3e --- /dev/null +++ b/repo/js/OCR文字坐标/settings.json @@ -0,0 +1,7 @@ +[ + { + "name": "AssetsDir", + "type": "checkbox", + "label": "操作说明:按住左Alt+右键选两点 → 触发OCR识别;Alt+左键重置" + } +]