Hi phasermaniac, I've got some code for you to try. Firstly, I've created a more library like wrapper for Interception, which you'll need to use, it's like the one I posted earlier and is similar to the original one by ToonyTom but there is some basic stuff changed so key & mouse objects can be created easier and I've also added in access to another function which can set the precedence of devices within a context, which is part of interception.dll but wasn't included in the original wrapper. You'll need this for the scripts to work properly together and not fight with each other, since interception will be used to do the position reporting for the guns, but only when the button is pressed.
You'll need the following code and call the saved file "Interception.ahk". Either put it in a library folder (as per ahk's instructions to do so) or change how the other scripts include it for their use. You'll also need to set this up a bit for your machine. I've put comments in the code for what needs to be done, and all the changes you'll need to make are near the top of the script. There are 3 of them, they're essentially making sure it can access the actual interception.dll file on your machine and that the hardware strings match your hardware (instead of the ones already there which won't be correct for your machine).
Interception.ahk
Code: Select all
#Include <_Struct>
#SingleInstance force
#MaxHotkeysPerInterval 255
#MaxThreads 255
SetKeyDelay -1
SetBatchLines -1
;Change this line to be the path & filename to Interception.dll (i.e "Drive:\Path...\Interception.dll"). Currently it should work if it's in the same folder as the script.
Global interception_dll_path := A_ScriptDir "\interception.dll"
InitDeviceNums()
{
Devices := {}
context := Interception_Create_Context()
Interception_Set_Filter(context, "keyboard","KEY_NONE")
Loop 20
{
DevID := Interception_Get_Hardware_ID(context,A_Index)
If (DevID = "HID\VID_045E&PID_0752&REV_0110") ;mainKeyboard (Change String "HID\..." to be whatever your keyboard's device string is
Devices["mainKeyboard"] := A_Index
Else If (DevID = "HID\VID_046D&PID_C019&REV_4301") ;Light Guns (Change String "HID\..." to be whatever the Gun's device string is)
{ ;Using an array to store as more than one device shares same id string
If !Devices.HasKey("Gun")
Devices["Gun"] := []
Devices.Gun.Push(A_Index)
}
}
Interception_Destroy_Context(context)
Return Devices
}
get_keyname(o,ByRef name,ByRef state){
Critical
if Interception_Is_Keyboard(o.device)
{
state:=o.state
hex:=hex(o.code)
name:=GetKeyName("sc" hex)
;ToolTip % state "`n" name "`n" hex
if !name ;windows key
{
if hex=0x5b
name=LWin
if hex=0x5c
name=RWin
}
else if name in LControl,LAlt
{
if state=2
name:= "R" . SubStr(name,2, strlen(name))
if state=3
name:= "R" . SubStr(name,2, strlen(name))
}
else if name
{
if hex=0x53
{
if state in 0,1
name= NumpadDot
if state in 2,3
name=Delete
}
else if hex=0x36
name=RShift
else if (hex=0x2a) AND state=3
name:="PrintScreen", state:=1
else if (hex=0x37) AND state=2
name:="PrintScreen", state:=0
}
if state in 0,2 ;down
state:=1
else if state in 1,3 ;up
state:=0
}
else if Interception_Is_Mouse(o.device)
{
state:=o.state
if state in 1,2
name=LButton
else if state in 4,8
name=RButton
else if state in 16,32
name=MButton
else if state in 64,128
name=XButton1
else if state in 256,512
name=XButton2
else if state=1024
{
name=Wheel
if (o.rolling<0)
state:=1 ;down
else
state:=0 ;up
}
else if state = 2048
{
name=HWheel
if (o.rolling>0)
state:=1 ;right
else
state:=0 ;left
}
if state in 1,4,16,64,256 ;down
state:=1
if state in 2,8,32,128,512 ;up
state:=0
}
}
Interception_Send(context,device,stroke,nstroke)
{
Critical
res:=DllCall(interception_dll_path "\interception_send","Ptr",context,"int",device,"ptr",stroke[],"uint",nstroke,"Cdecl Int")
return res
}
Interception_Receive(context,device,ByRef key,ByRef mouse,nstroke)
{
Critical
if !isObject(key)
key := Interception_KeyStroke()
if !isObject(mouse)
mouse := Interception_MouseStroke()
if Interception_Is_Keyboard(device)
{
res:=DllCall(interception_dll_path "\interception_receive","Ptr",context,"int",device,"ptr",key[""],"uint",nstroke,"Cdecl Int")
key.device:=device
}
else if Interception_Is_Mouse(device)
{
res:=DllCall(interception_dll_path "\interception_receive","Ptr",context,"int",device,"ptr",mouse[""],"uint",nstroke,"Cdecl Int")
mouse.device:=device
}
Return res
}
Interception_KeyStroke()
{
_keystroke:="
(
ushort code;
ushort state;
uint information;
uint device;
)"
;varsetcapacity(key,12)
Return (new _Struct(_keystroke))
}
Interception_MouseStroke()
{
_mousestroke:="
(
ushort state;
ushort flags;
short rolling;
int x;
int y;
uint information;
uint device;
)"
;varsetcapacity(mouse,18)
Return (new _Struct(_mousestroke))
}
Interception_Get_Hardware_ID(context,device){
Critical
VarSetCapacity(buffer,500)
if (a_ptrsize > 4)
DllCall(interception_dll_path "\interception_get_hardware_id","Ptr",context,"int",device,"str",buffer,"Uint",500,"Cdecl Int")
else if (a_ptrsize < 4)
DllCall(interception_dll_path "\interception_get_hardware_id","Ptr",context,"int",device,"ptr",&buffer,"Uint",500,"Cdecl Int")
return a_ptrsize > 4 ? buffer : StrGet(&buffer, "UTF-16")
}
Interception_Wait(context)
{
Critical
return DllCall(interception_dll_path "\interception_wait","Ptr",context,"Cdecl Int")
}
Interception_Set_Filter(context,filter,keys)
{
Static keyboard:="interception_is_keyboard"
,mouse:="interception_is_mouse"
,KEY_DOWN = 0x00
,KEY_UP = 0x01
,KEY_NONE = 0x0000
,KEY_ALL = 0xFFFF
,KEY_E0 = 0x02 ;Delete Key
,KEY_E1 = 0x04
,KEY_TERMSRV_SET_LED = 0x08
,KEY_TERMSRV_SHADOW = 0x10
,KEY_TERMSRV_VKPACKET = 0x20
,FILTER_KEY_NONE = 0x0000
,FILTER_KEY_ALL = 0xFFFF
,FILTER_KEY_DOWN := KEY_UP
,FILTER_KEY_UP := KEY_UP << 1
,FILTER_KEY_E0 := KEY_E0 << 1
,FILTER_KEY_E1 := KEY_E1 << 1
,FILTER_KEY_TERMSRV_SET_LED := KEY_TERMSRV_SET_LED << 1
,FILTER_KEY_TERMSRV_SHADOW := KEY_TERMSRV_SHADOW << 1
,FILTER_KEY_TERMSRV_VKPACKET := KEY_TERMSRV_VKPACKET << 1
,MOUSE_NONE = 0x0000
,MOUSE_ALL = 0xFFFF
,MOUSE_LEFT_BUTTON_DOWN = 0x001
,MOUSE_LEFT_BUTTON_UP = 0x002
,MOUSE_RIGHT_BUTTON_DOWN = 0x004
,MOUSE_RIGHT_BUTTON_UP = 0x008
,MOUSE_MIDDLE_BUTTON_DOWN= 0x010
,MOUSE_MIDDLE_BUTTON_UP = 0x020
,MOUSE_BUTTON_1_DOWN := MOUSE_LEFT_BUTTON_DOWN
,MOUSE_BUTTON_1_UP := MOUSE_LEFT_BUTTON_UP
,MOUSE_BUTTON_2_DOWN := MOUSE_RIGHT_BUTTON_DOWN
,MOUSE_BUTTON_2_UP := MOUSE_RIGHT_BUTTON_UP
,MOUSE_BUTTON_3_DOWN := MOUSE_MIDDLE_BUTTON_DOWN
,MOUSE_BUTTON_3_UP := MOUSE_MIDDLE_BUTTON_UP
,MOUSE_BUTTON_4_DOWN = 0x040
,MOUSE_BUTTON_4_UP = 0x080
,MOUSE_BUTTON_5_DOWN = 0x100
,MOUSE_BUTTON_5_UP = 0x200
,MOUSE_WHEEL = 0x400
,MOUSE_HWHEEL = 0x800
,MOUSE_MOVE = 0x1000
,MOUSE_MOVE_RELATIVE = 0x000
,MOUSE_MOVE_ABSOLUTE = 0x001
,MOUSE_VIRTUAL_DESKTOP = 0x002
,MOUSE_ATTRIBUTES_CHANGED = 0x004
,MOUSE_MOVE_NOCOALESCE = 0x008
,MOUSE_TERMSRV_SRC_SHADOW = 0x100
if Instr(keys,"|")
{
loop,parse,keys,|
{
key:=%a_loopfield%
if a_index=1
keys2:=key
else
keys2:=keys2|key
}
keys:=keys2
}
else
keys:=%keys%
f:=get_pointer(%filter%)
DllCall(interception_dll_path "\interception_set_filter","ptr",context,"ptr",f, "int",keys,"Cdecl Int")
}
Interception_Is_Mouse(device)
{
Critical
return DllCall(interception_dll_path "\interception_is_mouse","int",device)
}
Interception_Is_Keyboard(device)
{
Critical
return DllCall(interception_dll_path "\interception_is_keyboard","int",device)
}
get_pointer(func){
global dllh
return DllCall("GetProcAddress", ptr, dllh, "astr", func, ptr)
}
Interception_Create_Context()
{
return DllCall(interception_dll_path "\interception_create_context")
}
Interception_Destroy_Context(context)
{
return DllCall(interception_dll_path "\interception_destroy_context","ptr",context)
}
Interception_Load()
{
global dllh
dllh:=DllCall("LoadLibrary", "Str", interception_dll_path "", "Ptr")
}
hex(n){
SetFormat, IntegerFast, hex
n+= 0
n.= ""
SetFormat, IntegerFast, d
return n
}
Interception_Set_Precedence(context, device, precedence)
{
DllCall(interception_dll_path "\interception_set_precedence","ptr",context,"int",device,"int",precedence)
if ErrorLevel
MsgBox %ErrorLevel%
Return
}
/*
;Do not use
Interception_Get_Precedence(context, device)
{
;If used 0 always returned and when script finishes device it was used on is bricked until unplugged/replugged or reboot.
result := DllCall(interception_dll_path "\interception_get_precedence","ptr",context,"int",device) ;,"Cdecl Int")
if ErrorLevel
MsgBox %ErrorLevel%
Return result
}
*/
Next, This is the script you'll need to run, it's an autohotkey style script and you can call it whatever you want, I've been using LightGun.ahk. Make sure you also have the script after this one before you run it, as it will try to run that one when you start this one. Also, If you don't like the name I gave the script after this one, You'll need to change the name in this script located in the Intercept object next to the CaptureScriptName field to match.
LightGun.ahk
Code: Select all
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn ; Enable warnings to assist with detecting common errors.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
#Include <Interception>
Intercept := {Context:"",CtrlrHwnd:0,CaptureScriptName:"LightGunIntercept.ahk"}
GunPos := {1:{x:0,y:0},2:{x:0,y:0}}
OnExit("ExitSub")
Interception_Load()
Dev := InitDeviceNums()
If (Round(Dev.Gun.MaxIndex()))
{
If (Round(Dev.Gun.MaxIndex()) < 2)
Dev.Gun.Push(21) ; if only one gun give the 2nd gun an out of bounds device number that can't be detected, since script assumes there are two devices
}
Else
{
MsgBox, Error, No Attached Guns Detected
ExitApp
}
Run, % Intercept.CaptureScriptName " " A_ScriptHwnd
Intercept.context := Interception_Create_Context()
OnMessage(0x10D1,"GunPosnMsg")
OnMessage(0x10D2,"GunPosnMsg")
triggerdelay := 15
triggerlength := 60
F13:: FirePressed("a","b",1)
F14:: FirePressed("k","o",2)
FirePressed(flasher,trigger,gun)
{
Global
SendMousePosition(Dev.Gun[gun],GunPos[gun].x,GunPos[gun].y)
send, %flasher%
sleep, %triggerdelay%
Send, {%trigger% down}
sleep, %triggerlength%
Send, {%trigger% up}
Return
}
SendMousePosition(device,msx,msy)
{
Global Intercept, GunPos
Global fakemouse := Interception_MouseStroke()
fakemouse.device := device
fakemouse.state := 0
fakemouse.x := msx
fakemouse.y := msy
Interception_send(Intercept.context, device, fakemouse,1)
Return
}
GunPosnMsg(wParam,lParam,msg)
{
Critical
Global GunPos
gundev := 0
If (msg = 0x10D1)
gundev := 1
Else If (msg = 0x10D2)
gundev := 2
If gundev
{
GunPos[gundev].x := wParam
GunPos[gundev].y := lParam
}
Return gundev
}
ExitSub()
{
Global
If Intercept.Context
Interception_Destroy_Context(Intercept.Context)
DetectHiddenWindows On
SetTitleMatchMode 2
If WinExist(Intercept.CaptureScriptName)
WinClose,% Intercept.CaptureScriptName
ExitApp
}
And the final script, is the intercept portion. I've hidden the icon of this script as a right click on it will cause inputs to not be processed properly until a reboot. The previous script should shut this one down, or you can still press F12 and that will break the loop and also close both scripts. This script can't be run on it's own, as it needs a window handle to communicate with, which is sent from the previous script when it runs this one. Also I wasn't sure what the other mouse buttons for the gun devices were meant to do so I just made them hit the keys you had in the last script you posted, and removed the sleeps, so they act like key down when button is down key up when button goes up. You should name this one:
LightGunIntercept.ahk
Code: Select all
#SingleInstance, Force
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
;#Warn, All, OutputDebug
#MaxHotkeysPerInterval 255
#MaxThreads 255
SetKeyDelay -1
SetBatchLines -1
SetWorkingDir %A_ScriptDir%
#NoTrayIcon
RecvrHwnd = %1%
If !(RecvrHwnd)
{
MsgBox Error, No Receiving Script Defined
ExitApp
}
Process, Priority,,High
#Include <Interception>
OnExit("ExitSub")
Interception_Load()
Dev := InitDeviceNums()
Gun := {}
If (Round(Dev.Gun.MaxIndex()))
{
Loop, % Round(Dev.Gun.MaxIndex())
Gun[(Dev.Gun[A_Index])] := {Msg:(0x10D0 + A_Index),Fired:0}
If (Round(Dev.Gun.MaxIndex()) < 2)
Dev.Gun.Push(21) ; if only one gun give the 2nd gun an out of bounds device number that can't be detected, since script assumes there are two devices
}
Else
{
MsgBox, Error, No Attached Guns Detected
ExitApp
}
DetectHiddenWindows On ; Allows a script's hidden main window to be detected.
context := Interception_Create_Context()
Interception_set_filter(context, "keyboard","KEY_ALL")
Interception_set_filter(context, "mouse", mouse_filter "MOUSE_ALL")
Loop, % Round(Dev.Gun.MaxIndex())
Interception_set_precedence(context,Dev.Gun[A_Index],1)
While ( Interception_receive(context,device:=Interception_wait(context),key,mouse,1) >0 )
{
critical
If Interception_is_keyboard(device)
{
get_keyname(key,name,state)
If (name = "F12")
break
Interception_send(context,device,key,1)
}
Else If Interception_is_mouse(device)
{
;ToolTip % "device: " device "`nname:" name "`nstate:" state "`nid:" hardware_id
If (device = Dev.Gun[1] || device = Dev.Gun[2])
{
If !(mouse.state)
{
If !(Gun[device].Fired)
PostMessage, % Gun[device].Msg, % mouse.x, % mouse.y,, AHK_id %RecvrHwnd%
}
Else
{
get_keyname(mouse,name,state)
fakekey:=""
If (name = "LButton")
{
Gun[device].Fired := state
If (device = Dev.Gun[1])
fakekey := GetKeySC("F13")
Else
fakekey := GetKeySC("F14")
}
Else If (name = "RButton")
{
If (device = Dev.Gun[1])
fakekey := GetKeySC("d")
Else
fakekey := GetKeySC("q")
}
Else If (name = "MButton")
{
If (device = Dev.Gun[1])
fakekey := GetKeySC("1")
Else
fakekey := GetKeySC("2")
}
If (fakekey)
{
key.device := Dev.mainKeyboard
key.code := fakekey
key.state := !state
Interception_send(context, Dev.mainKeyboard, key,1)
}
Else
Interception_send(context,device,mouse,1)
}
}
Else
Interception_send(context,device,mouse,1)
}
}
Interception_destroy_context(context)
context := ""
Return
ExitSub()
{
Global
If (context)
Interception_destroy_context(context)
If (WinExist("Ahk_Id " RecvrHwnd))
WinClose AHK_Id %RecvrHwnd%
ExitApp
}