JustPaste
HomeCategoriesAboutDonateContactTerms of UsePrivacy Policy
JustPaste

Free online notepad — write and share instantly

Navigate

  • Home
  • Timeline
  • Categories

Info

  • About
  • Donate
  • Contact

Legal

  • Terms of Use
  • Privacy Policy

© 2026 JustPaste.app. All rights reserved.

Made with ♥ by JustPaste

Untitled Page | JustPaste.app
15 days ago1 views
👨‍💻Programming
import sys
import subprocess

# ============================================================
#   DEPENDENCY INJECTOR - Forces install into active runtime
# ============================================================
def force_install_dependencies():
    required = {
        "vgamepad": "vgamepad",
        "pygame": "pygame",
        "pywinusb": "pywinusb",
        "inputs": "inputs",
    }
    for pkg, import_name in required.items():
        try:
            __import__(import_name)
        except ImportError:
            print(f"[!] Missing: {pkg}")
            print(f"[+] Installing into: {sys.executable}")
            try:
                subprocess.check_call(
                    [sys.executable, "-m", "pip", "install", pkg],
                    stdout=subprocess.DEVNULL,
                    stderr=subprocess.DEVNULL,
                )
                print(f"[+] {pkg} installed successfully.")
            except Exception as e:
                print(f"[-] Failed to install {pkg}: {e}")
                print(f"\n[!] Run manually:")
                print(f'    "{sys.executable}" -m pip install {pkg}')
                sys.exit(1)

force_install_dependencies()

# ============================================================
#   CORE IMPORTS
# ============================================================
import threading
import time
import ctypes
import ctypes.wintypes
import tkinter as tk
from tkinter import ttk
import vgamepad as vg

# ============================================================
#   XINPUT DIRECT BYPASS ENGINE
#   Reads controller state via XInput API directly.
#   This bypasses HidHide because XInput talks to the
#   kernel-level driver stack, not the raw HID device.
# ============================================================

# XInput button bitmasks
XINPUT_BUTTONS = {
    "DPAD_UP":        0x0001,
    "DPAD_DOWN":      0x0002,
    "DPAD_LEFT":      0x0004,
    "DPAD_RIGHT":     0x0008,
    "START":          0x0010,
    "BACK":           0x0020,
    "LEFT_THUMB":     0x0040,
    "RIGHT_THUMB":    0x0080,
    "LEFT_SHOULDER":  0x0100,
    "RIGHT_SHOULDER": 0x0200,
    "A":              0x1000,
    "B":              0x2000,
    "X":              0x4000,
    "Y":              0x8000,
}

class XINPUT_GAMEPAD(ctypes.Structure):
    _fields_ = [
        ("wButtons",      ctypes.wintypes.WORD),
        ("bLeftTrigger",  ctypes.wintypes.BYTE),
        ("bRightTrigger", ctypes.wintypes.BYTE),
        ("sThumbLX",      ctypes.wintypes.SHORT),
        ("sThumbLY",      ctypes.wintypes.SHORT),
        ("sThumbRX",      ctypes.wintypes.SHORT),
        ("sThumbRY",      ctypes.wintypes.SHORT),
    ]

class XINPUT_STATE(ctypes.Structure):
    _fields_ = [
        ("dwPacketNumber", ctypes.wintypes.DWORD),
        ("Gamepad",        XINPUT_GAMEPAD),
    ]

