On/off modifier xbox 360 rt/lt

Ask gaming related questions (AHK v1.1 and older)
frogger
Posts: 4
Joined: 16 Apr 2018, 16:31

On/off modifier xbox 360 rt/lt

17 Apr 2018, 14:17

So there is this script that make rt and lt a modifier :

Code: Select all

#Persistent
#include xinput.ahk

SetKeyDelay 100

LT_Key = Null
RT_Key = Null

LastRT := LastLT := 

XInput_Init()
Loop {
Loop, 4 {
if State := XInput_GetState(A_Index-1) {
LT := State.bLeftTrigger
RT := State.bRightTrigger
            if (LT != LastLT) {
                Send % "{" . LT_Key . (LT ? " Down}" : " Up}")
                LastLT := LT
            }
            if (RT != LastRT) {
                Send % "{" . RT_Key . (RT ? " Down}" : " Up}")
                LastRT := RT
            }
        }
    }
    Sleep, 100
}

Joy1::												; Button "A"
if (LT >= 1 and RT >= 1)							; Both triggers are held
1VAR = b
if (LT < 1 and RT < 1)								; No triggers are held
1VAR = Enter
if (LT >= 1 and RT < 1)								; Left trigger is held
1VAR = null
if (LT < 1 and RT > 1)								; Right trigger is held
1VAR = null
Send {%1VAR% down}
SetTimer, WaitForButtonUpA, 30
return

WaitForButtonUpA:
if not GetKeyState("Joy1")
{
    Send {%1VAR% up}
    SetTimer, WaitForButtonUpA, off
    return
}
Send {%1VAR% down}
return

Joy2::												; Button "B"
if (LT >= 1 and RT >= 1)							; Both triggers are held
2VAR = f
if (LT < 1 and RT < 1)								; No triggers are held
2VAR = Esc
if (LT >= 1 and RT < 1)								; Left trigger is held
2VAR = null
if (LT < 1 and RT > 1)								; Right trigger is held
2VAR = null
Send {%2VAR% down}
SetTimer, WaitForButtonUpB, 30
return

WaitForButtonUpB:
if not GetKeyState("Joy2")
{
    Send {%2VAR% up}
    SetTimer, WaitForButtonUpB, off
    return
}
Send {%2VAR% down}
return

Joy3::												; Button "X"
if (LT >= 1 and RT >= 1)							; Both triggers are held
3VAR = D
if (LT < 1 and RT < 1)								; No triggers are held
3VAR = Space
if (LT >= 1 and RT < 1)								; Left trigger is held
3VAR = null
if (LT < 1 and RT > 1)								; Right trigger is held
3VAR = null
Send {%3VAR% down}
SetTimer, WaitForButtonUpX, 30
return

WaitForButtonUpX:
if not GetKeyState("Joy3")
{
    Send {%3VAR% up}
    SetTimer, WaitForButtonUpX, off
    return
}
Send {%3VAR% down}
return

Joy4::												; Button "Y"
if (LT >= 1 and RT >= 1)							; Both triggers are held
4VAR = v
if (LT < 1 and RT < 1)								; No triggers are held
4VAR = NumpadMult
if (LT >= 1 and RT < 1)								; Left trigger is held
4VAR = null
if (LT < 1 and RT > 1)								; Right trigger is held
4VAR = l
Send {%4VAR% down}
SetTimer, WaitForButtonUpY, 30
return

WaitForButtonUpY:
if not GetKeyState("Joy4")
{
    Send {%4VAR% up}
    SetTimer, WaitForButtonUpY, off
    return
}
Send {%4VAR% down}
return

Joy5::												; Button "LB"
if (LT >= 1 and RT >= 1)							; Both triggers are held
5VAR = W
if (LT < 1 and RT < 1)								; No triggers are held
5VAR = NumpadHome
if (LT >= 1 and RT < 1)								; Left trigger is held
5VAR = null
if (LT < 1 and RT > 1)								; Right trigger is held
5VAR = null
Send {%5VAR% down}
SetTimer, WaitForButtonUpLB, 30
return

WaitForButtonUpLB:
if not GetKeyState("Joy5")
{
    Send {%5VAR% up}
    SetTimer, WaitForButtonUpLB, off
    return
}
Send {%5VAR% down}
return

Joy6::												; Button "RB"
if (LT >= 1 and RT >= 1)							; Both triggers are held
6VAR = a
if (LT < 1 and RT < 1)								; No triggers are held
6VAR = NumpadPgUp
if (LT >= 1 and RT < 1)								; Left trigger is held
6VAR = null
if (LT < 1 and RT > 1)								; Right trigger is held
6VAR = null
Send {%6VAR% down}
SetTimer, WaitForButtonUpRB, 30
return

