J.J. Huang   2026-04-20   Python OpenCV 08.專案實作篇   瀏覽次數:次  

Python | OpenCV 專案:天堂私服遊戲輔助(二)自動補藥

📑 目錄
  1. ⚠️ 免責聲明
  2. 📚 前言
  3. 🎯 本篇目標
  4. 🗂️ 本篇新增檔案
  5. 💻 自動補藥模組:auto_potion.py
  6. 💻 主程式:main.py(第二篇版本)
  7. ⚠️ 注意事項
  8. 🎯 結語

⚠️ 免責聲明

本文章內容僅供學術研究與電腦視覺技術學習之用途,所有程式碼與技術說明均以教育目的為出發點。

  • 本文作者不提供任何形式的輔助程式販售、散佈或商業服務
  • 本文所有範例程式僅限在自行架設的私有伺服器環境中測試,不得用於任何正式營運的線上遊戲伺服器。
  • 使用遊戲輔助程式可能違反個別遊戲的使用者條款,並導致帳號封鎖、法律責任等後果,讀者須自行承擔一切相關風險與責任
  • 本文技術內容若被用於任何違法或損害他人利益之行為,作者概不負責
  • 私有伺服器的架設與使用涉及遊戲著作權相關法律問題,讀者應自行評估所在地區的法規,並確認於合法範圍內使用。

📚 前言

在上一篇 (一)主程式 GUI 框架與 HP/MP 血量監控 中,我們建立了 tkinter 骨架,可以即時顯示 HP/MP 比例。

本篇加入 自動補藥 功能:當 HP 或 MP 低於設定閾值時,自動模擬按下補藥熱鍵,並新增設定面板讓使用者在 UI 上調整參數。​‌‌‌​​​​​‌‌‌‌​​‌​‌‌‌​‌​​​‌‌​‌​​​​‌‌​‌‌‌‌​‌‌​‌‌‌​​​‌​‌‌​‌​‌‌​‌‌‌‌​‌‌‌​​​​​‌‌​​‌​‌​‌‌​‌‌‌​​‌‌​​​‌‌​‌‌‌​‌‌​​​‌​‌‌​‌​​‌‌​​‌​​​‌‌​​​​​​‌‌​​‌​​​‌‌​‌‌​​​‌‌​​​​​​‌‌​‌​​​​‌‌​​‌​​​‌‌​​​​​​‌​‌‌​‌​‌‌‌​​​​​‌‌‌‌​​‌​‌‌‌​‌​​​‌‌​‌​​​​‌‌​‌‌‌‌​‌‌​‌‌‌​​​‌​‌‌​‌​‌‌​‌‌‌‌​‌‌‌​​​​​‌‌​​‌​‌​‌‌​‌‌‌​​‌‌​​​‌‌​‌‌‌​‌‌​​​‌​‌‌​‌​‌‌‌​​​​​‌‌‌​​‌​​‌‌​‌‌‌‌​‌‌​‌​‌​​‌‌​​‌​‌​‌‌​​​‌‌​‌‌‌​‌​​​​‌​‌‌​‌​‌‌​‌‌​​​‌‌​‌​​‌​‌‌​‌‌‌​​‌‌​​‌​‌​‌‌​​​​‌​‌‌​​‌‌‌​‌‌​​‌​‌​​‌​‌‌​‌​‌‌​​​​‌​‌‌‌​‌​‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌​‌​‌‌‌​​​​​‌‌​‌‌‌‌​‌‌‌​‌​​​‌‌​‌​​‌​‌‌​‌‌‌‌​‌‌​‌‌‌​

系列總覽:

篇次 主題
主程式 GUI 框架與 HP/MP 血量監控
本篇(二) 自動補藥
YOLOv8 怪物偵測整合
四(最終篇) 目標優先序選擇

