Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import cv2
- import numpy as np
- import mss
- import win32api
- import win32con
- import time
- import keyboard
- import threading
- import tkinter as tk
- import json
- from tkinter import ttk, colorchooser, simpledialog, messagebox
- from PIL import Image, ImageTk
- # --- Default Configuration ---
- DEFAULT_AIM_HOTKEY = 'shift'
- DEFAULT_SCREEN_CAPTURE_FOV = 300
- DEFAULT_LOWER_COLOR = np.array([0, 0, 0])
- DEFAULT_UPPER_COLOR = np.array([179, 255, 50])
- DEFAULT_AIM_SPEED_X = 0.3
- DEFAULT_AIM_SPEED_Y = 0.3
- DEFAULT_MIN_CONTOUR_AREA = 10
- PREDEFINED_COLORS = {
- "Black": ([0, 0, 0], [179, 255, 50]),
- "White": ([0, 0, 180], [179, 40, 255]),
- "Red": ([0, 120, 70], [10, 255, 255]),
- "Green": ([35, 80, 50], [85, 255, 255]),
- "Blue": ([95, 100, 50], [135, 255, 255]),
- "Yellow": ([20, 100, 100], [35, 255, 255]),
- "Pink": ([140, 80, 100], [170, 255, 255]),
- "Cyan": ([80, 100, 80], [100, 255, 255])
- }
- class ColorbotGUI:
- def __init__(self, root):
- self.root = root
- self.root.title("Advanced Colorbot GUI (Configurable)")
- self.bot_thread = None
- self.bot_running = False
- # Variables
- self.aim_hotkey = tk.StringVar(value=DEFAULT_AIM_HOTKEY)
- self.fov_size = tk.IntVar(value=DEFAULT_SCREEN_CAPTURE_FOV)
- self.aim_speed_x = tk.DoubleVar(value=DEFAULT_AIM_SPEED_X)
- self.aim_speed_y = tk.DoubleVar(value=DEFAULT_AIM_SPEED_Y)
- self.show_esp_box_main = tk.BooleanVar(value=True)
- self.min_contour_area = tk.IntVar(value=DEFAULT_MIN_CONTOUR_AREA)
- self.always_on_top = tk.BooleanVar(value=False)
- self.lower_color = list(DEFAULT_LOWER_COLOR)
- self.upper_color = list(DEFAULT_UPPER_COLOR)
- self.current_color_name = tk.StringVar(value="Black (Default)")
- # --- Layout ---
- main_frame = ttk.Frame(root, padding="10")
- main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
- # Left Column
- left_panel = ttk.Frame(main_frame)
- left_panel.grid(row=0, column=0, sticky=(tk.N, tk.S, tk.W, tk.E), padx=5)
- controls_frame = ttk.LabelFrame(left_panel, text="Controls", padding="10")
- controls_frame.pack(fill=tk.X, pady=5)
- color_select_frame = ttk.LabelFrame(left_panel, text="Color Selection", padding="10")
- color_select_frame.pack(fill=tk.X, pady=5)
- config_frame = ttk.LabelFrame(left_panel, text="Config Manager", padding="10")
- config_frame.pack(fill=tk.X, pady=5)
- # Right Column (Video)
- video_frame = ttk.LabelFrame(main_frame, text="Live Feed", padding="10")
- video_frame.grid(row=0, column=1, sticky=(tk.N, tk.S, tk.W, tk.E), padx=5, pady=5)
- root.columnconfigure(0, weight=1)
- main_frame.columnconfigure(1, weight=3)
- main_frame.columnconfigure(0, weight=1)
- # --- Video Feed ---
- self.video_label = ttk.Label(video_frame, text="Bot Inactive")
- self.video_label.pack(expand=True, fill=tk.BOTH)
- # --- Controls Section ---
- row_idx = 0
- self.start_stop_button = ttk.Button(controls_frame, text="Start Bot", command=self.toggle_bot)
- self.start_stop_button.grid(row=row_idx, column=0, columnspan=2, pady=5, sticky=tk.EW); row_idx += 1
- ttk.Label(controls_frame, text="Aim Key:").grid(row=row_idx, column=0, sticky=tk.W, pady=2)
- self.aim_key_label = ttk.Label(controls_frame, textvariable=self.aim_hotkey)
- self.aim_key_label.grid(row=row_idx, column=1, sticky=tk.W, pady=2); row_idx += 1
- ttk.Button(controls_frame, text="Set Aim Key", command=self.set_aim_key).grid(row=row_idx, column=0, columnspan=2, pady=2, sticky=tk.EW); row_idx += 1
- ttk.Label(controls_frame, text="FOV Size:").grid(row=row_idx, column=0, sticky=tk.W, pady=2)
- ttk.Scale(controls_frame, from_=50, to=800, variable=self.fov_size, orient=tk.HORIZONTAL, command=lambda v: self.fov_size.set(int(float(v)))).grid(row=row_idx, column=1, sticky=tk.EW, pady=2); row_idx += 1
- ttk.Label(controls_frame, text="Min Color Size (Area):").grid(row=row_idx, column=0, sticky=tk.W, pady=2)
- ttk.Scale(controls_frame, from_=1, to=500, variable=self.min_contour_area, orient=tk.HORIZONTAL, command=lambda v: self.min_contour_area.set(int(float(v)))).grid(row=row_idx, column=1, sticky=tk.EW, pady=2); row_idx += 1
- ttk.Label(controls_frame, text="Aim Speed X:").grid(row=row_idx, column=0, sticky=tk.W, pady=2)
- ttk.Scale(controls_frame, from_=0.01, to=2.0, variable=self.aim_speed_x, orient=tk.HORIZONTAL).grid(row=row_idx, column=1, sticky=tk.EW, pady=2); row_idx += 1
- ttk.Label(controls_frame, text="Aim Speed Y:").grid(row=row_idx, column=0, sticky=tk.W, pady=2)
- ttk.Scale(controls_frame, from_=0.01, to=2.0, variable=self.aim_speed_y, orient=tk.HORIZONTAL).grid(row=row_idx, column=1, sticky=tk.EW, pady=2); row_idx += 1
- ttk.Checkbutton(controls_frame, text="Show ESP Box (Main Feed)", variable=self.show_esp_box_main).grid(row=row_idx, column=0, columnspan=2, pady=5, sticky=tk.W); row_idx+=1
- ttk.Checkbutton(controls_frame, text="Always on Top (GUI)", variable=self.always_on_top, command=self.toggle_always_on_top).grid(row=row_idx, column=0, columnspan=2, pady=5, sticky=tk.W); row_idx +=1
- controls_frame.columnconfigure(1, weight=1)
- # --- Color Selection Section ---
- ttk.Label(color_select_frame, text="Current Target Color:").pack(pady=(0,2))
- self.current_color_label = ttk.Label(color_select_frame, textvariable=self.current_color_name, font=("Arial", 10, "bold"))
- self.current_color_label.pack(pady=(0,5))
- self.color_preview = tk.Frame(color_select_frame, width=100, height=20, bg=self.get_hex_from_hsv_upper())
- self.color_preview.pack(pady=(0,10))
- # NEW: Visualizer Button
- ttk.Button(color_select_frame, text="Open Color Visualizer", command=self.open_visualizer).pack(fill=tk.X, pady=2)
- ttk.Button(color_select_frame, text="Pick Custom Color", command=self.pick_custom_color).pack(fill=tk.X, pady=5)
- ttk.Label(color_select_frame, text="Quick Palette:").pack(pady=(10,2))
- palette_frame = ttk.Frame(color_select_frame)
- palette_frame.pack()
- col_count = 0; palette_row_idx = 0; max_cols = 3
- for color_name, (lower, upper) in PREDEFINED_COLORS.items():
- b = ttk.Button(palette_frame, text=color_name, command=lambda l=list(lower), u=list(upper), n=color_name: self.set_target_color(l, u, n))
- b.grid(row=palette_row_idx, column=col_count % max_cols, padx=2, pady=2, sticky=tk.EW)
- col_count += 1
- if col_count % max_cols == 0: palette_row_idx +=1
- # --- Config Manager Section ---
- ttk.Label(config_frame, text="Config String:").pack(anchor=tk.W)
- self.config_entry = ttk.Entry(config_frame)
- self.config_entry.pack(fill=tk.X, pady=5)
- btn_frame = ttk.Frame(config_frame)
- btn_frame.pack(fill=tk.X)
- ttk.Button(btn_frame, text="Copy Config", command=self.copy_config).pack(side=tk.LEFT, expand=True, fill=tk.X, padx=2)
- ttk.Button(btn_frame, text="Load Config", command=self.load_config).pack(side=tk.LEFT, expand=True, fill=tk.X, padx=2)
- self.update_color_preview()
- self.root.protocol("WM_DELETE_WINDOW", self.on_closing)
- # --- Visualizer / Minimap Function ---
- def open_visualizer(self):
- viz_win = tk.Toplevel(self.root)
- viz_win.title("Color Range Visualizer")
- viz_win.geometry("400x500")
- viz_win.attributes('-topmost', True)
- # Image Label
- img_label = ttk.Label(viz_win)
- img_label.pack(padx=10, pady=10)
- # Controls Frame
- ctrl_frame = ttk.Frame(viz_win, padding=10)
- ctrl_frame.pack(fill=tk.X)
- # Tolerance Logic
- # We calculate tolerance based on Hue width
- current_h_center = (self.lower_color[0] + self.upper_color[0]) // 2
- current_tolerance = (self.upper_color[0] - self.lower_color[0]) // 2
- tol_var = tk.IntVar(value=current_tolerance)
- def update_viz_image(*args):
- # 1. Generate HSV Spectrum
- # X-axis: Hue (0-179), Y-axis: Saturation (255-0)
- # We use a fixed Value (Brightness) based on current settings to ensure visibility
- vis_v = int((self.lower_color[2] + self.upper_color[2]) / 2)
- if vis_v == 0: vis_v = 128 # Fallback if black
- # Create grid
- width = 360 # 2 pixels per hue degree for better visibility
- height = 256
- # Create Hue gradient (0 to 179 repeated to fill width)
- hue_range = np.linspace(0, 179, width, dtype=np.uint8)
- hue_grid = np.tile(hue_range, (height, 1))
- # Create Saturation gradient (255 to 0)
- sat_range = np.linspace(255, 0, height, dtype=np.uint8).reshape(-1, 1)
- sat_grid = np.tile(sat_range, (1, width))
- # Create Value grid
- val_grid = np.full((height, width), vis_v, dtype=np.uint8)
- # Merge into HSV image
- hsv_map = cv2.merge([hue_grid, sat_grid, val_grid])
- bgr_map = cv2.cvtColor(hsv_map, cv2.COLOR_HSV2BGR)
- # 2. Create Mask based on ACTUAL settings
- # We need to check if the pixels in our map fall within the bot's detection range
- lower_np = np.array(self.lower_color, dtype=np.uint8)
- upper_np = np.array(self.upper_color, dtype=np.uint8)
- mask = cv2.inRange(hsv_map, lower_np, upper_np)
- # 3. Apply "Grey Out" effect
- # Convert map to greyscale
- grey_map = cv2.cvtColor(bgr_map, cv2.COLOR_BGR2GRAY)
- grey_map_bgr = cv2.cvtColor(grey_map, cv2.COLOR_GRAY2BGR)
- # Combine: Where mask is white (255), use color. Where mask is black (0), use grey.
- mask_inv = cv2.bitwise_not(mask)
- colored_part = cv2.bitwise_and(bgr_map, bgr_map, mask=mask)
- grey_part = cv2.bitwise_and(grey_map_bgr, grey_map_bgr, mask=mask_inv)
- final_viz = cv2.add(colored_part, grey_part)
- # Add crosshair for center hue
- center_x = int((current_h_center / 179.0) * width)
- cv2.line(final_viz, (center_x, 0), (center_x, height), (255, 255, 255), 1)
- # Display
- img_pil = Image.fromarray(cv2.cvtColor(final_viz, cv2.COLOR_BGR2RGB))
- imgtk = ImageTk.PhotoImage(image=img_pil)
- img_label.imgtk = imgtk
- img_label.config(image=imgtk)
- def on_tolerance_change(val):
- try:
- tol = int(float(val))
- tol_var.set(tol)
- # Update Global Colors based on center + tolerance
- new_lower_h = max(0, current_h_center - tol)
- new_upper_h = min(179, current_h_center + tol)
- self.lower_color[0] = new_lower_h
- self.upper_color[0] = new_upper_h
- # Update main GUI preview
- self.update_color_preview()
- self.current_color_label.config(text=f"Custom (Tol: {tol})")
- # Update Visualizer
- update_viz_image()
- except: pass
- def on_entry_change(event=None):
- try:
- val = int(tol_entry.get())
- tolerance_scale.set(val) # This triggers the scale command
- except: pass
- ttk.Label(ctrl_frame, text="Hue Tolerance:").pack(anchor=tk.W)
- tolerance_scale = ttk.Scale(ctrl_frame, from_=1, to=90, orient=tk.HORIZONTAL, command=on_tolerance_change)
- tolerance_scale.set(current_tolerance)
- tolerance_scale.pack(fill=tk.X, pady=5)
- tol_entry = ttk.Entry(ctrl_frame, textvariable=tol_var)
- tol_entry.pack(fill=tk.X, pady=5)
- tol_entry.bind('<Return>', on_entry_change)
- tol_entry.bind('<FocusOut>', on_entry_change)
- ttk.Label(ctrl_frame, text="* Grey areas are colors the bot will IGNORE.").pack(pady=5)
- # Initial Draw
- update_viz_image()
- # --- Config Functions ---
- def copy_config(self):
- config_data = {
- "aim_key": self.aim_hotkey.get(),
- "fov": self.fov_size.get(),
- "speed_x": self.aim_speed_x.get(),
- "speed_y": self.aim_speed_y.get(),
- "min_size": self.min_contour_area.get(),
- "esp": self.show_esp_box_main.get(),
- "top": self.always_on_top.get(),
- "color_lower": self.lower_color,
- "color_upper": self.upper_color,
- "color_name": self.current_color_name.get()
- }
- try:
- config_str = json.dumps(config_data)
- self.config_entry.delete(0, tk.END)
- self.config_entry.insert(0, config_str)
- self.root.clipboard_clear()
- self.root.clipboard_append(config_str)
- messagebox.showinfo("Config", "Config copied to clipboard!")
- except Exception as e:
- messagebox.showerror("Error", f"Failed to generate config: {e}")
- def load_config(self):
- config_str = self.config_entry.get()
- if not config_str:
- messagebox.showwarning("Config", "Please paste a config string into the box first.")
- return
- try:
- data = json.loads(config_str)
- if "aim_key" in data: self.aim_hotkey.set(data["aim_key"])
- if "fov" in data: self.fov_size.set(data["fov"])
- if "speed_x" in data: self.aim_speed_x.set(data["speed_x"])
- if "speed_y" in data: self.aim_speed_y.set(data["speed_y"])
- if "min_size" in data: self.min_contour_area.set(data["min_size"])
- if "esp" in data: self.show_esp_box_main.set(data["esp"])
- if "top" in data:
- self.always_on_top.set(data["top"])
- self.toggle_always_on_top()
- if "color_lower" in data and "color_upper" in data:
- self.lower_color = data["color_lower"]
- self.upper_color = data["color_upper"]
- name = data.get("color_name", "Custom Config")
- self.current_color_name.set(name)
- self.update_color_preview()
- messagebox.showinfo("Config", "Configuration loaded successfully!")
- except Exception as e:
- messagebox.showerror("Config Error", f"Error loading config: {e}")
- # --- Existing Functions ---
- def toggle_always_on_top(self):
- if self.always_on_top.get():
- self.root.attributes('-topmost', True)
- else:
- self.root.attributes('-topmost', False)
- def get_hex_from_hsv_upper(self):
- try:
- hsv_color_array = np.uint8([[self.upper_color]])
- rgb_color_array = cv2.cvtColor(hsv_color_array, cv2.COLOR_HSV2RGB)
- return f"#{rgb_color_array[0][0][0]:02x}{rgb_color_array[0][0][1]:02x}{rgb_color_array[0][0][2]:02x}"
- except: return "#FFFFFF"
- def update_color_preview(self):
- self.color_preview.config(bg=self.get_hex_from_hsv_upper())
- def set_target_color(self, lower_hsv, upper_hsv, name="Custom"):
- self.lower_color = list(lower_hsv); self.upper_color = list(upper_hsv)
- self.current_color_name.set(name); self.update_color_preview()
- def pick_custom_color(self):
- color_code = colorchooser.askcolor(title="Choose Target Color (RGB)", parent=self.root)
- if color_code and color_code[0]:
- rgb = color_code[0]; rgb_np = np.uint8([[rgb]]); hsv_np = cv2.cvtColor(rgb_np, cv2.COLOR_RGB2HSV)
- hue = hsv_np[0][0][0]
- try:
- s_min = simpledialog.askinteger("Saturation Min", "Enter MIN Saturation (0-255):", initialvalue=100, minvalue=0, maxvalue=255, parent=self.root)
- s_max = simpledialog.askinteger("Saturation Max", "Enter MAX Saturation (0-255):", initialvalue=255, minvalue=0, maxvalue=255, parent=self.root)
- v_min = simpledialog.askinteger("Value Min", "Enter MIN Value/Brightness (0-255):", initialvalue=100, minvalue=0, maxvalue=255, parent=self.root)
- v_max = simpledialog.askinteger("Value Max", "Enter MAX Value/Brightness (0-255):", initialvalue=255, minvalue=0, maxvalue=255, parent=self.root)
- h_tolerance = simpledialog.askinteger("Hue Tolerance", "Enter Hue Tolerance (+/- value):", initialvalue=10, minvalue=1, maxvalue=89, parent=self.root)
- if None not in [s_min, s_max, v_min, v_max, h_tolerance]:
- lower_h = max(0, hue - h_tolerance); upper_h = min(179, hue + h_tolerance)
- self.set_target_color([lower_h, s_min, v_min], [upper_h, s_max, v_max], f"Custom RGB:({int(rgb[0])},{int(rgb[1])},{int(rgb[2])})")
- except Exception as e: messagebox.showerror("Error", f"Could not set custom color: {e}", parent=self.root)
- def set_aim_key(self):
- self.aim_key_label.config(text="Press new aim key...")
- self.root.update()
- try:
- event = keyboard.read_event(suppress=True)
- if event.event_type == keyboard.KEY_DOWN:
- new_key = event.name
- if 'left ' in new_key: new_key = new_key.replace('left ', '')
- if 'right ' in new_key: new_key = new_key.replace('right ', '')
- if new_key == 'ctrl': new_key = 'control'
- self.aim_hotkey.set(new_key)
- except Exception as e:
- self.aim_key_label.config(text=self.aim_hotkey.get())
- messagebox.showerror("Error", f"Could not set aim key: {e}", parent=self.root)
- def toggle_bot(self):
- if self.bot_running: self.stop_bot()
- else: self.start_bot()
- def start_bot(self):
- if self.bot_running: return
- self.bot_running = True
- self.start_stop_button.config(text="Stop Bot")
- self.video_label.config(text="Bot Starting...", image=None)
- if hasattr(self.video_label, 'imgtk'): self.video_label.imgtk = None
- self.bot_thread = threading.Thread(target=self.colorbot_loop, daemon=True)
- self.bot_thread.start()
- def stop_bot(self):
- if not self.bot_running: return
- self.bot_running = False
- if self.bot_thread and self.bot_thread.is_alive():
- self.bot_thread.join(timeout=1.5)
- self.start_stop_button.config(text="Start Bot")
- self.video_label.config(image=None, text="Bot Inactive")
- if hasattr(self.video_label, 'imgtk'): self.video_label.imgtk = None
- def on_closing(self):
- if self.bot_running: self.stop_bot()
- self.root.destroy()
- def display_main_feed(self, img_pil_main_feed):
- try:
- imgtk = ImageTk.PhotoImage(image=img_pil_main_feed)
- self.video_label.imgtk = imgtk
- self.video_label.config(image=imgtk)
- except Exception:
- pass
- def colorbot_loop(self):
- sct_local = mss.mss()
- last_frame_time = time.time(); target_fps = 30; min_frame_interval = 1.0 / target_fps
- while self.bot_running:
- current_time = time.time(); delta_time = current_time - last_frame_time
- if delta_time < min_frame_interval:
- sleep_duration = min_frame_interval - delta_time
- if sleep_duration > 0: time.sleep(sleep_duration)
- last_frame_time = time.time()
- try:
- active_aim_key = self.aim_hotkey.get(); fov = self.fov_size.get()
- current_lower_color = np.array(self.lower_color, dtype=np.uint8)
- current_upper_color = np.array(self.upper_color, dtype=np.uint8)
- speed_x = self.aim_speed_x.get(); speed_y = self.aim_speed_y.get()
- esp_on_main_gui = self.show_esp_box_main.get()
- min_area = self.min_contour_area.get()
- cursor_x, cursor_y = win32api.GetCursorPos()
- monitor_region = {"top": cursor_y - fov // 2, "left": cursor_x - fov // 2, "width": fov, "height": fov}
- img_np = np.array(sct_local.grab(monitor_region))
- frame_bgr_original = cv2.cvtColor(img_np, cv2.COLOR_BGRA2BGR)
- frame_for_esp_drawing = frame_bgr_original.copy()
- hsv = cv2.cvtColor(frame_bgr_original, cv2.COLOR_BGR2HSV)
- mask = cv2.inRange(hsv, current_lower_color, current_upper_color)
- contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
- target_center_x, target_center_y = None, None
- if contours:
- largest_contour = max(contours, key=cv2.contourArea)
- if cv2.contourArea(largest_contour) >= min_area:
- M = cv2.moments(largest_contour)
- if M["m00"] != 0:
- target_center_x = int(M["m10"] / M["m00"])
- target_center_y = int(M["m01"] / M["m00"])
- if esp_on_main_gui:
- x, y, w, h = cv2.boundingRect(largest_contour)
- cv2.rectangle(frame_for_esp_drawing, (x, y), (x + w, y + h), (0, 255, 0), 2)
- cv2.circle(frame_for_esp_drawing, (target_center_x, target_center_y), 5, (0,0,255), -1)
- if keyboard.is_pressed(active_aim_key) and target_center_x is not None:
- frame_center_x = fov // 2; frame_center_y = fov // 2
- dx = target_center_x - frame_center_x; dy = target_center_y - frame_center_y
- move_x = int(dx * speed_x); move_y = int(dy * speed_y)
- if abs(move_x) > 0 or abs(move_y) > 0:
- win32api.mouse_event(win32con.MOUSEEVENTF_MOVE, move_x, move_y, 0, 0)
- game_part_for_main_gui = frame_for_esp_drawing if esp_on_main_gui else frame_bgr_original
- mask_for_display_main_gui = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR)
- combined_display_main_gui = np.hstack((game_part_for_main_gui, mask_for_display_main_gui))
- img_pil_main_gui = Image.fromarray(cv2.cvtColor(combined_display_main_gui, cv2.COLOR_BGR2RGB))
- self.root.after(0, self.display_main_feed, img_pil_main_gui)
- except mss.exception.ScreenShotError: time.sleep(0.05)
- except Exception as e:
- print(f"Error in colorbot loop: {e}")
- time.sleep(0.05)
- self.root.after(0, lambda: self.video_label.config(image=None, text="Bot Inactive"))
- if hasattr(self.video_label, 'imgtk'): self.root.after(0, lambda: setattr(self.video_label, 'imgtk', None))
- if __name__ == "__main__":
- root = tk.Tk()
- app = ColorbotGUI(root)
- root.mainloop()
Advertisement
Add Comment
Please, Sign In to add comment