add 任务跟随模式
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,6 +1,7 @@
|
||||
# 忽略打包后的静态资源(你的核心需求)
|
||||
dist/
|
||||
build/
|
||||
dist.zip
|
||||
|
||||
# 忽略依赖库
|
||||
node_modules/
|
||||
|
||||
38
quest_follow.py
Normal file
38
quest_follow.py
Normal file
@@ -0,0 +1,38 @@
|
||||
"""
|
||||
任务跟随:按固定间隔向游戏发送「跟随」与「交互」按键(pydirectinput,与 auto_bot 一致)。
|
||||
"""
|
||||
|
||||
import time
|
||||
|
||||
import pydirectinput
|
||||
|
||||
|
||||
class QuestFollowBot:
|
||||
"""每隔 interval_sec 秒依次按下跟随键、交互键;不读取游戏状态。"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
follow_key="f",
|
||||
interact_key="4",
|
||||
interval_sec=3.0,
|
||||
log_callback=None,
|
||||
):
|
||||
self.follow_key = (follow_key or "f").strip().lower() or "f"
|
||||
self.interact_key = (interact_key or "4").strip().lower() or "4"
|
||||
self.interval_sec = max(0.5, float(interval_sec))
|
||||
self._last_cycle = 0.0
|
||||
self._log = log_callback or (lambda _m: None)
|
||||
|
||||
def execute_logic(self, state):
|
||||
"""state 可为 None;仅用于与时间间隔配合的定时按键。"""
|
||||
now = time.time()
|
||||
if now - self._last_cycle < self.interval_sec:
|
||||
return
|
||||
self._last_cycle = now
|
||||
try:
|
||||
pydirectinput.press(self.follow_key)
|
||||
time.sleep(0.08)
|
||||
pydirectinput.press(self.interact_key)
|
||||
self._log(f"➡️ 任务跟随: {self.follow_key} → {self.interact_key}")
|
||||
except Exception as e:
|
||||
self._log(f"❌ 任务跟随按键失败: {e}")
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
WoW 多功能控制器 GUI
|
||||
集成:状态监控、巡逻打怪、自动打怪、巡逻点录制、多键控制
|
||||
集成:状态监控、巡逻打怪、自动打怪、任务跟随、巡逻点录制、多键控制
|
||||
"""
|
||||
|
||||
import json
|
||||
@@ -289,10 +289,10 @@ class KeyWorker(QThread):
|
||||
self.log_signal.emit(f"❌ 按键 {self.key_name} 失败: {e}")
|
||||
|
||||
|
||||
# ============ 游戏主循环(状态监控 / 巡逻打怪 / 自动打怪 / 录制) ============
|
||||
# ============ 游戏主循环(状态监控 / 巡逻打怪 / 自动打怪 / 任务跟随 / 录制) ============
|
||||
|
||||
class GameLoopWorker(QThread):
|
||||
"""游戏状态主循环:支持状态监控、巡逻打怪、自动打怪、巡逻点录制"""
|
||||
"""游戏状态主循环:支持状态监控、巡逻打怪、自动打怪、任务跟随、巡逻点录制"""
|
||||
state_signal = pyqtSignal(str)
|
||||
log_signal = pyqtSignal(str)
|
||||
|
||||
@@ -305,12 +305,16 @@ class GameLoopWorker(QThread):
|
||||
record_min_distance=None,
|
||||
attack_loop_path=None,
|
||||
skinning_wait_sec=None,
|
||||
quest_follow_follow_key=None,
|
||||
quest_follow_interact_key=None,
|
||||
quest_follow_interval_sec=None,
|
||||
):
|
||||
super().__init__()
|
||||
self.mode = mode # 'monitor' | 'patrol' | 'combat' | 'record'
|
||||
self.mode = mode # 'monitor' | 'patrol' | 'combat' | 'quest_follow' | 'record'
|
||||
self.running = True
|
||||
self.bot_move = None
|
||||
self.bot_combat = None
|
||||
self.quest_follow_bot = None
|
||||
self.recorder = None
|
||||
self.waypoints_path = waypoints_path
|
||||
self.vendor_path = vendor_path
|
||||
@@ -318,6 +322,12 @@ class GameLoopWorker(QThread):
|
||||
self.record_min_distance = record_min_distance
|
||||
self.attack_loop_path = attack_loop_path or None
|
||||
self.skinning_wait_sec = skinning_wait_sec
|
||||
self.quest_follow_follow_key = (quest_follow_follow_key or "f").strip().lower() or "f"
|
||||
self.quest_follow_interact_key = (quest_follow_interact_key or "4").strip().lower() or "4"
|
||||
try:
|
||||
self.quest_follow_interval_sec = float(quest_follow_interval_sec)
|
||||
except (TypeError, ValueError):
|
||||
self.quest_follow_interval_sec = 3.0
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
@@ -350,6 +360,19 @@ class GameLoopWorker(QThread):
|
||||
self.log_signal.emit(f"❌ 自动打怪依赖加载失败: {e}")
|
||||
return
|
||||
|
||||
if self.mode == 'quest_follow':
|
||||
try:
|
||||
from quest_follow import QuestFollowBot
|
||||
self.quest_follow_bot = QuestFollowBot(
|
||||
follow_key=self.quest_follow_follow_key,
|
||||
interact_key=self.quest_follow_interact_key,
|
||||
interval_sec=self.quest_follow_interval_sec,
|
||||
log_callback=lambda m: self.log_signal.emit(m),
|
||||
)
|
||||
except ImportError as e:
|
||||
self.log_signal.emit(f"❌ 任务跟随依赖加载失败: {e}")
|
||||
return
|
||||
|
||||
if self.mode == 'record':
|
||||
try:
|
||||
from recorder import WaypointRecorder
|
||||
@@ -392,6 +415,8 @@ class GameLoopWorker(QThread):
|
||||
self.bot_combat.execute_logic(state)
|
||||
elif self.mode == 'record' and self.recorder:
|
||||
self.recorder.record(state)
|
||||
if self.mode == 'quest_follow' and self.quest_follow_bot:
|
||||
self.quest_follow_bot.execute_logic(state)
|
||||
time.sleep(0.1)
|
||||
|
||||
def save_recorder(self):
|
||||
@@ -477,6 +502,7 @@ class WoWMultiKeyGUI(QMainWindow):
|
||||
('monitor', '状态监控'),
|
||||
('patrol', '巡逻打怪'),
|
||||
('combat', '自动打怪'),
|
||||
('quest_follow', '任务跟随'),
|
||||
]:
|
||||
btn = QPushButton(name)
|
||||
btn.setCheckable(True)
|
||||
@@ -514,6 +540,31 @@ class WoWMultiKeyGUI(QMainWindow):
|
||||
self.combat_group.setVisible(False)
|
||||
game_layout.addWidget(self.combat_group)
|
||||
|
||||
qf_cfg = ((self.config or {}).get('bot') or {}).get('quest_follow') or {}
|
||||
self.quest_follow_group = QGroupBox("任务跟随配置")
|
||||
qf_layout = QFormLayout(self.quest_follow_group)
|
||||
self.quest_follow_follow_edit = QLineEdit()
|
||||
self.quest_follow_follow_edit.setPlaceholderText("如 f(跟随队友)")
|
||||
self.quest_follow_follow_edit.setMaxLength(8)
|
||||
self.quest_follow_follow_edit.setText(str(qf_cfg.get('follow_key', 'f')).strip() or 'f')
|
||||
self.quest_follow_interact_edit = QLineEdit()
|
||||
self.quest_follow_interact_edit.setPlaceholderText("如 4(与互动键一致)")
|
||||
self.quest_follow_interact_edit.setMaxLength(8)
|
||||
self.quest_follow_interact_edit.setText(str(qf_cfg.get('interact_key', '4')).strip() or '4')
|
||||
self.quest_follow_interval_spin = QDoubleSpinBox()
|
||||
self.quest_follow_interval_spin.setRange(0.5, 120.0)
|
||||
self.quest_follow_interval_spin.setSingleStep(0.5)
|
||||
try:
|
||||
self.quest_follow_interval_spin.setValue(float(qf_cfg.get('interval_sec', 3.0)))
|
||||
except (TypeError, ValueError):
|
||||
self.quest_follow_interval_spin.setValue(3.0)
|
||||
self.quest_follow_interval_spin.setSuffix(" 秒")
|
||||
qf_layout.addRow("跟随键:", self.quest_follow_follow_edit)
|
||||
qf_layout.addRow("交互键:", self.quest_follow_interact_edit)
|
||||
qf_layout.addRow("按键间隔:", self.quest_follow_interval_spin)
|
||||
self.quest_follow_group.setVisible(False)
|
||||
game_layout.addWidget(self.quest_follow_group)
|
||||
|
||||
self.state_label = QLabel("状态: ---")
|
||||
self.state_label.setStyleSheet("font-family: monospace; padding: 6px; background: #1e1e1e; color: #d4d4d4;")
|
||||
self.state_label.setMinimumHeight(36)
|
||||
@@ -981,6 +1032,7 @@ class WoWMultiKeyGUI(QMainWindow):
|
||||
self._refresh_attack_loop_combo()
|
||||
self.patrol_group.setVisible(mode == 'patrol')
|
||||
self.combat_group.setVisible(mode == 'combat')
|
||||
self.quest_follow_group.setVisible(mode == 'quest_follow')
|
||||
|
||||
def load_config(self):
|
||||
if os.path.exists(self.config_path):
|
||||
@@ -1060,7 +1112,7 @@ class WoWMultiKeyGUI(QMainWindow):
|
||||
def start_game_loop(self):
|
||||
mode = self._current_game_mode
|
||||
if mode is None:
|
||||
QMessageBox.warning(self, "提示", "请先选择模式(状态监控 / 巡逻打怪 / 自动打怪)")
|
||||
QMessageBox.warning(self, "提示", "请先选择模式(状态监控 / 巡逻打怪 / 自动打怪 / 任务跟随)")
|
||||
return
|
||||
waypoints_path = None
|
||||
vendor_path = None
|
||||
@@ -1089,6 +1141,16 @@ class WoWMultiKeyGUI(QMainWindow):
|
||||
if attack_loop_path and not os.path.exists(attack_loop_path):
|
||||
attack_loop_path = None
|
||||
|
||||
if mode == 'quest_follow':
|
||||
self.config = self.config or {}
|
||||
self.config.setdefault('bot', {})
|
||||
self.config['bot']['quest_follow'] = {
|
||||
'follow_key': self.quest_follow_follow_edit.text().strip() or 'f',
|
||||
'interact_key': self.quest_follow_interact_edit.text().strip() or '4',
|
||||
'interval_sec': float(self.quest_follow_interval_spin.value()),
|
||||
}
|
||||
self._save_main_config()
|
||||
|
||||
skinning_wait_sec = None
|
||||
try:
|
||||
skinning_wait_sec = float(((self.config or {}).get('bot') or {}).get('skinning_wait_sec', 1.5))
|
||||
@@ -1099,6 +1161,9 @@ class WoWMultiKeyGUI(QMainWindow):
|
||||
mode, waypoints_path=waypoints_path, vendor_path=vendor_path,
|
||||
attack_loop_path=attack_loop_path,
|
||||
skinning_wait_sec=skinning_wait_sec,
|
||||
quest_follow_follow_key=self.quest_follow_follow_edit.text(),
|
||||
quest_follow_interact_key=self.quest_follow_interact_edit.text(),
|
||||
quest_follow_interval_sec=self.quest_follow_interval_spin.value(),
|
||||
)
|
||||
self.game_worker.state_signal.connect(self.state_label.setText)
|
||||
self.game_worker.log_signal.connect(self.log)
|
||||
@@ -1106,7 +1171,12 @@ class WoWMultiKeyGUI(QMainWindow):
|
||||
self.game_worker.start()
|
||||
self.game_start_btn.setEnabled(False)
|
||||
self.game_stop_btn.setEnabled(True)
|
||||
mode_names = {'monitor': '状态监控', 'patrol': '巡逻打怪', 'combat': '自动打怪'}
|
||||
mode_names = {
|
||||
'monitor': '状态监控',
|
||||
'patrol': '巡逻打怪',
|
||||
'combat': '自动打怪',
|
||||
'quest_follow': '任务跟随',
|
||||
}
|
||||
self.status_bar.showMessage(f"🟢 {mode_names[mode]} 运行中")
|
||||
self.log(f"🎮 {mode_names[mode]} 已启动")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user