🎯 本篇目標

  • 建立 auto_potion.py,封裝補藥邏輯與冷卻時間
  • PostMessageWM_KEYDOWN / WM_KEYUP 直接送到目標視窗的 hwnd,背景也能按鍵(不搶焦點)
  • 在 UI 新增:啟用開關、HP/MP 閾值滑桿、F5~F12 熱鍵下拉選單
  • Worker Thread 1 整合補藥邏輯,main.py 整體更新

🗂️ 本篇新增檔案

1
2
3
4
5
6
lineage_assistant/
├── main.py ← 更新(加入補藥設定面板 + 傳入 AutoPotion)
├── window_capture.py ← 不變
├── hp_monitor.py ← 不變
├── auto_potion.py ← 新增(本篇重點)
└── config.json

本篇沿用第一篇已安裝的 pywin32,不需要額外套件。

Python - 圖 1 (auto potion flow)
Python - 圖 2 (auto potion architecture)​‌‌‌​​​​​‌‌‌‌​​‌​‌‌‌​‌​​​‌‌​‌​​​​‌‌​‌‌‌‌​‌‌​‌‌‌​​​‌​‌‌​‌​‌‌​‌‌‌‌​‌‌‌​​​​​‌‌​​‌​‌​‌‌​‌‌‌​​‌‌​​​‌‌​‌‌‌​‌‌​​​‌​‌‌​‌​​‌‌​​‌​​​‌‌​​​​​​‌‌​​‌​​​‌‌​‌‌​​​‌‌​​​​​​‌‌​‌​​​​‌‌​​‌​​​‌‌​​​​​​‌​‌‌​‌​‌‌‌​​​​​‌‌‌‌​​‌​‌‌‌​‌​​​‌‌​‌​​​​‌‌​‌‌‌‌​‌‌​‌‌‌​​​‌​‌‌​‌​‌‌​‌‌‌‌​‌‌‌​​​​​‌‌​​‌​‌​‌‌​‌‌‌​​‌‌​​​‌‌​‌‌‌​‌‌​​​‌​‌‌​‌​‌‌‌​​​​​‌‌‌​​‌​​‌‌​‌‌‌‌​‌‌​‌​‌​​‌‌​​‌​‌​‌‌​​​‌‌​‌‌‌​‌​​​​‌​‌‌​‌​‌‌​‌‌​​​‌‌​‌​​‌​‌‌​‌‌‌​​‌‌​​‌​‌​‌‌​​​​‌​‌‌​​‌‌‌​‌‌​​‌​‌​​‌​‌‌​‌​‌‌​​​​‌​‌‌‌​‌​‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌​‌​‌‌‌​​​​​‌‌​‌‌‌‌​‌‌‌​‌​​​‌‌​‌​​‌​‌‌​‌‌‌‌​‌‌​‌‌‌​

💻 自動補藥模組:auto_potion.py

設計重點:

  • check(hp, mp) 由 Worker Thread 1 呼叫,不能操作 tkinter 元件
  • 使用 PostMessageWM_KEYDOWN / WM_KEYUP 送到目標 hwnd,視窗可在背景;不像 pyautogui.press() 只會送到有焦點的視窗
  • 使用 log_fn callback 把訊息傳回主執行緒的 log_q
  • cooldown 防止連按,避免瞬間消耗大量藥水
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# auto_potion.py
import time
from typing import Callable, Optional

import win32api
import win32con


VK_MAP = {
"f1": win32con.VK_F1, "f2": win32con.VK_F2,
"f3": win32con.VK_F3, "f4": win32con.VK_F4,
"f5": win32con.VK_F5, "f6": win32con.VK_F6,
"f7": win32con.VK_F7, "f8": win32con.VK_F8,
"f9": win32con.VK_F9, "f10": win32con.VK_F10,
"f11": win32con.VK_F11, "f12": win32con.VK_F12,
}


def post_key(hwnd: int, key: str):
"""把 WM_KEYDOWN/UP PostMessage 到目標 hwnd,不需視窗在前景"""
vk = VK_MAP.get(key.lower())
if vk is None or not hwnd:
return
scan = win32api.MapVirtualKey(vk, 0)
lparam_down = (scan << 16) | 1
lparam_up = (scan << 16) | (1 | (1 << 30) | (1 << 31))
win32api.PostMessage(hwnd, win32con.WM_KEYDOWN, vk, lparam_down)
win32api.PostMessage(hwnd, win32con.WM_KEYUP, vk, lparam_up)