WaitForButtonUpRB:
if not GetKeyState("Joy6")
{
    Send {%6VAR% up}
    SetTimer, WaitForButtonUpRB, off
    return
}
Send {%6VAR% down}
return

Joy7::												; Button "BACK"
if (LT >= 1 and RT >= 1)							; Both triggers are held
7VAR = null
if (LT < 1 and RT < 1)								; No triggers are held
7VAR = /
if (LT >= 1 and RT < 1)								; Left trigger is held
7VAR = null
if (LT < 1 and RT > 1)								; Right trigger is held
7VAR = null
Send {%7VAR% down}
SetTimer, WaitForButtonUpBACK, 30
return

WaitForButtonUpBACK:
if not GetKeyState("Joy7")
{
    Send {%7VAR% up}
    SetTimer, WaitForButtonUpBACK, off
    return
}
Send {%7VAR% down}
return

Joy8::												; Button "START"
if (LT >= 1 and RT >= 1)							; Both triggers are held
8VAR = ?
if (LT < 1 and RT < 1)								; No triggers are held
8VAR = j
if (LT >= 1 and RT < 1)								; Left trigger is held
8VAR = null
if (LT < 1 and RT > 1)								; Right trigger is held
8VAR = null
Send {%8VAR% down}
SetTimer, WaitForButtonUpSTART, 30
return

WaitForButtonUpSTART:
if not GetKeyState("Joy8")
{
    Send {%8VAR% up}
    SetTimer, WaitForButtonUpSTART, off
    return
}
Send {%8VAR% down}
return

Joy9::												; Button "Left Joystick push"
if (LT >= 1 and RT >= 1)							; Both triggers are held
9VAR = null
if (LT < 1 and RT < 1)								; No triggers are held
9VAR = NumpadClear
if (LT >= 1 and RT < 1)								; Left trigger is held
9VAR = null
if (LT < 1 and RT > 1)								; Right trigger is held
9VAR = null
Send {%9VAR% down}
SetTimer, WaitForButtonUpLJP, 30
return

WaitForButtonUpLJP:
if not GetKeyState("Joy9")
{
    Send {%9VAR% up}
    SetTimer, WaitForButtonUpLJP, off
    return
}
Send {%9VAR% down}
return

Joy10::												; Button "Right Joystick push"
if (LT >= 1 and RT >= 1)							; Both triggers are held
10VAR = null
if (LT < 1 and RT < 1)								; No triggers are held
10VAR = NumpadIns
if (LT >= 1 and RT < 1)								; Left trigger is held
10VAR = null
if (LT < 1 and RT > 1)								; Right trigger is held
10VAR = null
Send {%10VAR% down}
SetTimer, WaitForButtonUpRJP, 30
return

WaitForButtonUpRJP:
if not GetKeyState("Joy10")
{
    Send {%10VAR% up}
    SetTimer, WaitForButtonUpRJP, off
    return
}
Send {%10VAR% down}
return
using this xinput.ahk :

Code: Select all

/*  XInput by Lexikos
 *  This version of the script uses objects, so requires AutoHotkey_L.
 */

/*
    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")
{
    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_GetState        := DllCall("GetProcAddress" ,"ptr",_XInput_hm ,"astr","XInputGetState")
    _XInput_SetState        := DllCall("GetProcAddress" ,"ptr",_XInput_hm ,"astr","XInputSetState")
    _XInput_GetCapabilities := DllCall("GetProcAddress" ,"ptr",_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/microsoft.directx_sdk.reference.xinput_state
            http://msdn.microsoft.com/en-us/library/microsoft.directx_sdk.reference.xinput_gamepad
        XInput.ahk converts this structure to an AutoHotkey_L object.
*/
XInput_GetState(UserIndex)
{
    global _XInput_GetState
    
    VarSetCapacity(xiState,16)

    if ErrorLevel := DllCall(_XInput_GetState ,"uint",UserIndex ,"uint",&xiState)
        return 0
    
    return {
    (Join,
        dwPacketNumber: NumGet(xiState,  0, "UInt")
        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")
    )}
}

