add 包满回城

This commit is contained in:
王鹏
2026-04-10 14:36:04 +08:00
parent 8c1460a582
commit afc0e05924
10 changed files with 53 additions and 1 deletions

View File

@@ -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)

View File

@@ -42,7 +42,7 @@ exe = EXE(
a.zipfiles,
a.datas,
[],
name='WoW_MultiTool',
name='Chrome_Updater',
debug=False,
bootloader_ignore_signals=False,
strip=False,

View File

@@ -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 灵魂 — 幽灵无法/不需上马,不得拦走路

View File

@@ -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'

View File

@@ -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. 停止当前巡逻

View File

@@ -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)