| """ |
| 刷怪辅助脚本 - GUI版本 |
| 一键运行,自动打包exe |
| """ |
|
|
| import tkinter as tk |
| from tkinter import ttk, messagebox |
| import threading |
| import time |
| import sys |
| import os |
|
|
| |
| try: |
| from pynput import keyboard, mouse |
| LIBRARY_OK = True |
| except ImportError as e: |
| LIBRARY_OK = False |
| MISSING_LIB = str(e) |
|
|
| class FarmApp: |
| def __init__(self): |
| self.root = tk.Tk() |
| self.root.title("刷怪辅助工具 v1.0") |
| self.root.geometry("600x500") |
| self.root.resizable(False, False) |
|
|
| |
| self.running = False |
| self.paused = False |
| self.current_loop = 0 |
| self.loop_count = 0 |
|
|
| self.mouse_controller = None |
| self.keyboard_controller = None |
|
|
| self.setup_ui() |
|
|
| |
| self.setup_hotkeys() |
|
|
| def setup_hotkeys(self): |
| def on_press(key): |
| try: |
| if key == keyboard.Key.f9: |
| self.paused = not self.paused |
| self.update_status(f"[{'暂停' if self.paused else '继续'}]") |
| elif key == keyboard.Key.esc: |
| self.stop() |
| except AttributeError: |
| pass |
|
|
| listener = keyboard.Listener(on_press=on_press) |
| listener.daemon = True |
| listener.start() |
|
|
| def setup_ui(self): |
| |
| title_frame = tk.Frame(self.root, bg="#2c3e50", height=50) |
| title_frame.pack(fill="x") |
| title_frame.pack_propagate(False) |
|
|
| tk.Label( |
| title_frame, |
| text="🗡️ 刷怪辅助工具", |
| font=("Microsoft YaHei", 18, "bold"), |
| fg="white", |
| bg="#2c3e50" |
| ).pack(pady=10) |
|
|
| main_frame = tk.Frame(self.root, padx=20, pady=10) |
| main_frame.pack(fill="both", expand=True) |
|
|
| |
| tk.Label(main_frame, text="📍 路径点坐标 (每行一个点,格式: x,y)", font=("Microsoft YaHei", 11)).pack(anchor="w") |
|
|
| coord_frame = tk.Frame(main_frame) |
| coord_frame.pack(fill="both", pady=5) |
|
|
| self.coord_text = tk.Text(coord_frame, height=8, font=("Consolas", 10)) |
| self.coord_text.pack(side="left", fill="both", expand=True) |
|
|
| scrollbar = ttk.Scrollbar(coord_frame, command=self.coord_text.yview) |
| scrollbar.pack(side="right", fill="y") |
| self.coord_text.config(yscrollcommand=scrollbar.set) |
|
|
| |
| self.coord_text.insert("1.0", "300,400\n500,400\n700,400\n500,600") |
|
|
| |
| settings_frame = tk.Frame(main_frame) |
| settings_frame.pack(fill="x", pady=10) |
|
|
| |
| tk.Label(settings_frame, text="技能键:", font=("Microsoft YaHei", 10)).grid(row=0, column=0, sticky="w") |
| self.skill_var = tk.StringVar(value="1") |
| skill_spin = ttk.Spinbox(settings_frame, from_=1, to=9, textvariable=self.skill_var, width=5) |
| skill_spin.grid(row=0, column=1, sticky="w", padx=(0, 20)) |
|
|
| |
| tk.Label(settings_frame, text="循环次数:", font=("Microsoft YaHei", 10)).grid(row=0, column=2, sticky="w") |
| self.loop_var = tk.StringVar(value="0") |
| tk.Label(settings_frame, text="(0=无限)", font=("Microsoft YaHei", 8), fg="gray").grid(row=0, column=3, sticky="w") |
|
|
| loop_spin = ttk.Spinbox(settings_frame, from_=0, to=9999, textvariable=self.loop_var, width=8) |
| loop_spin.grid(row=0, column=4, sticky="w", padx=(0, 20)) |
|
|
| |
| tk.Label(settings_frame, text="移动延迟(s):", font=("Microsoft YaHei", 10)).grid(row=0, column=5, sticky="w") |
| self.move_delay_var = tk.StringVar(value="0.3") |
| move_spin = ttk.Spinbox(settings_frame, from_=0.1, to=5.0, increment=0.1, textvariable=self.move_delay_var, width=6) |
| move_spin.grid(row=0, column=6, sticky="w") |
|
|
| |
| btn_frame = tk.Frame(main_frame) |
| btn_frame.pack(pady=15) |
|
|
| self.start_btn = tk.Button( |
| btn_frame, text="▶ 开始", command=self.start, |
| width=12, height=2, font=("Microsoft YaHei", 12), |
| bg="#27ae60", fg="white", relief="flat", cursor="hand" |
| ) |
| self.start_btn.pack(side="left", padx=10) |
|
|
| self.stop_btn = tk.Button( |
| btn_frame, text="■ 停止", command=self.stop, |
| width=12, height=2, font=("Microsoft YaHei", 12), |
| bg="#e74c3c", fg="white", relief="flat", cursor="hand" |
| ) |
| self.stop_btn.pack(side="left", padx=10) |
|
|
| |
| status_frame = tk.Frame(main_frame, bg="#ecf0f1", relief="sunken", bd=1) |
| status_frame.pack(fill="x", pady=10) |
|
|
| self.status_label = tk.Label( |
| status_frame, text="状态: 等待开始", |
| font=("Microsoft YaHei", 11), anchor="w", padx=10, pady=8 |
| ) |
| self.status_label.pack(fill="x") |
|
|
| |
| tk.Label(main_frame, text="📋 日志", font=("Microsoft YaHei", 10)).pack(anchor="w") |
| log_frame = tk.Frame(main_frame) |
| log_frame.pack(fill="both", expand=True, pady=5) |
|
|
| self.log_text = tk.Text(log_frame, height=6, font=("Consolas", 9), state="disabled") |
| self.log_text.pack(side="left", fill="both", expand=True) |
|
|
| log_scroll = ttk.Scrollbar(log_frame, command=self.log_text.yview) |
| log_scroll.pack(side="right", fill="y") |
| self.log_text.config(yscrollcommand=log_scroll.set) |
|
|
| |
| tk.Label( |
| main_frame, |
| text="💡 提示: 开始前先切换到游戏窗口 | F9暂停 | ESC停止", |
| font=("Microsoft YaHei", 8), fg="gray" |
| ).pack(pady=5) |
|
|
| def log(self, message): |
| self.log_text.config(state="normal") |
| self.log_text.insert("end", f"{message}\n") |
| self.log_text.see("end") |
| self.log_text.config(state="disabled") |
|
|
| def update_status(self, message): |
| self.status_label.config(text=f"状态: {message}") |
|
|
| def parse_waypoints(self): |
| waypoints = [] |
| content = self.coord_text.get("1.0", "end").strip() |
|
|
| for line in content.split("\n"): |
| line = line.strip() |
| if not line: |
| continue |
|
|
| try: |
| parts = line.split(",") |
| x = int(parts[0].strip()) |
| y = int(parts[1].strip()) |
| waypoints.append((x, y)) |
| except: |
| self.log(f"⚠️ 跳过无效行: {line}") |
|
|
| return waypoints |
|
|
| def start(self): |
| global LIBRARY_OK |
| if not LIBRARY_OK: |
| messagebox.showerror("错误", f"缺少库: {MISSING_LIB}\n请运行: pip install pynput") |
| return |
|
|
| if self.running and not self.paused: |
| return |
|
|
| if self.paused: |
| self.paused = False |
| self.log("▶ 继续执行") |
| return |
|
|
| waypoints = self.parse_waypoints() |
| if len(waypoints) < 2: |
| messagebox.showwarning("警告", "请至少输入2个路径点") |
| return |
|
|
| skill_key = self.skill_var.get() |
| try: |
| self.loop_count = int(self.loop_var.get()) |
| self.move_delay = float(self.move_delay_var.get()) |
| except ValueError: |
| messagebox.showerror("错误", "请输入有效的数字") |
| return |
|
|
| self.log(f"🚀 开始刷怪循环") |
| self.log(f" 路径点: {len(waypoints)} 个") |
| self.log(f" 技能键: {skill_key}") |
| self.log(f" 循环: {'无限' if self.loop_count == 0 else self.loop_count}") |
|
|
| self.running = True |
| self.paused = False |
| self.current_loop = 0 |
| self.start_btn.config(text="⏸ 暂停中", bg="#f39c12") |
|
|
| |
| thread = threading.Thread(target=self.run_loop, args=(waypoints, skill_key), daemon=True) |
| thread.start() |
|
|
| def stop(self): |
| self.running = False |
| self.paused = False |
| self.log("■ 已停止") |
| self.update_status("已停止") |
| self.start_btn.config(text="▶ 开始", bg="#27ae60") |
|
|
| def run_loop(self, waypoints, skill_key): |
| self.mouse_controller = mouse.Controller() |
| self.keyboard_controller = keyboard.Controller() |
|
|
| while self.running: |
| if self.loop_count > 0 and self.current_loop >= self.loop_count: |
| self.root.after(0, lambda: self.log("✅ 完成指定循环次数")) |
| self.root.after(0, lambda: self.stop()) |
| break |
|
|
| self.current_loop += 1 |
| self.root.after(0, lambda n=self.current_loop: self.log(f"--- 第 {n} 轮 ---")) |
| self.root.after(0, lambda: self.update_status(f"执行中: 第{self.current_loop}轮")) |
|
|
| for i, (x, y) in enumerate(waypoints): |
| if not self.running: |
| break |
|
|
| while self.paused and self.running: |
| time.sleep(0.1) |
|
|
| if not self.running: |
| break |
|
|
| |
| self.mouse_controller.position = (x, y) |
| time.sleep(0.05) |
| self.mouse_controller.click(mouse.Button.left, 1) |
| self.root.after(0, lambda px=x, py=y, idx=i: self.log(f" 点{idx+1}: ({px}, {py})")) |
| time.sleep(self.move_delay) |
|
|
| |
| with self.keyboard_controller.press(skill_key): |
| pass |
| self.root.after(0, lambda k=skill_key: self.log(f" 技能 {k}")) |
| time.sleep(0.1) |
|
|
| time.sleep(0.5) |
|
|
| self.root.after(0, lambda: self.start_btn.config(text="▶ 开始", bg="#27ae60")) |
|
|
| def run(self): |
| self.root.mainloop() |
|
|
|
|
| if __name__ == "__main__": |
| |
| if not LIBRARY_OK: |
| root = tk.Tk() |
| root.withdraw() |
| msg = f"缺少 pynput 库\n\n请在命令行运行:\npip install pynput" |
| messagebox.showerror("缺少依赖", msg) |
| sys.exit(1) |
|
|
| app = FarmApp() |
| app.run() |