class AutoPotion:
def __init__(self,
hwnd: int,
hp_threshold: float = 0.6,
mp_threshold: float = 0.4,
hp_key: str = "f5",
mp_key: str = "f6",
cooldown: float = 1.5,
enabled: bool = True,
log_fn: Optional[Callable] = None):
self.hwnd = hwnd
self.hp_threshold = hp_threshold
self.mp_threshold = mp_threshold
self.hp_key = hp_key
self.mp_key = mp_key
self.cooldown = cooldown
self.enabled = enabled # 可由主執行緒即時切換
self._log = log_fn or (lambda msg: None)
self._last_hp_t = 0.0
self._last_mp_t = 0.0

def check(self, hp: float, mp: float):
"""根據當前 HP/MP 決定是否補藥"""
if not self.enabled:
return
now = time.time()
if hp < self.hp_threshold and (now - self._last_hp_t) >= self.cooldown:
post_key(self.hwnd, self.hp_key)
self._last_hp_t = now
self._log(
f"HP 補藥({hp*100:.0f}% < {self.hp_threshold*100:.0f}%)"
f",按 [{self.hp_key.upper()}]"
)
if mp < self.mp_threshold and (now - self._last_mp_t) >= self.cooldown:
post_key(self.hwnd, self.mp_key)
self._last_mp_t = now
self._log(
f"MP 補藥({mp*100:.0f}% < {self.mp_threshold*100:.0f}%)"
f",按 [{self.mp_key.upper()}]"
)

💻 主程式:main.py(第二篇版本)

這段內容已加密
需要 ☕ 咖啡會員 或更高等級的密碼才能閱讀
💡 年度公開密碼,到 /support 直接取得

整合自動補藥模組的完整主程式,UI 新增閾值滑桿與 F5~F12 熱鍵下拉選單,啟動時連同目標 hwnd 一起傳入 Worker Thread
圖:整合自動補藥模組的完整主程式,UI 新增閾值滑桿與 F5~F12 熱鍵下拉選單,啟動時連同目標 hwnd 一起傳入 Worker Thread

⚠️ 注意事項

  • 按鍵直接 PostMessage 到目標 hwnd:不搶焦點,你可以在別的視窗工作;按鍵只會進指定遊戲視窗。
  • DirectInput 遊戲可能不吃 PostMessage:本篇鎖定以 WM_KEYDOWN / WM_KEYUP 接收熱鍵的傳統 Win32 遊戲視窗(如天堂 L1J 系列私服);若遊戲採 DirectInput/Raw Input,要改用 SendInput 並把視窗帶到前景才能生效。
  • 冷卻時間 cooldown=1.5:防止連按,依藥水生效速度調整。
  • 面板設定皆為即時生效:checkbox、HP/MP 閾值滑桿、F5~F12 下拉選單都由 _poll 每 200ms 推進 AutoPotion,調了就馬上套用。
  • hwnd 例外,是啟動時一次讀取:切換目標視窗要先停止、重新 🎯 選取、再啟動。
  • 執行緒不會再靜默死掉monitor_loop 外層 try/except/finally 把 pywin32 例外吞進 log;_poll 偵測到執行緒掛掉會自動把 ▶ / ■ 按鈕切回「啟動」並提示看日誌。

🎯 結語