class XInputEngine:
    """
    Direct XInput reader. HidHide does NOT block XInput.
    XInput talks through xinput driver -> kernel, not HID path.
    Supports up to 4 controllers, auto-detects first active one.
    """
    def __init__(self):
        try:
            self.xinput = ctypes.windll.xinput1_4
        except Exception:
            try:
                self.xinput = ctypes.windll.xinput1_3
            except Exception:
                self.xinput = ctypes.windll.xinput9_1_0

        self.active_port = -1
        self.state = XINPUT_STATE()
        self._deadzone_left  = 7849   # XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE
        self._deadzone_right = 8689   # XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE
        self._trigger_threshold = 30  # XINPUT_GAMEPAD_TRIGGER_THRESHOLD

    def scan_for_controller(self):
        """Find first connected XInput controller port."""
        for port in range(4):
            state = XINPUT_STATE()
            result = self.xinput.XInputGetState(port, ctypes.byref(state))
            if result == 0:  # ERROR_SUCCESS
                self.active_port = port
                return True
        self.active_port = -1
        return False

    def get_state(self):
        """
        Returns dict with all controller values, or None if disconnected.
        All stick values normalized to -1.0 -> 1.0
        Triggers normalized to 0.0 -> 1.0
        """
        if self.active_port == -1:
            return None

        result = self.xinput.XInputGetState(
            self.active_port, ctypes.byref(self.state)
        )
        if result != 0:
            self.active_port = -1
            return None

        gp = self.state.Gamepad
        return {
            "buttons":  gp.wButtons,
            "lt":       gp.bLeftTrigger  / 255.0,
            "rt":       gp.bRightTrigger / 255.0,
            "lx":       self._normalize_stick(gp.sThumbLX, self._deadzone_left),
            "ly":       self._normalize_stick(gp.sThumbLY, self._deadzone_left),
            "rx":       self._normalize_stick(gp.sThumbRX, self._deadzone_right),
            "ry":       self._normalize_stick(gp.sThumbRY, self._deadzone_right),
        }

    def _normalize_stick(self, raw, deadzone):
        """Normalize raw XInput SHORT value with deadzone to -1.0 -> 1.0"""
        if abs(raw) < deadzone:
            return 0.0
        if raw > 0:
            return min(1.0, (raw - deadzone) / (32767.0 - deadzone))
        else:
            return max(-1.0, (raw + deadzone) / (32768.0 - deadzone))

    def is_button_pressed(self, state, button_name):
        if state is None:
            return False
        mask = XINPUT_BUTTONS.get(button_name, 0)
        return bool(state["buttons"] & mask)

