add 飞行模式

This commit is contained in:
王鹏
2026-03-23 16:05:27 +08:00
parent f517c29579
commit 9b4a9d5ab8
21 changed files with 393 additions and 3 deletions

View File

@@ -292,7 +292,7 @@ class KeyWorker(QThread):
# ============ 游戏主循环(状态监控 / 巡逻打怪 / 自动打怪 / 任务跟随 / 录制) ============
class GameLoopWorker(QThread):
"""游戏状态主循环:支持状态监控、巡逻打怪、自动打怪、任务跟随、巡逻点录制"""
"""游戏状态主循环:支持状态监控、巡逻打怪、自动打怪、任务跟随、飞行模式、巡逻点录制"""
state_signal = pyqtSignal(str)
log_signal = pyqtSignal(str)
@@ -308,13 +308,19 @@ class GameLoopWorker(QThread):
quest_follow_follow_key=None,
quest_follow_interact_key=None,
quest_follow_interval_sec=None,
flight_json_path=None,
flight_takeoff_key=None,
flight_takeoff_hold_sec=None,
flight_land_key=None,
flight_land_hold_sec=None,
):
super().__init__()
self.mode = mode # 'monitor' | 'patrol' | 'combat' | 'quest_follow' | 'record'
self.mode = mode # 'monitor' | 'patrol' | 'combat' | 'quest_follow' | 'flight' | 'record'
self.running = True
self.bot_move = None
self.bot_combat = None
self.quest_follow_bot = None
self.flight_bot = None
self.recorder = None
self.waypoints_path = waypoints_path
self.vendor_path = vendor_path
@@ -328,6 +334,11 @@ class GameLoopWorker(QThread):
self.quest_follow_interval_sec = float(quest_follow_interval_sec)
except (TypeError, ValueError):
self.quest_follow_interval_sec = 3.0
self.flight_json_path = flight_json_path
self.flight_takeoff_key = flight_takeoff_key
self.flight_takeoff_hold_sec = flight_takeoff_hold_sec
self.flight_land_key = flight_land_key
self.flight_land_hold_sec = flight_land_hold_sec
def run(self):
try:
@@ -373,6 +384,24 @@ class GameLoopWorker(QThread):
self.log_signal.emit(f"❌ 任务跟随依赖加载失败: {e}")
return
if self.mode == 'flight':
if not self.flight_json_path:
self.log_signal.emit("❌ 飞行模式:未选择航线 JSON")
return
try:
from flight_mode import FlightModeBot
self.flight_bot = FlightModeBot(
json_path=self.flight_json_path,
log_callback=lambda m: self.log_signal.emit(m),
takeoff_key=self.flight_takeoff_key,
takeoff_hold_sec=self.flight_takeoff_hold_sec,
land_key=self.flight_land_key,
land_hold_sec=self.flight_land_hold_sec,
)
except ImportError as e:
self.log_signal.emit(f"❌ 飞行模式依赖加载失败: {e}")
return
if self.mode == 'record':
try:
from recorder import WaypointRecorder
@@ -403,6 +432,8 @@ class GameLoopWorker(QThread):
self.bot_combat.execute_logic(state)
elif self.mode == 'record' and self.recorder:
self.recorder.record(state)
elif self.mode == 'flight' and self.flight_bot:
self.flight_bot.execute_logic(state)
if self.mode == 'quest_follow' and self.quest_follow_bot:
self.quest_follow_bot.execute_logic(state)
time.sleep(0.1)
@@ -491,6 +522,7 @@ class WoWMultiKeyGUI(QMainWindow):
('patrol', '巡逻打怪'),
('combat', '自动打怪'),
('quest_follow', '任务跟随'),
('flight', '飞行模式'),
]:
btn = QPushButton(name)
btn.setCheckable(True)
@@ -553,6 +585,53 @@ class WoWMultiKeyGUI(QMainWindow):
self.quest_follow_group.setVisible(False)
game_layout.addWidget(self.quest_follow_group)
ff_cfg = ((self.config or {}).get('bot') or {}).get('flight') or {}
self.flight_group = QGroupBox("飞行模式配置")
flight_layout = QFormLayout(self.flight_group)
self.flight_json_combo = QComboBox()
self.flight_json_combo.setMinimumWidth(200)
self._refresh_flight_json_combo()
flight_refresh_btn = QPushButton("🔄 刷新列表")
flight_refresh_btn.clicked.connect(self._refresh_flight_json_combo)
flight_layout.addRow("航线 JSON取最后一点为目的地:", self.flight_json_combo)
self.flight_takeoff_key_edit = QLineEdit()
self.flight_takeoff_key_edit.setPlaceholderText("如 space 或 空格")
self.flight_takeoff_key_edit.setMaxLength(16)
self.flight_takeoff_key_edit.setText(str(ff_cfg.get('takeoff_key', 'space')).strip() or 'space')
self.flight_takeoff_hold_spin = QDoubleSpinBox()
self.flight_takeoff_hold_spin.setRange(0.1, 120.0)
self.flight_takeoff_hold_spin.setSingleStep(0.1)
try:
self.flight_takeoff_hold_spin.setValue(float(ff_cfg.get('takeoff_hold_sec', 2.0)))
except (TypeError, ValueError):
self.flight_takeoff_hold_spin.setValue(2.0)
self.flight_takeoff_hold_spin.setSuffix("")
self.flight_land_key_edit = QLineEdit()
self.flight_land_key_edit.setPlaceholderText("如 p")
self.flight_land_key_edit.setMaxLength(16)
self.flight_land_key_edit.setText(str(ff_cfg.get('land_key', 'p')).strip() or 'p')
self.flight_land_hold_spin = QDoubleSpinBox()
self.flight_land_hold_spin.setRange(0.1, 120.0)
self.flight_land_hold_spin.setSingleStep(0.1)
try:
self.flight_land_hold_spin.setValue(float(ff_cfg.get('land_hold_sec', 2.0)))
except (TypeError, ValueError):
self.flight_land_hold_spin.setValue(2.0)
self.flight_land_hold_spin.setSuffix("")
flight_layout.addRow("起飞按键:", self.flight_takeoff_key_edit)
flight_layout.addRow("起飞按住时长:", self.flight_takeoff_hold_spin)
flight_layout.addRow("降落按键:", self.flight_land_key_edit)
flight_layout.addRow("降落按住时长:", self.flight_land_hold_spin)
flight_layout.addRow("", flight_refresh_btn)
self.flight_group.setVisible(False)
game_layout.addWidget(self.flight_group)
self.state_label = QLabel("状态: ---")
self.state_label.setStyleSheet("font-family: monospace; padding: 6px; background: #1e1e1e; color: #d4d4d4;")
self.state_label.setMinimumHeight(36)
@@ -971,6 +1050,7 @@ class WoWMultiKeyGUI(QMainWindow):
"""切换 Tab 时加载参数或刷新下拉列表"""
if index == 1: # 状态/巡逻/打怪
self._refresh_recorder_combos()
self._refresh_flight_json_combo()
elif index == 3: # 巡逻点预览
self._refresh_preview_waypoints()
elif index == 4: # 攻击循环
@@ -1029,6 +1109,18 @@ class WoWMultiKeyGUI(QMainWindow):
elif combo.count() > 1:
combo.setCurrentIndex(1)
def _refresh_flight_json_combo(self):
"""刷新飞行模式航线 JSON 下拉列表"""
items = list_recorder_json()
self.flight_json_combo.blockSignals(True)
self.flight_json_combo.clear()
self.flight_json_combo.addItem("-- 请选择 --", "")
for name, path in items:
self.flight_json_combo.addItem(name, path)
self.flight_json_combo.blockSignals(False)
if self.flight_json_combo.count() > 1:
self.flight_json_combo.setCurrentIndex(1)
def set_game_mode(self, mode):
if self.game_worker and self.game_worker.isRunning():
self.log("请先停止当前模式再切换")
@@ -1045,6 +1137,9 @@ class WoWMultiKeyGUI(QMainWindow):
self.patrol_group.setVisible(mode == 'patrol')
self.combat_group.setVisible(mode == 'combat')
self.quest_follow_group.setVisible(mode == 'quest_follow')
self.flight_group.setVisible(mode == 'flight')
if mode == 'flight':
self._refresh_flight_json_combo()
def load_config(self):
if os.path.exists(self.config_path):
@@ -1124,10 +1219,11 @@ 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
flight_json_path = None
if mode == 'patrol':
wp = self.waypoints_combo.currentData() or ""
vp = self.vendor_combo.currentData() or ""
@@ -1163,6 +1259,25 @@ class WoWMultiKeyGUI(QMainWindow):
}
self._save_main_config()
if mode == 'flight':
fp = self.flight_json_combo.currentData() or ""
if not fp:
QMessageBox.warning(self, "提示", "飞行模式需选择航线 JSON 文件")
return
if not os.path.exists(fp):
QMessageBox.warning(self, "提示", f"航线文件不存在: {fp}")
return
flight_json_path = fp
self.config = self.config or {}
self.config.setdefault('bot', {})
self.config['bot']['flight'] = {
'takeoff_key': self.flight_takeoff_key_edit.text().strip() or 'space',
'takeoff_hold_sec': float(self.flight_takeoff_hold_spin.value()),
'land_key': self.flight_land_key_edit.text().strip() or 'p',
'land_hold_sec': float(self.flight_land_hold_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))
@@ -1176,6 +1291,11 @@ class WoWMultiKeyGUI(QMainWindow):
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(),
flight_json_path=flight_json_path,
flight_takeoff_key=self.flight_takeoff_key_edit.text(),
flight_takeoff_hold_sec=self.flight_takeoff_hold_spin.value(),
flight_land_key=self.flight_land_key_edit.text(),
flight_land_hold_sec=self.flight_land_hold_spin.value(),
)
self.game_worker.state_signal.connect(self.state_label.setText)
self.game_worker.log_signal.connect(self.log)
@@ -1188,6 +1308,7 @@ class WoWMultiKeyGUI(QMainWindow):
'patrol': '巡逻打怪',
'combat': '自动打怪',
'quest_follow': '任务跟随',
'flight': '飞行模式',
}
self.status_bar.showMessage(f"🟢 {mode_names[mode]} 运行中")
self.log(f"🎮 {mode_names[mode]} 已启动")