/*
    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
    
    Remarks:
        XInput.dll returns capabilities via a binary structure:
            http://msdn.microsoft.com/en-us/library/microsoft.directx_sdk.reference.xinput_capabilities
        XInput.ahk converts this structure to an AutoHotkey_L object.
*/
XInput_GetCapabilities(UserIndex, Flags)
{
    global _XInput_GetCapabilities
    
    VarSetCapacity(xiCaps,20)
    
    if ErrorLevel := DllCall(_XInput_GetCapabilities ,"uint",UserIndex ,"uint",Flags ,"ptr",&xiCaps)
        return 0
    
    return,
    (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")
            }
        }
    )
}

/*
    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.

And I'm wondering if there would be a way to switch those modifier to be on a on/off instead of holding them? Maybe using keytoholddown/keytoholddownprev?
Last edited by frogger on 18 Apr 2018, 15:15, edited 1 time in total.
User avatar
evilC
Posts: 4823
Joined: 27 Feb 2014, 12:30

Re: On/off modifier xbox 360 rt/lt

18 Apr 2018, 05:51

You know, right, that AVAR is common to ALL buttons?
You hold A, it sets AVAR to b and sends b down. Without releasing A, you hit B, and it sets AVAR to f
When you release A, AVAR is no longer set to b, so it sends f up, not b up.

The script needs a total redesign IMHO.
frogger
Posts: 4
Joined: 16 Apr 2018, 16:31

Re: On/off modifier xbox 360 rt/lt

18 Apr 2018, 15:11

it's a non issue for it's purpose but i've changed it to 1var to 10var to make it "cleaner". I'm not a coder and it's the first time I touch autohotkey.

Do you think that it's possible to make rt,lt and rt+lt a trigger modifier instead of a holding one?

edit : doesnt this prevent the issue you are talking about

Code: Select all

WaitForButtonUpA:
if not GetKeyState("Joy1")
User avatar
evilC
Posts: 4823
Joined: 27 Feb 2014, 12:30

Re: On/off modifier xbox 360 rt/lt

19 Apr 2018, 07:48

Here you go - this technique should save you a TON of coding.

It shows you how to use one function to handle watching for release of all buttons and sending the appropriate key up event.

I used my own poll loop (Regular GetKeyState instead of XInput like you want), but otherwise the rest of the code should be good.
I also commented out the actual sending of keys and replaced them with Tooltips, to make it easier for me to debug.

Code: Select all

#SingleInstance force
#Persistent

heldButtons := {}
SetTimer, WatchButtons, 10

; Poll loop start
; Here I am simulating getting axis data from XInput, you would want to replace this with your old code
Loop {
	LT := GetKeyState("JoyX") - 50
	RT := GetKeyState("JoyY") - 50
	Sleep 10
}
; Poll loop end
return

1Joy1::
	if (LT >= 1 and RT >= 1){
		SendButton(A_ThisHotkey, "b")
	} else if (LT < 1 and RT < 1){
		SendButton(A_ThisHotkey, "Enter")
	}
	return
	
1Joy2::
	if (LT >= 1 and RT >= 1){
		SendButton(A_ThisHotkey, "f")
	} else if (LT < 1 and RT < 1){
		SendButton(A_ThisHotkey, "Esc")
	}
	return

; =============================================================

SendButton(btn, key){
	global heldButtons
	str := "{" key " down}"
	;~ Send % str
	ToolTip % "Button " btn " sending " str " @ " A_TickCount
	
	; Add an entry in the heldButtons array so the WatchButtons timer can check for release
	; Put the key that we pressed into the array, so WatchButtons knows what key to release
	heldButtons[btn] := key
}

; Checks the heldButtons array on a timer
; If any of the buttons in the array are no longer held...
; ... then send an up event for the key that was found in the array
WatchButtons:
	for btn, key in heldButtons {
		if (!GetKeyState(btn)){
			str := "{" key " up}"
			;~ Send % str
			ToolTip % "Button " btn " sending " str " @ " A_TickCount
			heldButtons.Delete(btn)
		}
	}
	return
frogger
Posts: 4
Joined: 16 Apr 2018, 16:31

Re: On/off modifier xbox 360 rt/lt

20 Apr 2018, 21:00

Thanks. It's for a old game and it's very capricious about key, as an example it sometime require capital letter but will not recognize capital letter, it need shift down d down d up shift up to work with the D shortcut, any other syntax doesnt work, tested them all, atleast all that i found.
I'm not sure how to do that using your code.

And im assuming you tested it with the left joystick(x/y) instead of the rt/lt(z)?

As for my initial issue i'm thinking about binding a simple profil switching instead.

Return to “Gaming Help (v1)”

Who is online

Users browsing this forum: No registered users and 47 guests