# ============================================================
#   VIRTUAL CONTROLLER ASSISTANT - FULL REWRITE
# ============================================================
class VirtualControllerAssistant:

    POLL_RATE_HZ   = 500           # Input polling rate
    POLL_INTERVAL  = 1.0 / 500     # Seconds per poll cycle

    def __init__(self):
        # --- State ---
        self.running          = True
        self.controller_found = False
        self.port_label       = "None"

        # --- XInput Engine (bypasses HidHide) ---
        self.xinput = XInputEngine()

        # --- Virtual Gamepad ---
        try:
            self.vpad        = vg.VX360Gamepad()
            self.vpad_status = "Active"
        except Exception:
            self.vpad        = None
            self.vpad_status = "ViGEmBus Driver Missing"

        # --- Shoot Timing State ---
        self._rs_down_time  = 0.0
        self._rs_tracking   = False
        self._last_ry       = 0.0

        # --- GUI Variables ---
        self.shooting_assist     = tk.BooleanVar(value=True)
        self.dribble_assist      = tk.BooleanVar(value=True)
        self.defense_assist      = tk.BooleanVar(value=True)
        self.auto_combo          = tk.BooleanVar(value=False)
        self.tempo_release       = tk.DoubleVar(value=0.45)
        self.dribble_speed       = tk.DoubleVar(value=1.0)
        self.defense_intensity   = tk.DoubleVar(value=0.8)
        self.sensitivity_var     = tk.DoubleVar(value=1.1)
        self.curve_var           = tk.DoubleVar(value=1.4)

        # --- Build GUI ---
        self.root = tk.Tk()
        self.root.title("2K Virtual Controller Assistant")
        self.root.geometry("580x780")
        self.root.configure(bg="#0a0b0d")
        self.root.resizable(False, False)

        self._build_gui()
        self._bind_hotkeys()

        # --- Start Input Thread ---
        self._input_thread = threading.Thread(
            target=self._input_loop, daemon=True
        )
        self._input_thread.start()

        self.root.protocol("WM_DELETE_WINDOW", self._on_close)
        self.root.mainloop()

    # ==========================================================
    #   GUI CONSTRUCTION
    # ==========================================================
    def _build_gui(self):
        style = ttk.Style()
        style.theme_use("clam")
        style.configure("TFrame",      background="#0a0b0d")
        style.configure("TLabel",      background="#0a0b0d", foreground="#ffffff",
                        font=("Segoe UI", 10))
        style.configure("TCheckbutton",background="#0a0b0d", foreground="#ffffff",
                        font=("Segoe UI", 10))
        style.map("TCheckbutton",
                  background=[("active", "#0a0b0d")],
                  foreground=[("active", "#00d2ff")])
        style.configure("Horizontal.TScale",
                        background="#0a0b0d",
                        troughcolor="#1a1c23",
                        slidercolor="#00d2ff")

        # ---- HEADER ----
        hdr = tk.Frame(self.root, bg="#0a0b0d")
        hdr.pack(fill="x", padx=25, pady=18)

        tk.Label(hdr, text="2K VIRTUAL CONTROLLER",
                 font=("Segoe UI", 16, "bold"),
                 fg="#00d2ff", bg="#0a0b0d").pack(side="left")

        self._anim_canvas = tk.Canvas(hdr, width=14, height=14,
                                      bg="#0a0b0d", highlightthickness=0)
        self._anim_canvas.pack(side="right", padx=(6, 0))
        self._dot = self._anim_canvas.create_oval(2, 2, 12, 12,
                                                   fill="#ff3b30", outline="")

        self._status_lbl = tk.Label(hdr, text="SCANNING...",
                                    font=("Segoe UI", 9, "bold"),
                                    fg="#ff3b30", bg="#0a0b0d")
        self._status_lbl.pack(side="right")

        # ---- MAIN SCROLL CONTAINER ----
        container = tk.Frame(self.root, bg="#0a0b0d")
        container.pack(fill="both", expand=True, padx=25, pady=5)

        # ---- ASSIST MODULES ----
        self._section(container, "ASSIST MODULES")
        mod = tk.Frame(container, bg="#0a0b0d")
        mod.pack(fill="x", pady=8)

        checks = [
            ("Tempo Shooting Assist  [F1]", self.shooting_assist),
            ("Dribble Combo Engine   [F2]", self.dribble_assist),
            ("Lateral Defense Assist [F3]", self.defense_assist),
            ("Macro Auto-Combo Chain",      self.auto_combo),
        ]
        for txt, var in checks:
            ttk.Checkbutton(mod, text=txt, variable=var).pack(anchor="w", pady=5)

        # ---- TUNING ----
        self._section(container, "TUNING CONTROLS")
        tun = tk.Frame(container, bg="#0a0b0d")
        tun.pack(fill="x", pady=8)

        sliders = [
            ("Tempo Shot Release Window (sec)",   self.tempo_release,     0.20, 0.80),
            ("Dribble Scale Factor",              self.dribble_speed,     0.50, 1.50),
            ("Defense Stick Response",            self.defense_intensity, 0.50, 1.50),
            ("Stick Sensitivity Multiplier",      self.sensitivity_var,   0.80, 2.00),
            ("Stick Response Curve Exponent",     self.curve_var,         0.80, 2.50),
        ]
        for lbl_txt, var, lo, hi in sliders:
            tk.Label(tun, text=lbl_txt,
                     bg="#0a0b0d", fg="#a0a5b5",
                     font=("Segoe UI", 9)).pack(anchor="w")
            row = tk.Frame(tun, bg="#0a0b0d")
            row.pack(fill="x", pady=(2, 10))
            ttk.Scale(row, from_=lo, to=hi, orient="horizontal",
                      variable=var,
                      style="Horizontal.TScale").pack(side="left", fill="x",
                                                      expand=True)
            val_lbl = tk.Label(row, textvariable=var, width=5,
                               bg="#0a0b0d", fg="#00d2ff",
                               font=("Segoe UI", 9))
            val_lbl.pack(side="right")

        # ---- HARDWARE MATRIX ----
        self._section(container, "HARDWARE MATRIX")
        matrix = tk.Frame(container, bg="#111318", bd=1, relief="flat")
        matrix.pack(fill="x", pady=10, ipady=8)

        self._lbl_xinput = tk.Label(
            matrix,
            text="XInput Engine: Scanning ports 0-3...",
            bg="#111318", fg="#ffffff", font=("Segoe UI", 9)
        )
        self._lbl_xinput.pack(anchor="w", padx=15, pady=3)

        self._lbl_hidhide = tk.Label(
            matrix,
            text="HidHide Bypass: XInput API (kernel-level, always active)",
            bg="#111318", fg="#00ff66", font=("Segoe UI", 9)
        )
        self._lbl_hidhide.pack(anchor="w", padx=15, pady=3)

        self._lbl_vpad = tk.Label(
            matrix,
            text=f"ViGEmBus Virtual Stack: {self.vpad_status}",
            bg="#111318", fg="#ffffff", font=("Segoe UI", 9)
        )
        self._lbl_vpad.pack(anchor="w", padx=15, pady=3)

        self._lbl_poll = tk.Label(
            matrix,
            text=f"Poll Rate: {self.POLL_RATE_HZ} Hz",
            bg="#111318", fg="#a0a5b5", font=("Segoe UI", 9)
        )
        self._lbl_poll.pack(anchor="w", padx=15, pady=3)

        # ---- LIVE STICK VISUALIZER ----
        self._section(container, "LIVE STICK MONITOR")
        vis = tk.Frame(container, bg="#111318", bd=1, relief="flat")
        vis.pack(fill="x", pady=10, ipady=8)

        stick_row = tk.Frame(vis, bg="#111318")
        stick_row.pack(padx=15, pady=5)

        self._ls_canvas = self._make_stick_canvas(stick_row, "L-STICK")
        tk.Frame(stick_row, bg="#111318", width=30).pack(side="left")
        self._rs_canvas = self._make_stick_canvas(stick_row, "R-STICK")

        # ---- FOOTER ----
        footer = tk.Frame(self.root, bg="#0a0b0d")
        footer.pack(fill="x", side="bottom", padx=25, pady=12)
        tk.Label(footer, text="F4 - Emergency Kill All Assists",
                 bg="#0a0b0d", fg="#ff3b30",
                 font=("Segoe UI", 9, "bold")).pack(side="left")
        tk.Label(footer, text="v3.0.0-XInputBypass",
                 bg="#0a0b0d", fg="#4a4d5a",
                 font=("Segoe UI", 9)).pack(side="right")

        self._animate_status()

    def _make_stick_canvas(self, parent, label):
        frame = tk.Frame(parent, bg="#111318")
        frame.pack(side="left")
        tk.Label(frame, text=label, bg="#111318", fg="#a0a5b5",
                 font=("Segoe UI", 8)).pack()
        c = tk.Canvas(frame, width=80, height=80,
                      bg="#1a1c23", highlightthickness=1,
                      highlightbackground="#2a2d3a")
        c.pack()
        # Background crosshair
        c.create_line(40, 0, 40, 80, fill="#2a2d3a")
        c.create_line(0, 40, 80, 40, fill="#2a2d3a")
        c.create_oval(5, 5, 75, 75, outline="#2a2d3a", fill="")
        # Dot
        c._dot = c.create_oval(36, 36, 44, 44, fill="#00d2ff", outline="")
        return c

    def _update_stick_visual(self, canvas, x_norm, y_norm):
        """x_norm, y_norm in -1.0 -> 1.0"""
        cx = 40 + x_norm * 34
        cy = 40 - y_norm * 34
        canvas.coords(canvas._dot, cx - 4, cy - 4, cx + 4, cy + 4)

    def _section(self, parent, text):
        f = tk.Frame(parent, bg="#0a0b0d")
        f.pack(fill="x", pady=(14, 2))
        tk.Label(f, text=text, font=("Segoe UI", 8, "bold"),
                 fg="#00d2ff", bg="#0a0b0d").pack(side="left")
        tk.Frame(f, bg="#1a1c23", height=1).pack(
            side="left", fill="x", expand=True, padx=(10, 0), pady=5
        )

    def _bind_hotkeys(self):
        self.root.bind("<F1>", lambda e: self.shooting_assist.set(
            not self.shooting_assist.get()))
        self.root.bind("<F2>", lambda e: self.dribble_assist.set(
            not self.dribble_assist.get()))
        self.root.bind("<F3>", lambda e: self.defense_assist.set(
            not self.defense_assist.get()))
        self.root.bind("<F4>", lambda e: self._emergency_kill())

    def _emergency_kill(self):
        self.shooting_assist.set(False)
        self.dribble_assist.set(False)
        self.defense_assist.set(False)
        self.auto_combo.set(False)
        if self.vpad:
            self.vpad.reset()
            self.vpad.update()

    def _animate_status(self):
        if not self.running:
            return
        cur = self._anim_canvas.itemcget(self._dot, "fill")
        if self.controller_found and self.vpad_status == "Active":
            self._status_lbl.config(text="SYSTEM OPERATIONAL", fg="#00ff66")
            nxt = "#00ff66" if cur != "#00ff66" else "#004d1f"
        else:
            self._status_lbl.config(text="NO CONTROLLER DETECTED", fg="#ff3b30")
            nxt = "#ff3b30" if cur != "#ff3b30" else "#4d0f0f"
        self._anim_canvas.itemconfig(self._dot, fill=nxt)
        self.root.after(500, self._animate_status)

    # ==========================================================
    #   STICK PROCESSING
    # ==========================================================
    def _process_stick(self, val):
        """
        XInput engine already applies deadzone in normalization.
        This adds sensitivity curve on top.
        """
        if val == 0.0:
            return 0.0
        sign = 1.0 if val > 0 else -1.0
        curved = pow(abs(val), self.curve_var.get()) * self.sensitivity_var.get()
        return max(-1.0, min(1.0, sign * curved))

    # ==========================================================
    #   INPUT LOOP  (runs on background thread, 500 Hz)
    # ==========================================================
    def _input_loop(self):
        last_scan  = 0.0
        scan_every = 2.0   # Re-scan for controller every 2 seconds

        while self.running:
            t_start = time.perf_counter()

            # --- Controller discovery ---
            now = time.perf_counter()
            if not self.controller_found or (now - last_scan) > scan_every:
                if self.xinput.scan_for_controller():
                    self.controller_found = True
                    port = self.xinput.active_port
                    self._safe_gui(
                        self._lbl_xinput,
                        f"XInput Engine: Controller on Port {port} "
                        f"[XInput direct bypass ACTIVE]"
                    )
                else:
                    self.controller_found = False
                    self._safe_gui(
                        self._lbl_xinput,
                        "XInput Engine: No controller found (ports 0-3)"
                    )
                last_scan = now

            if not self.controller_found:
                if self.vpad:
                    self.vpad.reset()
                    self.vpad.update()
                time.sleep(0.5)
                continue

            if not self.vpad:
                time.sleep(0.1)
                continue

            # --- Read state ---
            state = self.xinput.get_state()
            if state is None:
                self.controller_found = False
                continue

            gp = state  # shorthand

            # ---- BUTTONS ----
            btn_map = {
                "A":              vg.XUSB_BUTTON.XUSB_GAMEPAD_A,
                "B":              vg.XUSB_BUTTON.XUSB_GAMEPAD_B,
                "X":              vg.XUSB_BUTTON.XUSB_GAMEPAD_X,
                "Y":              vg.XUSB_BUTTON.XUSB_GAMEPAD_Y,
                "LEFT_SHOULDER":  vg.XUSB_BUTTON.XUSB_GAMEPAD_LEFT_SHOULDER,
                "RIGHT_SHOULDER": vg.XUSB_BUTTON.XUSB_GAMEPAD_RIGHT_SHOULDER,
                "BACK":           vg.XUSB_BUTTON.XUSB_GAMEPAD_BACK,
                "START":          vg.XUSB_BUTTON.XUSB_GAMEPAD_START,
                "LEFT_THUMB":     vg.XUSB_BUTTON.XUSB_GAMEPAD_LEFT_THUMB,
                "RIGHT_THUMB":    vg.XUSB_BUTTON.XUSB_GAMEPAD_RIGHT_THUMB,
                "DPAD_UP":        vg.XUSB_BUTTON.XUSB_GAMEPAD_DPAD_UP,
                "DPAD_DOWN":      vg.XUSB_BUTTON.XUSB_GAMEPAD_DPAD_DOWN,
                "DPAD_LEFT":      vg.XUSB_BUTTON.XUSB_GAMEPAD_DPAD_LEFT,
                "DPAD_RIGHT":     vg.XUSB_BUTTON.XUSB_GAMEPAD_DPAD_RIGHT,
            }
            for name, vbtn in btn_map.items():
                if self.xinput.is_button_pressed(gp, name):
                    self.vpad.press_button(vbtn)
                else:
                    self.vpad.release_button(vbtn)

            # ---- TRIGGERS ----
            lt_raw = gp["lt"]
            rt_raw = gp["rt"]
            self.vpad.left_trigger( value=int(lt_raw * 255))
            self.vpad.right_trigger(value=int(rt_raw * 255))

            # ---- STICKS - raw normalized values ----
            lx = self._process_stick(gp["lx"])
            ly = self._process_stick(gp["ly"])
            rx = self._process_stick(gp["rx"])
            ry = self._process_stick(gp["ry"])

            # ---- ASSIST: DEFENSE ----
            # Scales left stick when LB is held
            if self.defense_assist.get() and \
               self.xinput.is_button_pressed(gp, "LEFT_SHOULDER"):
                scale = self.defense_intensity.get()
                lx = max(-1.0, min(1.0, lx * scale))
                ly = max(-1.0, min(1.0, ly * scale))

            # ---- ASSIST: AUTO DRIBBLE COMBO ----
            # When left stick is pushed hard sideways, nudge right stick
            if self.dribble_assist.get() and self.auto_combo.get():
                if abs(lx) > 0.7:
                    nudge = 0.3 * self.dribble_speed.get()
                    direction = 1.0 if lx > 0 else -1.0
                    rx = max(-1.0, min(1.0, rx + nudge * direction))

            # ---- ASSIST: SHOOTING TEMPO ----
            # Detects downward pull on right stick then applies
            # timed release window delay for green window consistency
            if self.shooting_assist.get():
                if ry > 0.7 and self._last_ry <= 0.7:
                    self._rs_down_time = time.perf_counter()
                    self._rs_tracking  = True

                if self._rs_tracking and ry < -0.4 and self._last_ry >= -0.4:
                    elapsed = time.perf_counter() - self._rs_down_time
                    delay   = self.tempo_release.get()
                    if elapsed < delay:
                        time.sleep(delay - elapsed)
                    ry = 0.0
                    rx = 0.0
                    self._rs_tracking = False

                self._last_ry = ry

            # ---- WRITE TO VIRTUAL PAD ----
            self.vpad.left_joystick(
                x_value=int(lx  * 32767),
                y_value=int(ly  * 32767)   # XInput Y is already correct axis
            )
            self.vpad.right_joystick(
                x_value=int(rx  * 32767),
                y_value=int(ry  * 32767)
            )
            self.vpad.update()

            # ---- UPDATE STICK VISUALIZER (throttled to ~30fps) ----
            if int(time.perf_counter() * 30) % 1 == 0:
                self.root.after(0, self._update_stick_visual,
                                self._ls_canvas, lx, ly)
                self.root.after(0, self._update_stick_visual,
                                self._rs_canvas, rx, ry)

            # ---- PRECISE TIMING ----
            elapsed = time.perf_counter() - t_start
            sleep_t = self.POLL_INTERVAL - elapsed
            if sleep_t > 0:
                time.sleep(sleep_t)

    # ==========================================================
    #   THREAD-SAFE GUI UPDATE
    # ==========================================================
    def _safe_gui(self, widget, text):
        try:
            self.root.after(0, widget.config, {"text": text})
        except Exception:
            pass

    # ==========================================================
    #   CLEAN SHUTDOWN
    # ==========================================================
    def _on_close(self):
        self.running = False
        if self.vpad:
            self.vpad.reset()
            self.vpad.update()
        self.root.destroy()


# ============================================================
#   ENTRY POINT
# ============================================================
if __name__ == "__main__":
    app = VirtualControllerAssistant()
← Back to timeline