本篇的自動補藥功能是遊戲輔助的基礎,整個邏輯都在 Worker Thread 1 裡執行,與 UI 完全解耦。​‌‌‌​​​​​‌‌‌‌​​‌​‌‌‌​‌​​​‌‌​‌​​​​‌‌​‌‌‌‌​‌‌​‌‌‌​​​‌​‌‌​‌​‌‌​‌‌‌‌​‌‌‌​​​​​‌‌​​‌​‌​‌‌​‌‌‌​​‌‌​​​‌‌​‌‌‌​‌‌​​​‌​‌‌​‌​​‌‌​​‌​​​‌‌​​​​​​‌‌​​‌​​​‌‌​‌‌​​​‌‌​​​​​​‌‌​‌​​​​‌‌​​‌​​​‌‌​​​​​​‌​‌‌​‌​‌‌‌​​​​​‌‌‌‌​​‌​‌‌‌​‌​​​‌‌​‌​​​​‌‌​‌‌‌‌​‌‌​‌‌‌​​​‌​‌‌​‌​‌‌​‌‌‌‌​‌‌‌​​​​​‌‌​​‌​‌​‌‌​‌‌‌​​‌‌​​​‌‌​‌‌‌​‌‌​​​‌​‌‌​‌​‌‌‌​​​​​‌‌‌​​‌​​‌‌​‌‌‌‌​‌‌​‌​‌​​‌‌​​‌​‌​‌‌​​​‌‌​‌‌‌​‌​​​​‌​‌‌​‌​‌‌​‌‌​​​‌‌​‌​​‌​‌‌​‌‌‌​​‌‌​​‌​‌​‌‌​​​​‌​‌‌​​‌‌‌​‌‌​​‌​‌​​‌​‌‌​‌​‌‌​​​​‌​‌‌‌​‌​‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌​‌​‌‌‌​​​​​‌‌​‌‌‌‌​‌‌‌​‌​​​‌‌​‌​​‌​‌‌​‌‌‌‌​‌‌​‌‌‌​

下一篇將加入 (三)YOLOv8 怪物偵測整合,新增 Worker Thread 2 專門負責 YOLO 推論,並在 UI 中嵌入即時偵測預覽視窗。

📖 如在學習過程中遇到疑問,或是想了解更多相關主題,建議回顧一下 Python | OpenCV 系列導讀,掌握完整的章節目錄,方便快速找到你需要的內容。

註:以上參考了
pywin32 GitHub
PostMessage - Win32 API
WM_KEYDOWN - Win32 API
tkinter ttk.Scale​‌‌‌​​​​​‌‌‌‌​​‌​‌‌‌​‌​​​‌‌​‌​​​​‌‌​‌‌‌‌​‌‌​‌‌‌​​​‌​‌‌​‌​‌‌​‌‌‌‌​‌‌‌​​​​​‌‌​​‌​‌​‌‌​‌‌‌​​‌‌​​​‌‌​‌‌‌​‌‌​​​‌​‌‌​‌​​‌‌​​‌​​​‌‌​​​​​​‌‌​​‌​​​‌‌​‌‌​​​‌‌​​​​​​‌‌​‌​​​​‌‌​​‌​​​‌‌​​​​​​‌​‌‌​‌​‌‌‌​​​​​‌‌‌‌​​‌​‌‌‌​‌​​​‌‌​‌​​​​‌‌​‌‌‌‌​‌‌​‌‌‌​​​‌​‌‌​‌​‌‌​‌‌‌‌​‌‌‌​​​​​‌‌​​‌​‌​‌‌​‌‌‌​​‌‌​​​‌‌​‌‌‌​‌‌​​​‌​‌‌​‌​‌‌‌​​​​​‌‌‌​​‌​​‌‌​‌‌‌‌​‌‌​‌​‌​​‌‌​​‌​‌​‌‌​​​‌‌​‌‌‌​‌​​​​‌​‌‌​‌​‌‌​‌‌​​​‌‌​‌​​‌​‌‌​‌‌‌​​‌‌​​‌​‌​‌‌​​​​‌​‌‌​​‌‌‌​‌‌​​‌​‌​​‌​‌‌​‌​‌‌​​​​‌​‌‌‌​‌​‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌​‌​‌‌‌​​​​​‌‌​‌‌‌‌​‌‌‌​‌​​​‌‌​‌​​‌​‌‌​‌‌‌‌​‌‌​‌‌‌​