Scripts for automatic pause upon controller disconnect
-
(This may be helpful for PC players like me who use Bluetooth controllers that like to disconnect randomly, also looking for feedback from anyone who might know how to achieve this effect with lower latency)
This should work with Windows 10 and 11.
-Open config file for game of choice and set key P bind to "pause"
-PowerShell code that achieves this effect:Add-Type -TypeDefinition @" using System; using System.Runtime.InteropServices; public class XInput { [DllImport("XInput1_4.dll", EntryPoint="XInputGetState")] public static extern int XInputGetState(int dwUserIndex, out XINPUT_STATE pState); } [StructLayout(LayoutKind.Sequential)] public struct XINPUT_STATE { public int dwPacketNumber; public XINPUT_GAMEPAD Gamepad; } [StructLayout(LayoutKind.Sequential)] public struct XINPUT_GAMEPAD { public short wButtons; public byte bLeftTrigger; public byte bRightTrigger; public short sThumbLX; public short sThumbLY; public short sThumbRX; public short sThumbRY; } "@ function Send-KeyPress { param ($key) Add-Type -TypeDefinition @" using System; using System.Runtime.InteropServices; public class Keyboard { [DllImport("user32.dll")] public static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, uint dwExtraInfo); } "@ $VK_P = 0x50 [Keyboard]::keybd_event($VK_P, 0, 0, 0) # Press "P" Start-Sleep -Milliseconds 50 # Small delay before releasing [Keyboard]::keybd_event($VK_P, 0, 2, 0) # Release "P" } $global:isConnected = $true Write-Host "Monitoring Xbox Controller... Press Ctrl+C to exit." try { while ($true) { $state = New-Object XINPUT_STATE $result = [XInput]::XInputGetState(0, [ref]$state) if ($result -eq 0) { if (-not $global:isConnected) { $global:isConnected = $true } } else { if ($global:isConnected) { $global:isConnected = $false Send-KeyPress -key "P" Write-Host "Controller disconnected - Sent 'P' key press!" } } Start-Sleep -Milliseconds 16 # Polls ~60 times per second } } catch { Write-Host "Script terminated." }
-Ctrl+C to exit or kill shell
Alternative using AutoHotKey 2.0.19 (runs in background):
-Download AutoHotKey (dot com)
-Create ControllerMonitor.ahk containing following text:#Requires AutoHotkey v2.0 #SingleInstance Force ; Include the XInput library #include XInput.ahk global isConnected := false SetTimer(CheckController, 16) ; 60 times per second (16ms interval) ; Define the hotkey to exit the script #!x:: ExitApp ; Terminates the script return CheckController() { global isConnected state := Buffer(16, 0) if (XInput_GetState(0, state) == 0) { ; 0 means connected if (!isConnected) { isConnected := true } } else { if (isConnected) { isConnected := false Send("p") } } }
-Win+Alt+X to terminate script when done playing
-Of course you can change Send("p") or #!x:: to anything you like-Create in same folder XInput.ahk (save file type as "All Files") containing following text:
; XInput.ahk - XInput wrapper for AutoHotkey v2 DllCall("LoadLibrary", "Str", "XInput1_4.dll") XInput_GetState(controllerIndex, state) { return DllCall("XInput1_4\XInputGetState", "UInt", controllerIndex, "Ptr", state.Ptr, "UInt") }
-Run ControllerMonitor.ahk and terminate with Win+Alt+X when done playing
Unfortunately, it takes roughly a second to register despite a high polling frequently. I tried looking for ways around this accessing log files from Event Viewer but had no success. Most of my issues doing it by other methods come from Windows 11 being so adamant that Bluetooth devices always appear connected.
If anyone sees this who is part of the high round zombies community, I would love to know if this would be an accepted method of preventing losing a game by hardware issues, or if this would be considered cheating with a macro. Specifically considering first room games on BO1 personally (and yea I know not to use plutonium for BO1).
Inb4 "just press ESC" igi
-
fixed ControllerMonitor.ahk:
#Requires AutoHotkey v2.0 #SingleInstance Force ; Include the XInput library #include XInput.ahk global isConnected := false SetTimer(CheckController, 16) ; 60 times per second (16ms interval) ; Define the hotkey to exit the script #!x::ExitApp ; Terminates the script CheckController() { global isConnected ; Explicitly declare the global variable state := Buffer(16, 0) ; Ensure the buffer is correctly allocated if (XInput_GetState(0, state) == 0) { ; 0 means connected if (!isConnected) { isConnected := true } } else { if (isConnected) { isConnected := false Send("p") ; Send 'p' on disconnection } } }