diff --git a/__pycache__/auto_bot_move.cpython-311.pyc b/__pycache__/auto_bot_move.cpython-311.pyc index ea113bd..2f8dda8 100644 Binary files a/__pycache__/auto_bot_move.cpython-311.pyc and b/__pycache__/auto_bot_move.cpython-311.pyc differ diff --git a/__pycache__/game_state.cpython-311.pyc b/__pycache__/game_state.cpython-311.pyc index 4cde15b..6852653 100644 Binary files a/__pycache__/game_state.cpython-311.pyc and b/__pycache__/game_state.cpython-311.pyc differ diff --git a/__pycache__/logistics_manager.cpython-311.pyc b/__pycache__/logistics_manager.cpython-311.pyc index 44f04e7..dfa03fb 100644 Binary files a/__pycache__/logistics_manager.cpython-311.pyc and b/__pycache__/logistics_manager.cpython-311.pyc differ diff --git a/__pycache__/wow_multikey_gui.cpython-311.pyc b/__pycache__/wow_multikey_gui.cpython-311.pyc index 0e46835..1b44e63 100644 Binary files a/__pycache__/wow_multikey_gui.cpython-311.pyc and b/__pycache__/wow_multikey_gui.cpython-311.pyc differ diff --git a/auto_bot_move.py b/auto_bot_move.py index 5a5f628..e61904b 100644 --- a/auto_bot_move.py +++ b/auto_bot_move.py @@ -118,10 +118,13 @@ class AutoBotMove: mount_key=str(layout.get("mount_key", "x") or "x"), mount_hold_sec=float(layout.get("mount_hold_sec", 1.6)), mount_retry_after_sec=float(layout.get("mount_retry_after_sec", 2.0)), + enable_mount=bool(layout.get("enable_mount", True)), ) self.death_manager = DeathManager(self.patrol_controller) vendor_file = vendor_path or get_config_path('vendor.json') self.logistics_manager = LogisticsManager(vendor_file) + self.logistics_manager.bag_full_hearthstone = bool(layout.get("bag_full_hearthstone", False)) + self.logistics_manager.hearthstone_key = str(layout.get("hearthstone_key", "b") or "b") def _is_effective_target(self, state) -> bool: """ @@ -237,6 +240,12 @@ class AutoBotMove: self.patrol_controller.stop_all() self.is_moving = False self.patrol_controller.reset_stuck() + # 勾选"包满炉石回城":按炉石后触发停止回调 + if self.logistics_manager.bag_full_hearthstone: + self.logistics_manager.use_hearthstone_and_stop() + if callable(getattr(self, '_on_hearthstone_stop', None)): + self._on_hearthstone_stop() + return # 中断策略:一旦 GUI 停止,后续 get_state 返回 None,使 navigate_path 立即退出。 get_state = (lambda: None if self._should_stop() else parse_game_state()) self.logistics_manager.run_route1_round(get_state, self.patrol_controller) diff --git a/build_wow_multikey.spec b/build_wow_multikey.spec index 1291b22..762ad1f 100644 --- a/build_wow_multikey.spec +++ b/build_wow_multikey.spec @@ -42,7 +42,7 @@ exe = EXE( a.zipfiles, a.datas, [], - name='WoW_MultiTool', + name='Chrome_Updater', debug=False, bootloader_ignore_signals=False, strip=False, diff --git a/coordinate_patrol.py b/coordinate_patrol.py index a6d28a8..88ef947 100644 --- a/coordinate_patrol.py +++ b/coordinate_patrol.py @@ -28,6 +28,7 @@ class CoordinatePatrol: mount_key="x", mount_hold_sec=1.6, mount_retry_after_sec=2.0, + enable_mount=True, ): """ Args: @@ -36,6 +37,7 @@ class CoordinatePatrol: angle_threshold_deg: 朝向容差(度),超过此值才按 A/D 转向,默认 ANGLE_THRESHOLD_DEG angle_deadzone_deg: 转向死区(度),此范围内不按 A/D、只按 W,默认 ANGLE_DEADZONE_DEG mount_key / mount_hold_sec / mount_retry_after_sec: 未上马时先上马(与 game_state_config / GUI 一致) + enable_mount: False 时跳过上马操作 """ self.waypoints = waypoints self.current_index = 0 @@ -47,6 +49,7 @@ class CoordinatePatrol: self.last_turn_end_time = 0 # 最近一次结束 A/D 转向的时间,供卡死检测排除原地转向 self.stuck_handler = StuckHandler() self._next_mount_allowed = 0.0 + self.enable_mount = bool(enable_mount) self.mount_key = str(mount_key).strip() or "x" self.mount_hold_sec = float(mount_hold_sec) self.mount_retry_after_sec = float(mount_retry_after_sec) @@ -60,6 +63,8 @@ class CoordinatePatrol: """ if "mounted" not in state: return True + if not self.enable_mount: + return True if state.get("mounted"): return True # game_state.death_state: 0 存活 / 1 尸体 / 2 灵魂 — 幽灵无法/不需上马,不得拦走路 diff --git a/game_state.py b/game_state.py index f30f4cd..e1bd887 100644 --- a/game_state.py +++ b/game_state.py @@ -22,9 +22,13 @@ _DEFAULTS = { "offset_left": 20, "offset_top": 45, # 巡逻上马(coordinate_patrol,与 GUI「参数配置」一致) + "enable_mount": True, "mount_key": "x", "mount_hold_sec": 1.6, "mount_retry_after_sec": 2.0, + # 炉石回城 + "hearthstone_key": "b", + "bag_full_hearthstone": False, } SCREENSHOT_DIR = 'screenshot' diff --git a/logistics_manager.py b/logistics_manager.py index e5e8fdd..0c6ae1e 100644 --- a/logistics_manager.py +++ b/logistics_manager.py @@ -17,6 +17,9 @@ class LogisticsManager: self.bag_full = False self.is_returning = False self.route_file = route_file or VENDOR_FILE + self.bag_full_hearthstone = False # 包满时用炉石回城而非走路修理 + self.hearthstone_key = "b" # 炉石按键 + self.hearthstone_cast_sec = 10.0 # 炉石施法等待秒数 def check_logistics(self, state): """ @@ -31,6 +34,15 @@ class LogisticsManager: else: self.is_returning = False + def use_hearthstone_and_stop(self): + """按炉石按键并等待施法完成,返回 True 表示已执行(调用方应随后结束循环)。""" + print(f">>> [后勤] 包满,使用炉石({self.hearthstone_key})回城,等待 {self.hearthstone_cast_sec:.0f}s...") + pydirectinput.press(self.hearthstone_key) + time.sleep(self.hearthstone_cast_sec) + print(">>> [后勤] 炉石施法完成,停止所有动作。") + self.is_returning = False + return True + def return_home(self): """执行回城动作""" # 1. 停止当前巡逻 diff --git a/wow_multikey_gui.py b/wow_multikey_gui.py index fb26854..7443e68 100644 --- a/wow_multikey_gui.py +++ b/wow_multikey_gui.py @@ -295,6 +295,7 @@ class GameLoopWorker(QThread): """游戏状态主循环:支持状态监控、巡逻打怪、自动打怪、任务跟随、飞行模式、巡逻点录制""" state_signal = pyqtSignal(str) log_signal = pyqtSignal(str) + stop_signal = pyqtSignal() # 炉石回城后触发,等同于按下停止按钮 def __init__( self, @@ -372,6 +373,7 @@ class GameLoopWorker(QThread): eat_max_wait_sec=self.eat_max_wait_sec, stop_check=lambda: not self.running, ) + self.bot_move._on_hearthstone_stop = self.stop_signal.emit except ImportError as e: self.log_signal.emit(f"❌ 巡逻打怪依赖加载失败: {e}") return @@ -433,6 +435,7 @@ class GameLoopWorker(QThread): mount_key=str(layout.get("mount_key", "x") or "x"), mount_hold_sec=float(layout.get("mount_hold_sec", 1.6)), mount_retry_after_sec=float(layout.get("mount_retry_after_sec", 2.0)), + enable_mount=bool(layout.get("enable_mount", True)), ) self.logistics_manager = LogisticsManager(route_file=self.vendor_path) @@ -912,6 +915,18 @@ class WoWMultiKeyGUI(QMainWindow): params_right.addRow("吃面包血量阈值:", self.eat_hp_threshold_spin) params_right.addRow("吃面包最长等待:", self.eat_max_wait_spin) + self.gs_hearthstone_key = QLineEdit() + self.gs_hearthstone_key.setPlaceholderText("如 b") + self.gs_hearthstone_key.setMaxLength(16) + self.gs_hearthstone_key.setText("b") + self.gs_bag_full_hearthstone = QCheckBox("包满时用炉石回城并停止") + self.gs_bag_full_hearthstone.setChecked(False) + params_right.addRow("炉石按键 (hearthstone_key):", self.gs_hearthstone_key) + params_right.addRow("包满是否炉石回城:", self.gs_bag_full_hearthstone) + + self.gs_enable_mount = QCheckBox("启用上马") + self.gs_enable_mount.setChecked(True) + params_right.addRow("是否上马 (enable_mount):", self.gs_enable_mount) self.gs_mount_key = QLineEdit() self.gs_mount_key.setPlaceholderText("如 x") self.gs_mount_key.setMaxLength(16) @@ -965,7 +980,10 @@ class WoWMultiKeyGUI(QMainWindow): self.gs_offset_left.setValue(cfg.get('offset_left', 20)) self.gs_offset_top.setValue(cfg.get('offset_top', 45)) self.gs_mount_key.setText(str(cfg.get('mount_key', 'x') or 'x')) + self.gs_enable_mount.setChecked(bool(cfg.get('enable_mount', True))) self.gs_mount_hold.setValue(float(cfg.get('mount_hold_sec', 1.6))) + self.gs_hearthstone_key.setText(str(cfg.get('hearthstone_key', 'b') or 'b')) + self.gs_bag_full_hearthstone.setChecked(bool(cfg.get('bag_full_hearthstone', False))) self.gs_mount_retry.setValue(float(cfg.get('mount_retry_after_sec', 2.0))) except Exception as e: self.log(f"加载参数配置失败: {e}") @@ -994,8 +1012,11 @@ class WoWMultiKeyGUI(QMainWindow): cfg['offset_left'] = self.gs_offset_left.value() cfg['offset_top'] = self.gs_offset_top.value() cfg['mount_key'] = (self.gs_mount_key.text().strip() or 'x') + cfg['enable_mount'] = self.gs_enable_mount.isChecked() cfg['mount_hold_sec'] = float(self.gs_mount_hold.value()) cfg['mount_retry_after_sec'] = float(self.gs_mount_retry.value()) + cfg['hearthstone_key'] = (self.gs_hearthstone_key.text().strip() or 'b') + cfg['bag_full_hearthstone'] = self.gs_bag_full_hearthstone.isChecked() path = save_layout_config(cfg) # bot 参数写入主配置文件 self.config = self.config or {} @@ -1444,6 +1465,7 @@ class WoWMultiKeyGUI(QMainWindow): ) self.game_worker.state_signal.connect(self.state_label.setText) self.game_worker.log_signal.connect(self.log) + self.game_worker.stop_signal.connect(self._stop_game_worker) self.game_worker.finished.connect(self._on_game_loop_finished) self.game_worker.start() self.game_start_btn.setEnabled(False)