Hi everybody
This is a collection of scripts I wrote a few years ago that are based on the Xinput lib Lexikos wrote. I would like to point out that I wrote these when I was pretty fresh to AHK and haven't yet finished the apps, but the core functionality is there and surprisingly smooth. I am posting them here at the request of another AHK user, and since my free time has been relativity non existent lately I figured I'd put it up here and see if anyone wants to modify or play with it.
As for the scripts, there are four that make up the solution, this was done to increase responsiveness as the solution was designed with 3D adventure/MMO games on a netbooks in mind so responsiveness was priority one here. Running multiple processes ended up being the solution at the time.
CURRENT FAQ:
http://www.autohotkey.net/~jamixzol/Xmount_a0.01_FAQ-Version%20Notes.txt
SCRIPTS:
joytest - main gui and button mappings(unfinished)
Joy to WASD - joystick functionality related to character movement "WASD" keys
Joy to mouse - joystick functionality for moving the mouse
WowRumble - geared towards WoW, this is intended to give a rumble heartbeat based on low health in varied degrees(unfinished)
TESTED ENVIRONMENTS:
NOTE: Tested to work with World of Warcraft on the current patch as of this post
Working:
Windows XP SP2 32bit
Windows XP SP3 32bit
Not Working:
Windows XP SP2 64bit
Unknown:
All other windows builds/versions
REQUIRED SOFT/HARDWARE:
Hardware:
Xbox 360 Controller for Windows(tested with drivers in link for winXP32) the wireless counterpart should also work with the wireless adapter
Software:
Controller driver used
http://www.microsoft.com/hardware/en-us/p/xbox-360-controller-for-windows#support
REQUIRED FILES:
GUI images
DEFAULT.ini (currently manual modification is needed to set mappings)
xinput1_3.dll
Xinput.ahk and JSON.ahk (or the modified lib in the zip)
any combination of or all the scripts/exe in the zip
ZIP FILE:
http://www.autohotkey.net/~jamixzol/XMOUNT%20Va0.01.zip
SOURCE CODE:
Tested on Version v1.1.01.00 of AutoHotkey_L
MAIN GUI(joytest.ahk)
Code:
#Singleinstance force
#NoEnv
#UseHook
#InstallMouseHook
#InstallKeybdHook
SendMode Play
setmousedelay, -1
setbatchlines, -1
LeftToggle = UP
lockclick = 1
lockright = 0
TESTRIGHT = RIGHT
TESTLEFT = LEFT
MOUSEAXISX = R
MOUSEAXISY = u
MOUSEAXISR = Y
MOUSEAXISU = x
JOYMOUSE = R
JOYCHAR = L
Threshold = 64
Sleep 1000
; Increase the following value to make the mouse cursor move faster:
JoyMultiplier = 1.70
; Decrease the following value to require less joystick displacement-from-center
; to start moving the mouse. However, you may need to calibrate your joystick
; -- ensuring it's properly centered -- to avoid cursor drift. A perfectly tight
; and centered joystick could use a value of 1:
JoyThresholdL = 25
JoyThresholdR = 25
; Change the following to true to invert the Y-axis, which causes the mouse to
; move vertically in the direction opposite the stick:
InvertYAxis := false
; Change these values to use joystick button numbers other than 1, 2, and 3 for
; the left, right, and middle mouse buttons. Available numbers are 1 through 32.
; Use the Joystick Test Script to find out your joystick's numbers more easily.
ButtonLeft = 5 ;LB
ButtonRight = 6 ;RB
ButtonMiddle = 32 ;Null
ButtonY = 4
ButtonX = 3
ButtonB = 2
ButtonA = 1
ButtonBack = 7
ButtonStart = 8
ButtonL3 = 9
ButtonR3 = 10
; If your joystick has a POV control, you can use it as a mouse wheel. The
; following value is the number of milliseconds between turns of the wheel.
; Decrease it to have the wheel turn faster:
WheelDelay = 150
; If your system has more than one joystick, increase this value to use a joystick
; other than the first:
JoystickNumber = 1
; END OF CONFIG SECTION -- Don't change anything below this point unless you want
; to alter the basic nature of the script.
JoystickPrefix = %JoystickNumber%Joy
Hotkey, %JoystickPrefix%%ButtonLeft%, ButtonLeft
Hotkey, %JoystickPrefix%%ButtonRight%, ButtonRight
Hotkey, %JoystickPrefix%%ButtonMiddle%, ButtonMiddle
; Calculate the axis displacements that are needed to start moving the cursor:
;X Axix
JoyThresholdUpperLX := 50 + JoyThresholdL
JoyThresholdLowerLX := 50 - JoyThresholdL
JoyThresholdUpperRX := 50 + JoyThresholdR
JoyThresholdLowerRX := 50 - JoyThresholdR
;Y Axix
JoyThresholdUpperLY := 50 + JoyThresholdL
JoyThresholdLowerLY := 50 - JoyThresholdL
JoyThresholdUpperRY := 50 + JoyThresholdR
JoyThresholdLowerRY := 50 - JoyThresholdR
if InvertYAxis
YAxisMultiplier = -1
else
YAxisMultiplier = 1
;SetTimer, WatchJoystick, 1 ; Monitor the movement of the joystick.
SetTimer, WatchJoysticklogic, 1
;SetTimer, CharWatch, 1 ; Monitor the movement of the joystick.
GetKeyState, JoyInfo, %JoystickNumber%JoyInfo
;IfInString, JoyInfo, P ; Joystick has POV control, so use it as a mouse wheel.
SetTimer, MouseWheel, %WheelDelay%
TIMER := 300
#include xinput.ahk
#INCLUDE GUI.ahk
run, joy to wasd.exe
run, joy to mouse.exe
run, wowrumble.exe
return ; End of auto-execute section.
; The subroutines below do not use KeyWait because that would sometimes trap the
; WatchJoystick quasi-thread beneath the wait-for-button-up thread, which would
; effectively prevent mouse-dragging with the joystick.
TRIGGERSTATE:
; Keys to bind to triggers.
LT_Key = Null
RT_Key = Null
; ~
LastRT := LastLT := 0
XInput_Init()
Loop, 4 {
if XInput_GetState(A_Index-1, State)=0 {
LT := json(State,"bLeftTrigger") >= Threshold
RT := json(State,"bRightTrigger") >= Threshold
}
}
return
TRIGGERWATCH:
;JoyFrom
gosub TRIGGERSTATE
if (LT = 1 and RT = 1) ;Both triggers are held
AVAR%JoyFrom% := %JoyFrom%4
if (LT = 0 and RT = 0) ;No triggers are held
AVAR%JoyFrom% := %JoyFrom%1
if (LT = 1 and RT = 0) ;Left trigger is held
AVAR%JoyFrom% := %JoyFrom%2
if (LT = 0 and RT = 1) ;Right trigger is held
AVAR%JoyFrom% := %JoyFrom%3
If TIMER = 9
TIMER = 9
else
TIMER := (TIMER - 97)
StringReplace, TIMER, TIMER, -, , A
return
;Y
Joy4::
joyfrom = Joy4
gosub TRIGGERWATCH
Send {%AVARJoy4% down}
SetTimer, WaitForButtonUpJoy4, %TIMER%
return
WaitForButtonUpJoy4:
if Not GetKeyState("Joy4") ; The button is still, down, so keep waiting.
{
Send {%AVARJoy4% up} ; Release the left mouse button.
SetTimer, WaitForButtonUpJoy4, off
TIMER := 300
return
}
gosub TRIGGERWATCH
Send {%AVARJoy4% down}
SetTimer, WaitForButtonUpJoy4, %TIMER%
return
;B
Joy2::
joyfrom = Joy3
gosub TRIGGERWATCH
Send {%AVARJoy3% down}
SetTimer, WaitForButtonUpJoy3, %TIMER%
return
WaitForButtonUpJoy3:
if not GetKeyState("Joy3") ; The button has been released.
{
Send {%AVARJoy3% up} ; Release the spacebar.
SetTimer, WaitForButtonUpJoy3, off ; Stop monitoring the button.
TIMER := 300
return
}
gosub TRIGGERWATCH
Send {%AVARJoy3% down} ; Send another keystroke.
SetTimer, WaitForButtonUpJoy3, %TIMER%
return
;x
Joy3::
joyfrom = Joy2
gosub TRIGGERWATCH
Send {%AVARJoy2% down}
SetTimer, WaitForButtonUpJoy2, %TIMER%
return
WaitForButtonUpJoy2:
if not GetKeyState("Joy2") ; The button has been released.
{
Send {%AVARJoy2% up} ; Release the spacebar.
SetTimer, WaitForButtonUpJoy2, off ; Stop monitoring the button.
TIMER := 300
return
}
gosub TRIGGERWATCH
Send {%AVARJoy2% down} ; Send another keystroke.
SetTimer, WaitForButtonUpJoy2, %TIMER%
return
;A
Joy1::
joyfrom = Joy1
gosub TRIGGERWATCH
Send {%AVARJoy1% down}
SetTimer, WaitForButtonUpJoy1, %TIMER%
return
WaitForButtonUpJoy1:
if not GetKeyState("Joy1") ; The button has been released.
{
Send {%AVARJoy1% up} ; Release the spacebar.
SetTimer, WaitForButtonUpjoy1, off ; Stop monitoring the button.
TIMER := 300
return
}
gosub TRIGGERWATCH
Send {%AVARJoy1% down} ; Send another keystroke.
SetTimer, WaitForButtonUpJoy1, %TIMER%
return
;Back
Joy7::
joyfrom = Joy7
gosub TRIGGERWATCH
Send {%AVARJoy7% down}
SetTimer, WaitForButtonUpJoy7, %TIMER%
return
WaitForButtonUpJoy7:
if not GetKeyState("Joy7") ; The button has been released.
{
Send {%AVARJoy7% up} ; Release the spacebar.
SetTimer, WaitForButtonUpjoy7, off ; Stop monitoring the button.
TIMER := 300
return
}
gosub TRIGGERWATCH
Send {%AVARJoy7% down} ; Send another keystroke.
SetTimer, WaitForButtonUpJoy7, %TIMER%
return
;Start
Joy8::
joyfrom = Joy8
if (LT = 1 and RT = 1) ;Both triggers are held
{
sendplay ^aUserName@Email.com`t
sleep 100
clipboard := "Password"
sendplay ^v
}
if (LT = 0 and RT = 0) ;No triggers are held
AVAR%JoyFrom% := %JoyFrom%1
if (LT = 1 and RT = 0) ;Left trigger is held
AVAR%JoyFrom% := %JoyFrom%2
if (LT = 0 and RT = 1) ;Right trigger is held
AVAR%JoyFrom% := %JoyFrom%3
If TIMER = 9
TIMER = 9
else
TIMER := (TIMER - 97)
StringReplace, TIMER, TIMER, -, , A
Send {%AVARJoy8% down}
SetTimer, WaitForButtonUpJoy8, %TIMER%
return
WaitForButtonUpJoy8:
if not GetKeyState("Joy8") ; The button has been released.
{
Send {%AVARJoy8% up} ; Release the spacebar.
SetTimer, WaitForButtonUpjoy8, off ; Stop monitoring the button.
TIMER := 300
return
}
gosub TRIGGERWATCH
Send {%AVARJoy8% down} ; Send another keystroke.
SetTimer, WaitForButtonUpJoy8, %TIMER%
return
;L3
Joy9::
joyfrom = Joy9
gosub TRIGGERWATCH
Send {%AVARJoy9% down}
SetTimer, WaitForButtonUpJoy9, %TIMER%
return
WaitForButtonUpJoy9:
if not GetKeyState("Joy9") ; The button has been released.
{
Send {%AVARJoy9% up} ; Release the spacebar.
SetTimer, WaitForButtonUpjoy9, off ; Stop monitoring the button.
TIMER := 300
return
}
gosub TRIGGERWATCH
Send {%AVARJoy9% down} ; Send another keystroke.
SetTimer, WaitForButtonUpJoy9, %TIMER%
return
;R3
Joy10::
joyfrom = Joy10
gosub TRIGGERWATCH
Send {%AVARJoy10% down}
SetTimer, WaitForButtonUpJoy10, %TIMER%
return
WaitForButtonUpJoy10:
if not GetKeyState("Joy10") ; The button has been released.
{
Send {%AVARJoy10% up} ; Release the spacebar.
SetTimer, WaitForButtonUpjoy10, off ; Stop monitoring the button.
TIMER := 300
return
}
gosub TRIGGERWATCH
Send {%AVARJoy10% down} ; Send another keystroke.
SetTimer, WaitForButtonUpJoy10, %TIMER%
return
ButtonLeft:
SetMouseDelay, -1 ; Makes movement smoother.
SENDINPUT {CLICK DOWN}
;MouseClick, left,,, 1, 0, D ; Hold down the left mouse button.
SetTimer, WaitForLeftButtonUp, 10
return
ButtonRight:
SetMouseDelay, -1 ; Makes movement smoother.
if lockclick = 1
{
If lockright = 0
{
MouseClick, right,,, 1, 0, D ; Hold down the right mouse button.
lockright = 1
return
}
else
{
MouseClick, right,,, 1, 0, U ; Hold down the right mouse button.
lockright = 0
return
}
}
else
{
MouseClick, right,,, 1, 0, D ; Hold down the right mouse button.
SetTimer, WaitForRightButtonUp, 10
}
return
ButtonMiddle:
SetMouseDelay, -1 ; Makes movement smoother.
MouseClick, middle,,, 1, 0, D ; Hold down the right mouse button.
SetTimer, WaitForMiddleButtonUp, 10
return
WaitForLeftButtonUp:
if GetKeyState(JoystickPrefix . ButtonLeft)
return ; The button is still, down, so keep waiting.
; Otherwise, the button has been released.
SetTimer, WaitForLeftButtonUp, off
SetMouseDelay, -1 ; Makes movement smoother.
SENDINPUT {CLICK UP}
;MouseClick, left,,, 1, 0, U ; Release the mouse button.
return
WaitForRightButtonUp:
if GetKeyState(JoystickPrefix . ButtonRight)
return ; The button is still, down, so keep waiting.
; Otherwise, the button has been released.
SetTimer, WaitForRightButtonUp, off
MouseClick, right,,, 1, 0, U ; Release the mouse button.
return
WaitForMiddleButtonUp:
if GetKeyState(JoystickPrefix . ButtonMiddle)
return ; The button is still, down, so keep waiting.
; Otherwise, the button has been released.
SetTimer, WaitForMiddleButtonUp, off
MouseClick, middle,,, 1, 0, U ; Release the mouse button.
return
!^w::
reload
return
WatchJoysticklogic:
SetControlDelay, -1
XInput_Init()
Loop, 4 {
if XInput_GetState(A_Index-1, State)=0 {
LTRAW := json(State,"bLeftTrigger")
RTRAW := json(State,"bRightTrigger")
}
}
GuiControl, , LTProg, %LTRAW%
GuiControl, , RTProg, %RTRAW%
GuiControl, , JOYRProg, %JOYR%
GuiControl, , JOYYProg, %JOYY%
GuiControl, , JOYUProg, %JOYU%
GuiControl, , JOYXProg, %JOYX%
;tooltip %DeltaR%%DeltaU%`n`n`nTIMER%TIMER%`nPOV %JoyPOV%`n LT %LTRAW% RT %RTRAW%`n lockright %lockright%`n`nLX%LX% LY%LY% RX%RX% RY%RY%`n`njoyx%joyx% Joyy%joyy% Joyrx%joyr% Joyu%joyu% Joyv%joyv% Joyz%joyz%
If (RT > 0 or LT > 0)
JoyMultiplier = 0.30
else
JoyMultiplier = 1.70
MouseNeedsToBeMoved := false ; Set default.
; ~ Config:
; Minimum to be considered "pressed", between 1 (0.39%) and 255 (100%).
SetFormat, float, 04
GetKeyState, joyx, %JoystickNumber%JoyX
GetKeyState, joyy, %JoystickNumber%JoyY
GetKeyState, joyr, %JoystickNumber%JoyR
GetKeyState, joyu, %JoystickNumber%Joyu
GetKeyState, joyv, %JoystickNumber%Joyv
GetKeyState, joyz, %JoystickNumber%JoyZ
return
WatchJoystick:
if joy%MOUSEAXISX% > %JoyThresholdUpperRX%
{
MouseNeedsToBeMoved := true
DeltaX := joy%MOUSEAXISX% - JoyThresholdUpperRX
}
else if joy%MOUSEAXISX% < %JoyThresholdLowerRX%
{
MouseNeedsToBeMoved := true
DeltaX := joy%MOUSEAXISX% - JoyThresholdLowerRX
}
else
DeltaX = 0
if joy%MOUSEAXISY% > %JoyThresholdUpperRY%
{
MouseNeedsToBeMoved := true
DeltaY := joy%MOUSEAXISY% - JoyThresholdUpperRY
}
else if joy%MOUSEAXISY% < %JoyThresholdLowerRY%
{
MouseNeedsToBeMoved := true
DeltaY := joy%MOUSEAXISY% - JoyThresholdLowerRY
}
else
DeltaY = 0
if MouseNeedsToBeMoved
{
SetMouseDelay, -1 ; Makes movement smoother.
MouseMove, DeltaX * JoyMultiplier, DeltaY * JoyMultiplier * YAxisMultiplier, 0, R
}
return
MouseWheel:
GetKeyState, JoyPOV, %JoystickNumber%JoyPOV
If JoyPOV =
return
if JoyPOV = -1 ; No angle.
return
if (JoyPOV > 31500 or JoyPOV < 4500) ; Forward
{
if (LT = 1 and RT = 1) ;Both triggers are held
{
ControlSend, , {Shift Down}, World of Warcraft
ControlClick,,World of Warcraft,,Wheelup
ControlSend, , {Shift UP}, World of Warcraft
}
if (LT = 0 and RT = 0) ;No triggers are held
{
ControlSend, , {Shift Down}, World of Warcraft
ControlSend, , {Up}, World of Warcraft
;ControlClick,,World of Warcraft,,up
ControlSend, , {Shift UP}, World of Warcraft
}
if (LT = 1 and RT = 0) ;UP trigger is held
{
ControlSend, , {Shift Down}, World of Warcraft
ControlClick,,World of Warcraft,,Wheelup
ControlSend, , {Shift UP}, World of Warcraft
}
if (LT = 0 and RT = 1) ;Right trigger is held
{
ControlSend, , {Shift Down}, World of Warcraft
ControlClick,,World of Warcraft,,Wheelup
ControlSend, , {Shift UP}, World of Warcraft
}
}
else if JoyPOV between 13500 and 22500 ; Back
{
if (LT = 1 and RT = 1) ;Both triggers are held
{
ControlSend, , {Shift Down}, World of Warcraft
ControlClick,,World of Warcraft,,Wheeldown
ControlSend, , {Shift UP}, World of Warcraft
}
if (LT = 0 and RT = 0) ;No triggers are held
{
ControlSend, , {Shift Down}, World of Warcraft
ControlSend, , {Down}, World of Warcraft
;ControlClick,,World of Warcraft,,down
ControlSend, , {Shift UP}, World of Warcraft
}
if (LT = 1 and RT = 0) ;Down trigger is held
{
ControlSend, , {Shift Down}, World of Warcraft
ControlClick,,World of Warcraft,,Wheeldown
ControlSend, , {Shift UP}, World of Warcraft
}
if (LT = 0 and RT = 1) ;Right trigger is held
{
ControlSend, , {Shift Down}, World of Warcraft
ControlClick,,World of Warcraft,,Wheeldown
ControlSend, , {Shift UP}, World of Warcraft
}
}
else if JoyPOV between 4500 and 13500 ; Right
{
if (LT = 1 and RT = 1) ;Both triggers are held
send ^{Tab}
if (LT = 0 and RT = 0) ;No triggers are held
send ^{Tab}
if (LT = 1 and RT = 0) ;Right trigger is held
send ^{Tab}
if (LT = 0 and RT = 1) ;Right trigger is held
send ^{Tab}
}
else if JoyPOV between 22500 and 31500 ; Left
{
if (LT = 1 and RT = 1) ;Both triggers are held
send B
if (LT = 0 and RT = 0) ;No triggers are held
send B
if (LT = 1 and RT = 0) ;Left trigger is held
send B
if (LT = 0 and RT = 1) ;Right trigger is held
send B
}
If POVSEND = `{ DOWN`}
POVSEND =
sleep 250
return
JOY TO WASD:
Code:
;
; AutoHotkey Version: 1.x
; Language: English
; Platform: Win9x/NT
; Author: A.N.Other <myemail@nowhere.com>
;
; Script Function:
; Template script (you can customize this template by editing "ShellNew\Template.ahk" in your Windows folder)
;
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
; Increase the following value to make the mouse cursor move faster:
JoyMultiplier = 1.30
;Declare defualt values for the stick
;~ LS_UP1:=Up
;~ LS_UP2:=Up
;~ LS_UP3:=Up
;~ LS_UP4:=Up
;~ LS_DOWN1:=Down
;~ LS_DOWN2:=Down
;~ LS_DOWN3:=Down
;~ LS_DOWN4:=Down
;~ LS_LEFT1:=Left
;~ LS_LEFT2:=Left
;~ LS_LEFT3:=Left
;~ LS_LEFT4:=Left
;~ LS_RIGHT1:=Right
;~ LS_RIGHT2:=Right
;~ LS_RIGHT3:=Right
;~ LS_RIGHT4:=Right
LS_UP1:=W
LS_UP2:=W
LS_UP3:=W
LS_UP4:=W
LS_DOWN1:=S
LS_DOWN2:=S
LS_DOWN3:=S
LS_DOWN4:=S
LS_LEFT1:=A
LS_LEFT2:=A
LS_LEFT3:=A
LS_LEFT4:=A
LS_RIGHT1:=D
LS_RIGHT2:=D
LS_RIGHT3:=D
LS_RIGHT4:=D
Threshold = 64
; Decrease the following value to require less joystick displacement-from-center
; to start moving the mouse. However, you may need to calibrate your joystick
; -- ensuring it's properly centered -- to avoid cursor drift. A perfectly tight
; and centered joystick could use a value of 1:
JoyThresholdL = 25
JoyThresholdR = 25
; Change the following to true to invert the Y-axis, which causes the mouse to
; move vertically in the direction opposite the stick:
InvertYAxis := false
; Change these values to use joystick button numbers other than 1, 2, and 3 for
; the left, right, and middle mouse buttons. Available numbers are 1 through 32.
; Use the Joystick Test Script to find out your joystick's numbers more easily.
ButtonLeft = 11
ButtonRight = 12
ButtonMiddle = 13
; If your joystick has a POV control, you can use it as a mouse wheel. The
; following value is the number of milliseconds between turns of the wheel.
; Decrease it to have the wheel turn faster:
WheelDelay = 250
; If your system has more than one joystick, increase this value to use a joystick
; other than the first:
JoystickNumber = 1
; END OF CONFIG SECTION -- Don't change anything below this point unless you want
; to alter the basic nature of the script.
#SingleInstance
setmousedelay, -1
setbatchlines, -1
INIFILE = DEFAULT.ini
IniRead, INIFILE, %INIFILE%, ini, DEFAULT , DEFAULT.ini
IniRead, MOUSEAXISU, %INIFILE%, AXIS, CharX , U
IniRead, MOUSEAXISR, %INIFILE%, AXIS, CharY , R
IniRead, JoyChar, %INIFILE%, AXIS, JoyChar , R
JoystickPrefix = %JoystickNumber%Joy
;Hotkey, %JoystickPrefix%%ButtonLeft%, ButtonLeft
;Hotkey, %JoystickPrefix%%ButtonRight%, ButtonRight
;Hotkey, %JoystickPrefix%%ButtonMiddle%, ButtonMiddle
; Calculate the axis displacements that are needed to start moving the cursor:
SetFormat, float, 03
;X Axix
JoyThresholdUpperLX := 50 + JoyThresholdL
JoyThresholdLowerLX := 50 - JoyThresholdL
JoyThresholdUpperRX := 50 + JoyThresholdR
JoyThresholdLowerRX := 50 - JoyThresholdR
;Y Axix
JoyThresholdUpperLY := 50 + JoyThresholdL
JoyThresholdLowerLY := 50 - JoyThresholdL
JoyThresholdUpperRY := 50 + JoyThresholdR
JoyThresholdLowerRY := 50 - JoyThresholdR
if InvertYAxis
YAxisMultiplier = -1
else
YAxisMultiplier = 1
SetTimer, WatchJoystick, 1 ; Monitor the movement of the joystick.
SetTimer, WatchUP, 1
SetTimer, WatchDOWN, 1
SetTimer, WatchLEFT, 1
SetTimer, WatchRIGHT, 1
GetKeyState, JoyInfo, %JoystickNumber%JoyInfo
;IfInString, JoyInfo, P ; Joystick has POV control, so use it as a mouse wheel.
; SetTimer, MouseWheel, %WheelDelay%
#include xinput.ahk
return ; End of auto-execute section.
!^w::
reload
return
WatchJoystick:
;tooltip DeltaU%DeltaU% DeltaR%DeltaR%`nJoyThresholdUpperLX%JoyThresholdUpperLX%`n%joyx%
SetFormat, float, 03
GetKeyState, joyx, %JoystickNumber%JoyX
GetKeyState, joyy, %JoystickNumber%JoyY
GetKeyState, joyr, %JoystickNumber%JoyR
GetKeyState, joyu, %JoystickNumber%Joyu
GetKeyState, joyz, %JoystickNumber%JoyZ
return
WatchUP:
;~ if joy%MOUSEAXISR% between %JoyThresholdLowerLY% AND %JoyThresholdUpperLY%
;~ sendvert={DOWN up}{UP up}
;~ if joy%MOUSEAXISR% < %JoyThresholdLowerLY%
;~ sendvert={UP down}
;~ if joy%MOUSEAXISR% > %JoyThresholdUpperLY%
;~ sendvert={DOWN down}
;~ if joy%MOUSEAXISU% Between %JoyThresholdLowerLX% AND %JoyThresholdUpperLX%
;~ sendhor={LEFT up}{RIGHT up}
;~ if joy%MOUSEAXISU% < %JoyThresholdLowerLX%
;~ sendhor={LEFT down}
;~ if joy%MOUSEAXISU% > %JoyThresholdUpperLX%
;~ sendhor={RIGHT down}
if joy%MOUSEAXISR% between %JoyThresholdLowerLY% AND %JoyThresholdUpperLY%
sendvert={S up}{W up}
if joy%MOUSEAXISR% < %JoyThresholdLowerLY%
sendvert={W down}
if joy%MOUSEAXISR% > %JoyThresholdUpperLY%
sendvert={S down}
if joy%MOUSEAXISU% Between %JoyThresholdLowerLX% AND %JoyThresholdUpperLX%
sendhor={A up}{D up}
if joy%MOUSEAXISU% < %JoyThresholdLowerLX%
sendhor={A down}
if joy%MOUSEAXISU% > %JoyThresholdUpperLX%
sendhor={D down}
return
WatchDOWN:
if joyinfo <>
{
if sendvert <> AND sendhor <>
sendinput % sendvert sendhor
return
}
WatchLEFT:
return
WatchRIGHT:
return
JOY TO MOUSE:
Code:
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
; Increase the following value to make the mouse cursor move faster:
JoyMultiplier = 1.30
; Decrease the following value to require less joystick displacement-from-center
; to start moving the mouse. However, you may need to calibrate your joystick
; -- ensuring it's properly centered -- to avoid cursor drift. A perfectly tight
; and centered joystick could use a value of 1:
JoyThresholdL = 25
JoyThresholdR = 25
; Change the following to true to invert the Y-axis, which causes the mouse to
; move vertically in the direction opposite the stick:
InvertYAxis := false
; Change these values to use joystick button numbers other than 1, 2, and 3 for
; the left, right, and middle mouse buttons. Available numbers are 1 through 32.
; Use the Joystick Test Script to find out your joystick's numbers more easily.
ButtonLeft = 11
ButtonRight = 12
ButtonMiddle = 13
; If your joystick has a POV control, you can use it as a mouse wheel. The
; following value is the number of milliseconds between turns of the wheel.
; Decrease it to have the wheel turn faster:
WheelDelay = 250
; If your system has more than one joystick, increase this value to use a joystick
; other than the first:
JoystickNumber = 1
; END OF CONFIG SECTION -- Don't change anything below this point unless you want
; to alter the basic nature of the script.
#SingleInstance
setmousedelay, -1
setbatchlines, -1
INIFILE = DEFAULT.ini
IniRead, INIFILE, %INIFILE%, ini, DEFAULT , DEFAULT.ini
IniRead, MOUSEAXISX, %INIFILE%, AXIS, mouseX , U
IniRead, MOUSEAXISY, %INIFILE%, AXIS, mouseY , R
IniRead, JoyMouse, %INIFILE%, AXIS, JoyMouse , R
JoystickPrefix = %JoystickNumber%Joy
;Hotkey, %JoystickPrefix%%ButtonLeft%, ButtonLeft
;Hotkey, %JoystickPrefix%%ButtonRight%, ButtonRight
;Hotkey, %JoystickPrefix%%ButtonMiddle%, ButtonMiddle
; Calculate the axis displacements that are needed to start moving the cursor:
;X Axix
JoyThresholdUpperLX := 50 + JoyThresholdL
JoyThresholdLowerLX := 50 - JoyThresholdL
JoyThresholdUpperRX := 50 + JoyThresholdR
JoyThresholdLowerRX := 50 - JoyThresholdR
;Y Axix
JoyThresholdUpperLY := 50 + JoyThresholdL
JoyThresholdLowerLY := 50 - JoyThresholdL
JoyThresholdUpperRY := 50 + JoyThresholdR
JoyThresholdLowerRY := 50 - JoyThresholdR
if InvertYAxis
YAxisMultiplier = -1
else
YAxisMultiplier = 1
SetTimer, WatchJoystick, 1 ; Monitor the movement of the joystick.
GetKeyState, JoyInfo, %JoystickNumber%JoyInfo
;IfInString, JoyInfo, P ; Joystick has POV control, so use it as a mouse wheel.
; SetTimer, MouseWheel, %WheelDelay%
return ; End of auto-execute section.
!^w::
reload
return
WatchJoystick:
MouseNeedsToBeMoved := false ; Set default.
SetFormat, float, 03
GetKeyState, joyx, %JoystickNumber%JoyX
GetKeyState, joyy, %JoystickNumber%JoyY
GetKeyState, joyr, %JoystickNumber%JoyR
GetKeyState, joyu, %JoystickNumber%Joyu
GetKeyState, joyv, %JoystickNumber%Joyv
GetKeyState, joyz, %JoystickNumber%JoyZ
if Joyz <> 50
JoyMultiplier = 0.20
else
JoyMultiplier = 1.00
if joy%MOUSEAXISX% > %JoyThresholdUpperRX%
{
MouseNeedsToBeMoved := true
DeltaX := joy%MOUSEAXISX% - JoyThresholdUpperRX
}
else if joy%MOUSEAXISX% < %JoyThresholdLowerRX%
{
MouseNeedsToBeMoved := true
DeltaX := joy%MOUSEAXISX% - JoyThresholdLowerRX
}
else
DeltaX = 0
if joy%MOUSEAXISY% > %JoyThresholdUpperRY%
{
MouseNeedsToBeMoved := true
DeltaY := joy%MOUSEAXISY% - JoyThresholdUpperRY
}
else if joy%MOUSEAXISY% < %JoyThresholdLowerRY%
{
MouseNeedsToBeMoved := true
DeltaY := joy%MOUSEAXISY% - JoyThresholdLowerRY
}
else
DeltaY = 0
if MouseNeedsToBeMoved
{
SetMouseDelay, -1 ; Makes movement smoother.
MouseMove, DeltaX * JoyMultiplier, DeltaY * JoyMultiplier * YAxisMultiplier, 0, R
}
return
WOWRUMBLE:
Code:
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
#include xinput.ahk
XInput_Init()
/*
COLORHEALTH = 0x00C800
50percent = 181, 63
25percent = 150, 63
10percent = 133, 63
CONTROL = 1267, 16 @ 0x0704D4
*/
SetTimer, WatchHealth, 1
SetTimer, Vibrator, 1
WatchHealth:
;tooltip 50per %50per% `n25per %25per%`n10per %10per%`n`nvibemode %vibemode%`nvibewait %vibewait%`n`nISDEAD? %ISDEAD%
PixelGetColor, control, 1267, 16, Slow
PixelGetColor, dead, 1035, 152, Slow
;tooltip control %control%
if control <> 0x000072
{
vibewait := 9
return
}
PixelGetColor, 50per, 181, 63, Slow
PixelGetColor, 25per, 150, 63, Slow
PixelGetColor, 10per, 133, 63, Slow
If dead = 0x7E7265
{
vibewait := 10
return
}
else If 10per <> 0x009E00
{
vibemode = CRITICAL HEALTH
vibewait = 4
}
else If 25per <> 0x00A700
{
vibemode = LOW HEALTH
vibewait = 2
}
else If 50per <> 0x00B400
{
vibemode = HALF HEALTH
vibewait = 1
}
else
{
vibemode = FULL HEALTH
vibewait := 9
}
SetTimer, WatchHealth, 1
return
Vibrator:
IfWinNotActive , World of Warcraft
return
vibetip = VIBE LOOP ON
If vibewait < 9
{
Loop, 4 {
if XInput_GetState(A_Index-1, State)=0 {
XInput_SetState(A_Index-1, vibewait*4000, vibewait*8000) ;MAX 65535
sleep 100
XInput_SetState(A_Index-1, vibewait*8191, vibewait*16383) ;MAX 65535
sleep 250
XInput_SetState(A_Index-1, vibewait*8000, vibewait*4000) ;MAX 65535
sleep 100
XInput_SetState(A_Index-1, vibewait*16383, vibewait*8191) ;MAX 65535 big 16383 low 8191
Sleep 250
XInput_SetState(A_Index-1, vibewait*4000, vibewait*8000) ;MAX 65535
sleep 100
XInput_SetState(A_Index-1, vibewait*8191, vibewait*16383) ;MAX 65535
sleep 250
XInput_SetState(A_Index-1, 0, 0) ;MAX 65535
sleep 2000/vibewait
}
}
}
If vibewait > 9
{
ISDEAD = YUP!
Loop, 4 {
if XInput_GetState(A_Index-1, State)=0 {
XInput_SetState(A_Index-1, vibewait*10, vibewait*500) ;MAX 65535
sleep 500
XInput_SetState(A_Index-1, vibewait*500, vibewait*1000) ;MAX 65535
sleep 500
XInput_SetState(A_Index-1, vibewait*1000, vibewait*4000) ;MAX 65535
sleep 500
XInput_SetState(A_Index-1, vibewait*4000, vibewait*1000) ;MAX 65535 big 16383 low 8191
Sleep 500
XInput_SetState(A_Index-1, vibewait*1000, vibewait*500) ;MAX 65535
sleep 500
XInput_SetState(A_Index-1, vibewait*500, vibewait*10) ;MAX 65535
sleep 500
XInput_SetState(A_Index-1, 0, 0) ;MAX 65535
sleep 10000/vibewait
XInput_SetState(A_Index-1, vibewait*500, vibewait*10) ;MAX 65535
sleep 500
XInput_SetState(A_Index-1, vibewait*1000, vibewait*500) ;MAX 65535
sleep 500
XInput_SetState(A_Index-1, vibewait*4000, vibewait*1000) ;MAX 65535 big 16383 low 8191
sleep 500
XInput_SetState(A_Index-1, vibewait*1000, vibewait*4000) ;MAX 65535
Sleep 500
XInput_SetState(A_Index-1, vibewait*500, vibewait*1000) ;MAX 65535
sleep 500
XInput_SetState(A_Index-1, vibewait*10, vibewait*500) ;MAX 65535
sleep 500
XInput_SetState(A_Index-1, 0, 0) ;MAX 65535
sleep 10000/vibewait
}
}
return
}
else
{
Loop, 4 {
if XInput_GetState(A_Index-1, State)=0 {
XInput_SetState(A_Index-1, 0, 0) ;MAX 65535
}
}
}
return
!#^F12::
reload
return
MODIFIED XINPUT LIB:
Code:
#Singleinstance force
#NoEnv
SendMode Play
setmousedelay, -1
setbatchlines, -1
; This version of Xinput contains the JSON parser as well as a modified version of Xinput for AHK_L compatability
;BEGIN JSON PARSER
/*
Function: JSON
Parameters:
js - source
s - path to element
v - (optional) value to overwrite
Returns:
Value of element (prior to change).
License:
- Version 2.0 by Titan <http://www.autohotkey.net/~Titan/#json>
- New BSD license terms <http://www.autohotkey.net/~Titan/license.txt>
*/
json(ByRef js, s, v = "") {
j = %js%
Loop, Parse, s, .
{
p = 2
RegExMatch(A_LoopField, "([+\-]?)([^[]+)((?:\[\d+\])*)", q)
Loop {
If (!p := RegExMatch(j, "(?<!\\)(""|')([^\1]+?)(?<!\\)(?-1)\s*:\s*((\{(?:[^{}]++|(?-1))*\})|(\[(?:[^[\]]++|(?-1))*\])|"
. "(?<!\\)(""|')[^\7]*?(?<!\\)(?-1)|[+\-]?\d+(?:\.\d*)?|true|false|null?)\s*(?:,|$|\})", x, p))
Return
Else If (x2 == q2 or q2 == "*") {
j = %x3%
z += p + StrLen(x2) - 2
If (q3 != "" and InStr(j, "[") == 1) {
StringTrimRight, q3, q3, 1
Loop, Parse, q3, ], [
{
z += 1 + RegExMatch(SubStr(j, 2, -1), "^(?:\s*((\[(?:[^[\]]++|(?-1))*\])|(\{(?:[^{\}]++|(?-1))*\})|[^,]*?)\s*(?:,|$)){" . SubStr(A_LoopField, 1) + 1 . "}", x)
j = %x1%
}
}
Break
}
Else p += StrLen(x)
}
}
If v !=
{
vs = "
If (RegExMatch(v, "^\s*(?:""|')*\s*([+\-]?\d+(?:\.\d*)?|true|false|null?)\s*(?:""|')*\s*$", vx)
and (vx1 + 0 or vx1 == 0 or vx1 == "true" or vx1 == "false" or vx1 == "null" or vx1 == "nul"))
vs := "", v := vx1
StringReplace, v, v, ", \", All
js := SubStr(js, 1, z := RegExMatch(js, ":\s*", zx, z) + StrLen(zx) - 1) . vs . v . vs . SubStr(js, z + StrLen(x3) + 1)
}
Return, j == "false" ? 0 : j == "true" ? 1 : j == "null" or j == "nul"
? "" : SubStr(j, 1, 1) == """" ? SubStr(j, 2, -1) : j
}
;END JSON PARSER
/*
Function: XInput_Init
Initializes XInput.ahk with the given XInput DLL.
Parameters:
dll - The path or name of the XInput DLL to load.
*/
XInput_Init(dll="xinput1_3.dll")
{
global
if _XInput_hm
return
;======== CONSTANTS DEFINED IN XINPUT.H ========
; NOTE: These are based on my outdated copy of the DirectX SDK.
; Newer versions of XInput may require additional constants.
; Device types available in XINPUT_CAPABILITIES
XINPUT_DEVTYPE_GAMEPAD = 0x01
; Device subtypes available in XINPUT_CAPABILITIES
XINPUT_DEVSUBTYPE_GAMEPAD = 0x01
; Flags for XINPUT_CAPABILITIES
XINPUT_CAPS_VOICE_SUPPORTED = 0x0004
; Constants for gamepad buttons
XINPUT_GAMEPAD_DPAD_UP = 0x0001
XINPUT_GAMEPAD_DPAD_DOWN = 0x0002
XINPUT_GAMEPAD_DPAD_LEFT = 0x0004
XINPUT_GAMEPAD_DPAD_RIGHT = 0x0008
XINPUT_GAMEPAD_START = 0x0010
XINPUT_GAMEPAD_BACK = 0x0020
XINPUT_GAMEPAD_LEFT_THUMB = 0x0040
XINPUT_GAMEPAD_RIGHT_THUMB = 0x0080
XINPUT_GAMEPAD_LEFT_SHOULDER = 0x0100
XINPUT_GAMEPAD_RIGHT_SHOULDER = 0x0200
XINPUT_GAMEPAD_A = 0x1000
XINPUT_GAMEPAD_B = 0x2000
XINPUT_GAMEPAD_X = 0x4000
XINPUT_GAMEPAD_Y = 0x8000
; Gamepad thresholds
XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE = 7849
XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE = 8689
XINPUT_GAMEPAD_TRIGGER_THRESHOLD = 30
; Flags to pass to XInputGetCapabilities
XINPUT_FLAG_GAMEPAD = 0x00000001
;=============== END CONSTANTS =================
_XInput_hm := DllCall("LoadLibrary" ,"str",dll)
if !_XInput_hm
{
MsgBox, Failed to initialize XInput: %dll%.dll not found.
return
}
_XInput_GetKeystroke := DllCall("GetProcAddress" ,"uint",_XInput_hm ,"AStr","XInputGetKeystroke")
_XInput_GetState := DllCall("GetProcAddress" ,"uint",_XInput_hm ,"AStr","XInputGetState")
_XInput_SetState := DllCall("GetProcAddress" ,"uint",_XInput_hm ,"AStr","XInputSetState")
_XInput_GetCapabilities := DllCall("GetProcAddress" ,"uint",_XInput_hm ,"AStr","XInputGetCapabilities")
if !(_XInput_GetState && _XInput_SetState && _XInput_GetCapabilities)
{
XInput_Term()
MsgBox, Failed to initialize XInput: function not found.
return
}
}
/*
Function: XInput_GetState
Retrieves the current state of the specified controller.
Parameters:
UserIndex - [in] Index of the user's controller. Can be a value from 0 to 3.
State - [out] Receives the current state of the controller.
Returns:
If the function succeeds, the return value is ERROR_SUCCESS (zero).
If the controller is not connected, the return value is ERROR_DEVICE_NOT_CONNECTED (1167).
If the function fails, the return value is an error code defined in Winerror.h.
http://msdn.microsoft.com/en-us/library/ms681381.aspx
Remarks:
XInput.dll returns controller state as a binary structure:
http://msdn.microsoft.com/en-us/library/bb174834.aspx
XInput.ahk converts this structure to a string, compatible with Titan's json():
http://www.autohotkey.com/forum/topic34565.html
*/
XInput_GetState(UserIndex, ByRef State)
{
global _XInput_GetState
VarSetCapacity(xiState,16)
if ErrorLevel := DllCall(_XInput_GetState ,"uint",UserIndex ,"uint",&xiState)
State =
else
State := "{
( C LTrim Join
'dwPacketNumber':" NumGet(xiState,0) ",
; Seems less convenient - though more technically accurate - to require
; "Gamepad." prefix to access any of the useful properties with json().
;'Gamepad':{
'wButtons':" NumGet(xiState,4,"UShort") ",
'bLeftTrigger':" NumGet(xiState,6,"UChar") ",
'bRightTrigger':" NumGet(xiState,7,"UChar") ",
'sThumbLX':" NumGet(xiState,8,"Short") ",
'sThumbLY':" NumGet(xiState,10,"Short") ",
'sThumbRX':" NumGet(xiState,12,"Short") ",
'sThumbRY':" NumGet(xiState,14,"Short") "
;}
)}"
return ErrorLevel
}
/*
Function: XInput_SetState
Sends data to a connected controller. This function is used to activate the vibration
function of a controller.
Parameters:
UserIndex - [in] Index of the user's controller. Can be a value from 0 to 3.
LeftMotorSpeed - [in] Speed of the left motor, between 0 and 65535.
RightMotorSpeed - [in] Speed of the right motor, between 0 and 65535.
Returns:
If the function succeeds, the return value is 0 (ERROR_SUCCESS).
If the controller is not connected, the return value is 1167 (ERROR_DEVICE_NOT_CONNECTED).
If the function fails, the return value is an error code defined in Winerror.h.
http://msdn.microsoft.com/en-us/library/ms681381.aspx
Remarks:
The left motor is the low-frequency rumble motor. The right motor is the
high-frequency rumble motor. The two motors are not the same, and they create
different vibration effects.
*/
XInput_SetState(UserIndex, LeftMotorSpeed, RightMotorSpeed)
{
global _XInput_SetState
return DllCall(_XInput_SetState ,"uint",UserIndex ,"uint*",LeftMotorSpeed|RightMotorSpeed<<16)
}
/*
Function: XInput_GetCapabilities
Retrieves the capabilities and features of a connected controller.
Parameters:
UserIndex - [in] Index of the user's controller. Can be a value in the range 0?3.
Flags - [in] Input flags that identify the controller type.
0 - All controllers.
1 - XINPUT_FLAG_GAMEPAD: Xbox 360 Controllers only.
Caps - [out] Receives the controller capabilities.
Returns:
If the function succeeds, the return value is 0 (ERROR_SUCCESS).
If the controller is not connected, the return value is 1167 (ERROR_DEVICE_NOT_CONNECTED).
If the function fails, the return value is an error code defined in Winerror.h.
http://msdn.microsoft.com/en-us/library/ms681381.aspx
*/
XInput_GetCapabilities(UserIndex, Flags, ByRef Caps)
{
global _XInput_GetCapabilities
VarSetCapacity(xiCaps,20)
if ErrorLevel := DllCall(_XInput_GetCapabilities ,"uint",UserIndex ,"uint",Flags ,"uint",&xiCaps)
Caps =
else
Caps := "{
( LTrim Join
'Type':" NumGet(xiCaps,0,"UChar") ",
'SubType':" NumGet(xiCaps,1,"UChar") ",
'Flags':" NumGet(xiCaps,2,"UShort") ",
'Gamepad':{
'wButtons':" NumGet(xiCaps,4,"UShort") ",
'bLeftTrigger':" NumGet(xiCaps,6,"UChar") ",
'bRightTrigger':" NumGet(xiCaps,7,"UChar") ",
'sThumbLX':" NumGet(xiCaps,8,"Short") ",
'sThumbLY':" NumGet(xiCaps,10,"Short") ",
'sThumbRX':" NumGet(xiCaps,12,"Short") ",
'sThumbRY':" NumGet(xiCaps,14,"Short") "
},
'Vibration':{
'wLeftMotorSpeed':" NumGet(xiCaps,16,"UShort") ",
'wRightMotorSpeed':" NumGet(xiCaps,18,"UShort") "
}
)}"
return ErrorLevel
}
/*
Function: XInput_Term
Unloads the previously loaded XInput DLL.
*/
XInput_Term() {
global
if _XInput_hm
DllCall("FreeLibrary","uint",_XInput_hm), _XInput_hm :=_XInput_GetState :=_XInput_SetState :=_XInput_GetCapabilities :=0
}
; TODO: XInputEnable, 'GetBatteryInformation and 'GetKeystroke.
;XInput_Init()
;Loop {
; Loop, 4 {
; if XInput_GetState(A_Index-1, State)=0 {
; LT := json(State,"bLeftTrigger")
; RT := json(State,"bRightTrigger")
; XInput_SetState(A_Index-1, LT*257, RT*257)
; }
; }
; Sleep, 100
;}
/*
; ~ Config:
; Minimum to be considered "pressed", between 1 (0.39%) and 255 (100%).
Threshold = 64
; Keys to bind to triggers.
LT_Key = Null
RT_Key = Null
; ~
LastRT := LastLT := 0
XInput_Init()
Loop {
Loop, 4 {
if XInput_GetState(A_Index-1, State)=0 {
LTRAW := json(State,"bLeftTrigger")
RTRAW := json(State,"bRightTrigger")
LX := json(State,"sThumbLX")
LY := json(State,"sThumbLY")
RX := json(State,"sThumbRX")
RY := json(State,"sThumbRY")
XInput_SetState(A_Index-1, LTRAW*25, RTRAW*25) ;vibration controll 257=max
LT := json(State,"bLeftTrigger") >= Threshold
RT := json(State,"bRightTrigger") >= Threshold
if (LT != LastLT) {
Sendplay % "{" . LT_Key . (LT ? " Down}" : " Up}")
LastLT := LT
}
if (RT != LastRT) {
Sendplay % "{" . RT_Key . (RT ? " Down}" : " Up}")
LastRT := RT
}
}
}
Sleep, 100
}
*/
OTHER NOTES:
To just take a peek at what's going on here, run the Xmount.exe in the zip that should give a pretty good visual of the intended design.
Modifications, revisions, and general tinkering is encouraged, however, keep in mind that some of the code was written by other AHK users.
I will update this thread as I have time to make revisions on this, also I apologize for the horribly alpha state of these scripts
As I mentioned I wrote this a long time ago, so if you see any code that looks like you wrote it please let me know so I can cite your work.