From be436b66a7ba4becae59b97ea543ad549cf5b9e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E9=B9=8F?= Date: Mon, 23 Mar 2026 09:25:22 +0800 Subject: [PATCH] =?UTF-8?q?add=20=E9=A3=9E=E8=A1=8C=E7=8A=B6=E6=80=81?= =?UTF-8?q?=E3=80=81=E4=B8=8A=E9=A9=AC=E7=8A=B6=E6=80=81=E3=80=81=E8=B7=9F?= =?UTF-8?q?=E9=9A=8F=E7=8A=B6=E6=80=81=E7=9B=91=E6=8E=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- LogicBeacon/LogicBeacon.lua | 61 ++++++++++++++++-- __pycache__/game_state.cpython-311.pyc | Bin 9027 -> 11529 bytes game_state.py | 75 ++++++++++++++++++---- game_state_config.json | 2 +- screenshot/game_state.png | Bin 602 -> 88 bytes screenshot/game_state_flight_block.png | Bin 0 -> 74 bytes screenshot/game_state_follow.png | Bin 0 -> 74 bytes screenshot/game_state_hp.png | Bin 88 -> 74 bytes screenshot/game_state_logistics_death.png | Bin 83 -> 74 bytes screenshot/game_state_mp.png | Bin 90 -> 74 bytes screenshot/game_state_target.png | Bin 86 -> 74 bytes screenshot/game_state_x.png | Bin 84 -> 74 bytes screenshot/game_state_y.png | Bin 83 -> 74 bytes wow_multikey_gui.py | 16 +---- 14 files changed, 122 insertions(+), 32 deletions(-) create mode 100644 screenshot/game_state_flight_block.png create mode 100644 screenshot/game_state_follow.png diff --git a/LogicBeacon/LogicBeacon.lua b/LogicBeacon/LogicBeacon.lua index 44212b3..e897709 100644 --- a/LogicBeacon/LogicBeacon.lua +++ b/LogicBeacon/LogicBeacon.lua @@ -4,9 +4,9 @@ 供外部 Python 等脚本截取小区域即可获取完整状态机。 ]] --- 配置:8个状态位(1个白色锚点 + 7个数据位) +-- 配置:10个状态位(1个白色锚点 + 9个数据位) local PIXEL_SIZE = 10 -local STATUS_COUNT = 8 +local STATUS_COUNT = 10 local ADDON_NAME = "LogicBeacon" -- 默认配置(可被 SavedVariables 覆盖) @@ -27,8 +27,8 @@ for k, v in pairs(defaults) do LogicBeaconDB[k] = v end end --- 升级:至少 8 个状态位(含目标位+后勤位+坐标朝向) -LogicBeaconDB.statusCount = math.max(LogicBeaconDB.statusCount or 0, 8) +-- 升级:至少 10 个状态位(含跟随信号) +LogicBeaconDB.statusCount = math.max(LogicBeaconDB.statusCount or 0, 10) local db = LogicBeaconDB @@ -48,7 +48,7 @@ local bg = f:CreateTexture(nil, "BACKGROUND") bg:SetAllPoints() bg:SetColorTexture(0, 0, 0, 1) --- 像素纹理([1]=锚点 [2~8]=数据位) +-- 像素纹理([1]=锚点 [2~10]=数据位) local pixels = {} for i = 1, db.statusCount do local tex = f:CreateTexture(nil, "OVERLAY") @@ -98,6 +98,47 @@ local function GetPlayerCoords() return 0, 0 end +-- 专门用于计算飞行信号的函数(R 通道:0 未上马 / 0.5 可起飞需按空格 / 1.0 已在飞) +local function GetFlightSignal() + local isMounted = IsMounted() + local isFlying = IsFlying() + local canFly = IsFlyableArea() + + if not isMounted then + return 0 + end + + if isMounted and canFly and not isFlying then + if not UnitAffectingCombat("player") and IsOutdoors() then + return 0.5 + end + end + + if isMounted and isFlying then + return 1.0 + end + + return 0 +end + +-- 专门用于计算跟随信号的函数(R 通道:0 未组队 / 0.5 需补跟随 / 1.0 跟随中) +local function GetFollowSignal() + if not IsInGroup() then + return 0 + end + + local leader = "party1" + + if IsFollowing() then + return 1.0 + else + if UnitExists(leader) and UnitIsVisible(leader) then + return 0.5 + end + end + return 0 +end + f:SetScript("OnUpdate", function() -- [1] 锚点:永远纯白 (255, 255, 255) pixels[1]:SetColorTexture(1, 1, 1) @@ -150,6 +191,16 @@ f:SetScript("OnUpdate", function() math.floor((mapY * 10000) % 100) / 255, 0 ) + + -- [9] R=飞行信号 GetFlightSignal(),G=上马(1/0),B=可飞区域 IsFlyableArea() + local fSignal = GetFlightSignal() + local mountedSig = IsMounted() and 1 or 0 + local canFlySig = IsFlyableArea() and 1 or 0 + pixels[9]:SetColorTexture(fSignal, mountedSig, canFlySig, 1) + + -- [10] R=跟随信号(0 / 0.5 需补跟随 / 1.0 跟随中) + local followSig = GetFollowSignal() + pixels[10]:SetColorTexture(followSig, 0, 0, 1) end) -- 可拖动 diff --git a/__pycache__/game_state.cpython-311.pyc b/__pycache__/game_state.cpython-311.pyc index 64ffd6a0ec106e443ef7271db0f7abffff987435..1de3258699d42af7a0cb5c13641c533b053e67ed 100644 GIT binary patch delta 4341 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 Vcmr(JIdtHbF3+)=xK$1j{s*q{{EGkp diff --git a/game_state.py b/game_state.py index 5958515..d197438 100644 --- a/game_state.py +++ b/game_state.py @@ -13,11 +13,11 @@ try: except Exception: pass -# 默认布局参数 +# 默认布局参数(与 LogicBeacon:锚点 + 9 个数据块 对齐,需盖住第 9、10 格) _DEFAULTS = { "pixel_size": 17, "block_start_x": 30, - "scan_region_width": 155, + "scan_region_width": 190, "scan_region_height": 15, "offset_left": 20, "offset_top": 45, @@ -62,6 +62,51 @@ def load_layout_config(): return cfg +def _tri_state_from_r(channel_byte): + """Lua SetColorTexture 的 R 通道 0 / 0.5 / 1.0 → 与最近档位对齐(抗截图量化误差)""" + v = channel_byte / 255.0 + return min((0.0, 0.5, 1.0), key=lambda t: abs(t - v)) + + +def _tri_state_label(value, low_mid_high): + """将 0 / 0.5 / 1.0 三档转为对应中文说明(抗浮点误差)""" + v = float(value) if value is not None else 0.0 + if v < 0.25: + return low_mid_high[0] + if v < 0.75: + return low_mid_high[1] + return low_mid_high[2] + + +def format_game_state_line(state): + """单行状态文字(中文),供 CLI 与 GUI 共用。""" + death_txt = ('存活', '尸体', '灵魂')[state.get('death_state', 0)] + target_hp = state.get('target_hp') + if target_hp is not None: + hp_part = f"血:{state['hp']}% 目标血:{target_hp}% 法:{state['mp']}%" + else: + hp_part = f"血:{state['hp']}% 法:{state['mp']}%" + combat_txt = '战斗中' if state['combat'] else '未战斗' + target_txt = '有敌对目标' if state['target'] else '无有效目标' + flight_txt = _tri_state_label( + state.get('flight', 0), + ('地面', '待起飞', '飞行中'), + ) + mounted_txt = '已上马' if state.get('mounted') else '未上马' + flyable_txt = '区域可飞' if state.get('flyable') else '区域不可飞' + follow_txt = _tri_state_label( + state.get('follow', 0), + ('未跟随', '需补跟随', '跟随中'), + ) + return ( + f"{hp_part} | " + f"{combat_txt} {target_txt} | " + f"空格:{state.get('free_slots', 0)} 耐久:{state.get('durability', 0):.0%} {death_txt} | " + f"x:{state['x']} y:{state['y']} 朝向:{state['facing']:.1f}° | " + f"{flight_txt} {mounted_txt} {flyable_txt} {follow_txt}" + ) + + def save_layout_config(cfg): """保存布局配置到 game_state_config.json""" path = _get_config_path() @@ -101,8 +146,11 @@ def parse_game_state(): os.makedirs(SCREENSHOT_DIR, exist_ok=True) screenshot.save(os.path.join(SCREENSHOT_DIR, 'game_state.png')) - # 按截图像素分段:每 pixel_size 一格 → hp, mp, combat, target, logistics_death, x, y - CHANNEL_NAMES = ('hp', 'mp', 'combat', 'target', 'logistics_death', 'x', 'y') + # 每 pixel_size 一格 → … x, y, 飞行块(pixels[9]), 跟随(pixels[10]) + CHANNEL_NAMES = ( + 'hp', 'mp', 'combat', 'target', 'logistics_death', 'x', 'y', + 'flight_block', 'follow', + ) for idx, name in enumerate(CHANNEL_NAMES): left = block_start_x + idx * pixel_size box = (left, 0, left + pixel_size, pixel_size) @@ -146,6 +194,16 @@ def parse_game_state(): p7 = get_val(6) state['y'] = round((p7[0] + p7[1]/100), 2) + # 第 9 像素(Lua pixels[9]):R=飞行信号,G=上马,B=可飞区域 + p9 = get_val(7) + state['flight'] = _tri_state_from_r(p9[0]) + state['mounted'] = p9[1] > 127 + state['flyable'] = p9[2] > 127 + + # 第 10 像素(Lua pixels[10]):R=跟随信号 + p10 = get_val(8) + state['follow'] = _tri_state_from_r(p10[0]) + return state if __name__ == "__main__": @@ -154,14 +212,7 @@ if __name__ == "__main__": while True: state = parse_game_state() if state: - death_txt = ('存活', '尸体', '灵魂')[state.get('death_state', 0)] - print( - f"\r[状态] 血:{state['hp']}% 法:{state['mp']}% 目标血:{state.get('target_hp', 0)}% | " - f"战斗:{'Y' if state['combat'] else 'N'} 目标:{'Y' if state['target'] else 'N'} | " - f"空格:{state.get('free_slots', 0)} 耐久:{state.get('durability', 0):.0%} {death_txt} | " - f"x:{state['x']} y:{state['y']} 朝向:{state['facing']:.1f}°", - end="" - ) + print(f"\r[状态] {format_game_state_line(state)}", end="") time.sleep(0.5) except KeyboardInterrupt: print("\n已停止。") \ No newline at end of file diff --git a/game_state_config.json b/game_state_config.json index 266e1fd..dc832e1 100644 --- a/game_state_config.json +++ b/game_state_config.json @@ -1,7 +1,7 @@ { "pixel_size": 17, "block_start_x": 30, - "scan_region_width": 155, + "scan_region_width": 190, "scan_region_height": 15, "offset_left": 20, "offset_top": 45 diff --git a/screenshot/game_state.png b/screenshot/game_state.png index 86f19af17184d8a934f62ba6cfa0615049e667c9..bb19555904b9fd7cfc7ecc4b35d2cbb2d6328387 100644 GIT binary patch literal 88 zcmeAS@N?(olHy`uVBq!ia0vp^`+%6Ag9%7pZFnRFq~twa978JRygg{h2;?1F@YO$; ft$qQJ2?jfO6-yZyXHKsx0&zWE{an^LB{Ts5M~xKW literal 602 zcmV-g0;TCmsnTBF(fB%gjgzNaPx)_a0u!vX8^+-NI)zQwEJy2MI|@ z$v_YUqNZ=UYHuaG*xTj7K8{KbG^;EYm4pK#L;yf0$W(ivnb!MH)4Y14?@oBS$KyMn z8#Tq5%w<=dASD^H&Nl3A#)+I>%imLbJ+HGrIhICBD$=8advz5KOigvzztJu613!0V z_(Vs?@^ZwHsjxzjkzEadBIywkcd_ZFz12*8@*9tz#PC>NzAf)1Jm3k!Ne~R0X=9~` zY`SW1CDSswiRoB=jc{_1hXO@w#uP;|MTCW>q^fSZYHuZNQ|9gUNM4NP{IEHd`C@rj zD+s41av<7e&4@1gvAZ4S-K+)9?CYQzb{XcGlAh2eoMJA?kY(*^|HH5)u4dD!^+=!p z)ybY53KJxq;hq9WrUG5~njdq$2Y2D)i|+Dvd2-KZc)fF=@3vh;g&J3O^f z=YE+}EHNpK6k4O&swJ?f)oWKhO$`0i-4aPHrL9({yj|3VWaduWmPR7o1n%C5kle9$ o(^Y#b+1G<%J}P)b<^+#^8f$<07*qoM6N<$g6%#T{{R30 diff --git a/screenshot/game_state_flight_block.png b/screenshot/game_state_flight_block.png new file mode 100644 index 0000000000000000000000000000000000000000..2da3e803ca4321469776e8b923e401aeb3b9c022 GIT binary patch literal 74 zcmeAS@N?(olHy`uVBq!ia0vp^f*{Pn1SGfcUswy`c)B=-RLn_EkYHV$AaX&Nfq}V% Vfid&R%yOV4gQu&X%Q~loCII~*5HbJ& literal 0 HcmV?d00001 diff --git a/screenshot/game_state_follow.png b/screenshot/game_state_follow.png new file mode 100644 index 0000000000000000000000000000000000000000..2da3e803ca4321469776e8b923e401aeb3b9c022 GIT binary patch literal 74 zcmeAS@N?(olHy`uVBq!ia0vp^f*{Pn1SGfcUswy`c)B=-RLn_EkYHV$AaX&Nfq}V% Vfid&R%yOV4gQu&X%Q~loCII~*5HbJ& literal 0 HcmV?d00001 diff --git a/screenshot/game_state_hp.png b/screenshot/game_state_hp.png index 62b8ce47ebfc1d0d73cbd097702545e76e808daa..2da3e803ca4321469776e8b923e401aeb3b9c022 100644 GIT binary patch delta 43 xcma#>nxLX4=;`7ZQZXkvL4tL0g2)A71_tI52FA=MGs_u(z|+;wWt~$(695k~3}pZS delta 57 zcmeZ@n4n@J@9E+gQZXm_&tV6hgv5qbsY+4YOg*n8uNvR@dV!mP;bj|>)b6#{xfp=J M)78&qol`;+0C@csOaK4? diff --git a/screenshot/game_state_logistics_death.png b/screenshot/game_state_logistics_death.png index 4aa9c12f9dd7f7b8482629a066e9d4a6216f5849..2da3e803ca4321469776e8b923e401aeb3b9c022 100644 GIT binary patch delta 43 xcmWIcnxLX4=;`7ZQZXkvL4tL0g2)A71_tI52FA=MGs_u(z|+;wWt~$(695id3}65N delta 52 zcmeYYo}i*H<>}%WQZXm_$(|DqS_w*#$5+e?v~7;(-^;+DW5w_z!t$dR0}yz+`njxg HN@xNA`FavY diff --git a/screenshot/game_state_mp.png b/screenshot/game_state_mp.png index 8cb1381ff75813d644870b2ac17fe9bcdbe2bb32..2da3e803ca4321469776e8b923e401aeb3b9c022 100644 GIT binary patch delta 43 xcma#@nxLX4=;`7ZQZXkvL4tL0g2)A71_tI52FA=MGs_u(z|+;wWt~$(695m03}*lU delta 59 zcmeZ@nxJB)=;`7ZQZXkvCE>?m2d0F?goFeoS7wo(SCUtaZ+yML&A_lWlToha|ChN8 OK;Y@>=d#Wzp$PzxO%>w+ diff --git a/screenshot/game_state_target.png b/screenshot/game_state_target.png index f962da96929883b0cfa82b7198443c1cebe396e8..2da3e803ca4321469776e8b923e401aeb3b9c022 100644 GIT binary patch delta 43 xcmWIZnxLX4=;`7ZQZXkvL4tL0g2)A71_tI52FA=MGs_u(z|+;wWt~$(695j}3}XNQ delta 55 zcmeYYo1kJO>*?YcQZXkvK|!z}E+s)Jl%M(Vig|&y&2jvD85sUwXZXJ8Na|z;Anmm;e9( diff --git a/screenshot/game_state_y.png b/screenshot/game_state_y.png index 89b67d2dd3e1a7dfab7af8ee9ad094c3eefd788a..2da3e803ca4321469776e8b923e401aeb3b9c022 100644 GIT binary patch delta 43 xcmWIcnxLX4=;`7ZQZXkvL4tL0g2)A71_tI52FA=MGs_u(z|+;wWt~$(695id3}65N delta 52 zcmeYYo}i*H<>}%WQZXm_%C{s1QGgTe~ HDWM4f3z!nh diff --git a/wow_multikey_gui.py b/wow_multikey_gui.py index cfc1f04..21f24df 100644 --- a/wow_multikey_gui.py +++ b/wow_multikey_gui.py @@ -331,7 +331,7 @@ class GameLoopWorker(QThread): def run(self): try: - from game_state import parse_game_state + from game_state import parse_game_state, format_game_state_line except ImportError: self.log_signal.emit("❌ 无法导入 game_state 模块") return @@ -395,19 +395,7 @@ class GameLoopWorker(QThread): while self.running: state = parse_game_state() if state: - death_txt = ('存活', '尸体', '灵魂')[state.get('death_state', 0)] - target_hp = state.get('target_hp') - if target_hp is not None: - hp_part = f"血:{state['hp']}% 目标血:{target_hp}% 法:{state['mp']}%" - else: - hp_part = f"血:{state['hp']}% 法:{state['mp']}%" - state_str = ( - f"{hp_part} | " - f"战斗:{'Y' if state['combat'] else 'N'} 目标:{'Y' if state['target'] else 'N'} | " - f"空格:{state.get('free_slots', 0)} 耐久:{state.get('durability', 0):.0%} {death_txt} | " - f"x:{state['x']} y:{state['y']} 朝向:{state['facing']:.1f}°" - ) - self.state_signal.emit(state_str) + self.state_signal.emit(format_game_state_line(state)) if self.mode == 'patrol' and self.bot_move: self.bot_move.execute_logic(state)