add 回城修理模式

This commit is contained in:
王鹏
2026-03-26 10:41:04 +08:00
parent 10ebf0b2cf
commit 8c1460a582
2 changed files with 101 additions and 2 deletions

View File

@@ -69,3 +69,9 @@
- `auto_bot_move.py`:在 `execute_logic` 的战斗/攻击分支中增加对 `state['target']` 的有效性判定,要求 `target_hp` 存在且 `> 0`,避免对无效/已死目标误触发攻击按键
- 同步调整:战斗调用 `execute_combat_logic()` 以及脱战阶段的 `Tab` 寻怪条件,均改为基于有效目标 `effective_target`
### 飞行模式后新增回城修理
- `wow_multikey_gui.py`:在“飞行模式”之后新增独立模式 `回城修理`,用于在回城时执行修理商交互
- 配置项:`回城修理` 模式增加 `修理商 JSON` 下拉选择,并将选择的 JSON 传给 `LogisticsManager`
- 行为约束:按下 GUI 的 `停止` 会将 `running` 置为 `False`,从而让回城路径行走在下一轮状态轮询中中断退出

View File

@@ -418,6 +418,46 @@ class GameLoopWorker(QThread):
self.log_signal.emit(f"❌ 飞行模式依赖加载失败: {e}")
return
if self.mode == 'return_repair':
if not self.vendor_path:
self.log_signal.emit("❌ 回城修理模式:未选择修理商 JSON")
return
try:
from logistics_manager import LogisticsManager
from coordinate_patrol import CoordinatePatrol
from game_state import load_layout_config
layout = load_layout_config()
self.patrol_controller = CoordinatePatrol(
waypoints=[(0.0, 0.0)],
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)),
)
self.logistics_manager = LogisticsManager(route_file=self.vendor_path)
self.log_signal.emit(f"⛑️ 回城修理:开始执行路径({os.path.basename(self.vendor_path)}")
get_state = lambda: parse_game_state() if self.running else None
ok = self.logistics_manager.run_route1_round(
get_state,
self.patrol_controller,
route_file=self.vendor_path,
)
if ok:
self.log_signal.emit("✅ 回城修理:路径完成")
else:
self.log_signal.emit("⏹️ 回城修理:已中止或未完成")
except ImportError as e:
self.log_signal.emit(f"❌ 回城修理依赖加载失败: {e}")
return
except Exception as e:
self.log_signal.emit(f"❌ 回城修理执行失败: {e}")
return
finally:
self.running = False
return
if self.mode == 'record':
try:
from recorder import WaypointRecorder
@@ -539,6 +579,7 @@ class WoWMultiKeyGUI(QMainWindow):
('combat', '自动打怪'),
('quest_follow', '任务跟随'),
('flight', '飞行模式'),
('return_repair', '回城修理'),
]:
btn = QPushButton(name)
btn.setCheckable(True)
@@ -648,6 +689,19 @@ class WoWMultiKeyGUI(QMainWindow):
self.flight_group.setVisible(False)
game_layout.addWidget(self.flight_group)
# 回城修理配置(在飞行模式之后新增一个独立模式)
self.repair_group = QGroupBox("回城修理配置")
repair_layout = QFormLayout(self.repair_group)
self.repair_vendor_combo = QComboBox()
self.repair_vendor_combo.setMinimumWidth(200)
self._refresh_repair_vendor_json_combo()
repair_refresh_btn = QPushButton("🔄 刷新列表")
repair_refresh_btn.clicked.connect(self._refresh_repair_vendor_json_combo)
repair_layout.addRow("修理商 JSON:", self.repair_vendor_combo)
repair_layout.addRow("", repair_refresh_btn)
self.repair_group.setVisible(False)
game_layout.addWidget(self.repair_group)
self.state_label = QLabel("状态: ---")
self.state_label.setStyleSheet("font-family: monospace; padding: 6px; background: #1e1e1e; color: #d4d4d4;")
self.state_label.setMinimumHeight(36)
@@ -1139,7 +1193,10 @@ class WoWMultiKeyGUI(QMainWindow):
def _refresh_recorder_combos(self):
"""刷新巡逻点、修理商下拉列表"""
items = list_recorder_json()
for combo, default_name in [(self.waypoints_combo, 'waypoints.json'), (self.vendor_combo, 'vendor.json')]:
combos = [(self.waypoints_combo, 'waypoints.json'), (self.vendor_combo, 'vendor.json')]
if hasattr(self, "repair_vendor_combo"):
combos.append((self.repair_vendor_combo, 'vendor.json'))
for combo, default_name in combos:
combo.clear()
combo.addItem("-- 请选择 --", "")
for name, path in items:
@@ -1151,6 +1208,24 @@ class WoWMultiKeyGUI(QMainWindow):
elif combo.count() > 1:
combo.setCurrentIndex(1)
def _refresh_repair_vendor_json_combo(self):
"""刷新“回城修理配置”的修理商下拉框。"""
if not hasattr(self, "repair_vendor_combo"):
return
items = list_recorder_json()
self.repair_vendor_combo.blockSignals(True)
self.repair_vendor_combo.clear()
self.repair_vendor_combo.addItem("-- 请选择 --", "")
for name, path in items:
self.repair_vendor_combo.addItem(name, path)
self.repair_vendor_combo.blockSignals(False)
if self.repair_vendor_combo.count() > 1:
idx = self.repair_vendor_combo.findData(os.path.join(get_recorder_dir(), 'vendor.json'))
if idx >= 0:
self.repair_vendor_combo.setCurrentIndex(idx)
else:
self.repair_vendor_combo.setCurrentIndex(1)
def _refresh_flight_json_combo(self):
"""刷新飞行模式航线 JSON 下拉列表"""
items = list_recorder_json()
@@ -1180,8 +1255,11 @@ class WoWMultiKeyGUI(QMainWindow):
self.combat_group.setVisible(mode == 'combat')
self.quest_follow_group.setVisible(mode == 'quest_follow')
self.flight_group.setVisible(mode == 'flight')
self.repair_group.setVisible(mode == 'return_repair')
if mode == 'flight':
self._refresh_flight_json_combo()
if mode == 'return_repair':
self._refresh_repair_vendor_json_combo()
def load_config(self):
if os.path.exists(self.config_path):
@@ -1261,7 +1339,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
@@ -1301,6 +1379,16 @@ class WoWMultiKeyGUI(QMainWindow):
}
self._save_main_config()
if mode == 'return_repair':
vp = self.repair_vendor_combo.currentData() or ""
if not vp:
QMessageBox.warning(self, "提示", "回城修理模式需选择修理商 JSON 文件")
return
if not os.path.exists(vp):
QMessageBox.warning(self, "提示", f"修理商文件不存在: {vp}")
return
vendor_path = vp
if mode == 'flight':
fp = self.flight_json_combo.currentData() or ""
if not fp:
@@ -1366,6 +1454,7 @@ class WoWMultiKeyGUI(QMainWindow):
'combat': '自动打怪',
'quest_follow': '任务跟随',
'flight': '飞行模式',
'return_repair': '回城修理',
}
self.status_bar.showMessage(f"🟢 {mode_names[mode]} 运行中")
self.log(f"🎮 {mode_names[mode]} 已启动")
@@ -1417,6 +1506,10 @@ class WoWMultiKeyGUI(QMainWindow):
if getattr(self.game_worker, "bot_move", None):
self.game_worker.bot_move.patrol_controller.stop_all()
self.game_worker.bot_move.logistics_manager.is_returning = False
if getattr(self.game_worker, "patrol_controller", None):
self.game_worker.patrol_controller.stop_all()
if getattr(self.game_worker, "logistics_manager", None):
self.game_worker.logistics_manager.is_returning = False
except Exception:
pass
# 不在这里 wait(),避免阻塞 GUI线程会在下一轮循环自然退出