Creating a wrapper for interception.dll (fixed and working!) Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
phasermaniac
Posts: 74
Joined: 09 Apr 2017, 14:05

Re: Creating a wrapper for interception.dll (fixed and working!)

25 Jun 2017, 15:12

Hi! I have been a little busy, and was testing this code and it works nice, it sleeps the mouse click, in a individual way to mantain the raw input sepparation.
This is used for crt lightguns connected to windows, as they work as absolute coord mice, but need a flashing just a moment before the click (15, 30 or 45ms depending on the game/ emulator), because they dont track on dark colors:

Code: Select all

load()
context:=create_context()
set_filter(context, "keyboard","KEY_ALL")
loop,5 ;everything but MOUSE_MOVE
set_filter(context, "mouse", mouse_filter "MOUSE_BUTTON_1_DOWN|MOUSE_BUTTON_1_UP")

while ( receive(context,device:=wait(context),key,mouse,1) >0 )
{
	critical
	if is_keyboard(device)
	{
   	get_keyname(key,name,state)

		if name=F12
			break

      send(context,device,key,1)
	}
  else if is_mouse(device)
	{
		get_keyname(mouse,name,state)
		;ToolTip % "device: " device "`nname:" name "`nstate:" state "`nid:" hardware_id

		if  (device = gun1id || device = gun2id)
		{
			if name=LButton
			{
				if (state = 1)
				{	
					if  (device = gun1id)
						flasher := gun1flasher
					if  (device = gun2id)
						flasher := gun2flasher
						
					send %flasher%
					sleep, %triggerdelay%
					send(context,device,mouse,1)
					sleep, %triggerlength%
					mouse.state := 2
					send(context,device,mouse,1)
				}
			}
			else
			send(context,device,mouse,1)
			}
		else
		send(context,device,mouse,1)
	}
}
destroy_context(context)
return

The next I wanted to do, is converting this to direct input. I mean, I have some games which work with direct input and the mice/guns aiming don't get sepparated.
I can set triggers to any key instead of mouse1button1, mouse2button1, and so each trigger shoots the correct player bullets, but the coordenates are shared, and when both guns are aiming to the screen, the shoots gets crossed.
So I thought this:

Code: Select all

load()

context:=create_context()
set_filter(context, "keyboard","KEY_ALL")
set_filter(context, "mouse", "MOUSE_ALL")


while ( receive(context,device:=wait(context),key,mouse,1) >0 )
{
	critical
	if is_keyboard(device)
	{
		get_keyname(key,name,state)

			if name=F12
				break

		  send(context,device,key,1)
	}
	else if is_mouse(device)
	{
		get_keyname(mouse,name,state)
		;ToolTip % "device: " device "`nname:" name "`nstate:" state "`nid:" hardware_id
		
		if  (device = gun1id || device = gun2id)
		{
			if name=LButton
			{
				if (state = 1)
				{	
					if  (device = gun1id)
						trigger := gun1trigger
					if  (device = gun2id)
						trigger := gun2trigger
					
					;send(context,device,mouse,0)
					mouse.state := 2
					send(context,device,mouse,1)
					sleep, %triggerdelay%
					send {%trigger% down}
					sleep, %triggerlength%
					send {%trigger% up}			
				}
			}
And, and it separate the shoots correctly, but as you said, when using MOUSE_MOVE, it may lag, although it isn't noticeable, the flashing and the click don't mach and don't work propperly on dark colors.
In this same code if I change

Code: Select all

 set_filter(context, "mouse", "MOUSE_ALL") 
to

Code: Select all

set_filter(context, "mouse", mouse_filter "MOUSE_BUTTON_1_DOWN|MOUSE_BUTTON_1_UP")
The flashing works propperly, but as I'm not blocking the sistem mouse coordinates, the shoots get crossed between p1 and p2.

Any idea about that? you said to sepparate in two scripts? I tried something but I don't understand how to do it...
do you think this is the problem? the lag caused when blocking MOUSE_MOVE?
Noesis
Posts: 301
Joined: 26 Apr 2014, 07:57

Re: Creating a wrapper for interception.dll (fixed and working!)

27 Jun 2017, 08:56

No I don't think it's lag causing incorrect coordinates, I think it's the coordinates not being reported at the correct position. In fact I see in your second script you're not reporting movements at all when blocking mouse movements, so that's why it's shooting at the wrong spot even with only one gun, at least from what you have included from your script anyway. The script you posted is incomplete, so I was going to edit it but since it isn't complete I'll try to explain. You need to use an else if checking for mouse movement after the LButton check for the case when the devices are one of the guns, and report the movement . I would kind of expect the two guns at the same time issue however.

The major issue with two guns at the same time, is there are two devices using mouse coordinates, and windows doesn't really know how to do this, if you have two mice attached to your computer the cursor responds regardless of which mouse is moved. It's easy to block one devices mouse movements, and do something else entirely with it but what you need to do is basically track each devices movement independently, and then report where each device is pointing based on the tracked values when the triggers are pressed. Not something that is easy to do. I'm assuming here that the guns are always updating the position when pointed at the screen, and I'm not sure that is the case, since you also mentioned they use ABSOLUTE mouse positioning, which potentially changes everything regarding how to do the movement. You'll need to code so you can see some data (i.e tooltip) regarding the mouse movements being captured/reported to understand exactly whats happening. Best case scenario is that the movement is in fact reported in an Absolute fashion and perhaps in a burst only when the trigger is pressed, that would make it quite easy to do, but this is all just guess work without any data showing how the movement is actually being captured/reported.
User avatar
evilC
Posts: 4822
Joined: 27 Feb 2014, 12:30

Re: Creating a wrapper for interception.dll (fixed and working!)

27 Jun 2017, 09:34

If it is a light gun, it will most likely be reported as absolute.

FYI, I have made advances with processing input from multiple mice - I now have a solution which can block all input (Using hooks) but still receive rawinput messages (So it can get independent updates for each mouse).
At the moment it only responds to relative input, but I could easily update it to support absolute I think.
It uses a C# DLL to do the RawInput, as this is easier and faster in C#
https://autohotkey.com/boards/viewtopic ... 78#p153378

I think all I would need to do is add another method for subscribing to absolute data, eg add an extra condition like this one:

Code: Select all

        if (args.Mode == MouseMode.MoveRelative && relativeMoveCallback != null && (Math.Abs(args.X) + Math.Abs(args.Y) > 0))
        {
            relativeMoveCallback(args.X, args.Y);
        }
phasermaniac
Posts: 74
Joined: 09 Apr 2017, 14:05

Re: Creating a wrapper for interception.dll (fixed and working!)

27 Jun 2017, 13:04

Sorry, the second code had some errors...

Code: Select all

	
if  (device = gun1id || device = gun2id)
	{	
	if (state = 1)
		{	
			if  (device = gun1id)
				trigger := gun1trigger
				flasher := gun1flasher
			if  (device = gun2id)
				trigger := gun2trigger
				flasher := gun2flasher
						
			[b]send %flasher%
			sleep, %triggerdelay%[/b]
			mouse.state := 2
			send(context,device,mouse,1)
			send {%trigger% down}
			sleep, %triggerlength%
			send {%trigger% up}			
		}
		else
		send(context,device,mouse,1)
	}
	else
	send(context,device,mouse,1)
No I don't think it's lag causing incorrect coordinates, I think it's the coordinates not being reported at the correct position. In fact I see in your second script you're not reporting movements at all when blocking mouse movements, so that's why it's shooting at the wrong spot even with only one gun, at least from what you have included from your script anyway.
Hi Noesis, yes, the guns are ever tracking when aiming onscreen.
When using the second script, I block mouse movement for the guns, but it is refreshed when shoot. I can see it, so on shoot, the cursor moves to the correct aiming position, even aiming with the two guns, the bullets go to his correct player owner as I'm blocking mouse movement, and refreshing with

Code: Select all

					
mouse.state := 2
send(context,device,mouse,1)
the only problem it's triggerdelay that seems to be modified because I see the flashing, but it may be altered, as only changing MOUSE_ALL or MOUSE_MOVE by MOUSE_BUTTON_1_DOWN|MOUSE_BUTTON_1_UP


I have tried too with:

Code: Select all

			[b]send %flasher%
			sleep, %triggerdelay%[/b]
			mouse.state := 1
			send(context,device,mouse,1)
			send {%trigger% down}
			sleep, %triggerlength%
			send {%trigger% up}		
			mouse.state := 2
			send(context,device,mouse,1)	
but same results.
At the moment it only responds to relative input, but I could easily update it to support absolute I think.
It would rock, but I have ever used C#, what would I need to script with this?
Noesis
Posts: 301
Joined: 26 Apr 2014, 07:57

Re: Creating a wrapper for interception.dll (fixed and working!)

28 Jun 2017, 09:30

Ok,
Issue 1, is due to the sleep statements. Essentially what is happening is, when you press the trigger, the entire script is unable to do anything while it sleeps, nothing new can be reported and no new info can be captured, but all new info is still blocked. It can only be overcome by using another thread and the easiest way is to use a different script as that other script will run in a different thread. Choices for doing this is to use postmessage to send a message to the other script which is listening for the message, i.e. when a button is pressed (see ahk's help for "OnMessage" for help with this) or you could do something like send a key that isn't used (F13-F24 are good candidates, as they usually don't exist on keyboards anymore) from this script and have hotkeys set up in the other script waiting for one of those keys and then send the proper keys with the delays, that way the interception script can intercept and report the mouse position data while the button(s) are down.

Issue 2, you're trying to do too much in a single capture. You should be sending a key/button down OR up in a single loop iteration. At the moment the Up interceptions are completely ignored from the device and when the down event occurs, you're causing the first Issue but also completely guessing the length of time the trigger is held down for. Triggerlength is rarely going to be constant and it's completely based on your finger, it doesn't help that this variable isn't assigned a value anywhere in any of the scripts you've posted, which means it's either irrelevant and not necessary or I still haven't seen a complete script.

Issue 3 is, I'm still unclear on how the mouse positioning with the guns work. If the guns are using absolute coordinates I need to know what is being reported, use a tooltip to display what the mouse.x and mouse.y values are for the guns when they are moved. Or alternatively tell me how far off the flashes are, where are they appearing, i.e. are they always in the top left corner of the screen or are they close to where the gun is aimed but off only a little bit due to the trigger presses. There is a flag in the interception script for absolute mouse move too, so perhaps setting the filter to something like MOUSE_BUTTON_1_DOWN|MOUSE_BUTTON_1_UP|MOUSE_MOVE_ABSOLUTE instead of using MOUSE_MOVE or MOUSE_ALL. And to be honest at the moment you probably don't even need MOUSE_BUTTON_1_UP either, that way you could eliminate all the guess work with the up events.
phasermaniac
Posts: 74
Joined: 09 Apr 2017, 14:05

Re: Creating a wrapper for interception.dll (fixed and working!)

30 Jun 2017, 11:57

Sorry here it is the full code: I didn't shared it before to make it shorter:

Code: Select all

#Include <_Struct>
#SingleInstance force
#NoEnv
Process, Priority, , H
SetBatchLines, -1
ListLines Off
#KeyHistory 0
SendMode Input
SetTitleMatchMode 2
SetTitleMatchMode Fast
SetKeyDelay, -1, -1
SetMouseDelay, -1
SetWinDelay, 0		; Changed to 0 upon recommendation of documentation
SetControlDelay, 0	; Changed to 0 upon recommendation of documentation
SetDefaultMouseSpeed, 0
SendMode Input

triggerdelay=15
triggerlength=60

load()

context:=create_context()
set_filter(context, "keyboard","KEY_ALL")
loop,5 ;everything but MOUSE_MOVE
;mouse_filter.="MOUSE_BUTTON_" a_index "_DOWN|MOUSE_BUTTON_" a_index "_UP|"
set_filter(context, "mouse", mouse_filter "MOUSE_ALL")

while ( receive(context,device:=wait(context),key,mouse,1) >0 )
{
	critical
	if is_keyboard(device)
	{
		get_keyname(key,name,state)

			if name=F12
				break

		  send(context,device,key,1)
	}
	else if is_mouse(device)
	{
		get_keyname(mouse,name,state)
		;ToolTip % "device: " device "`nname:" name "`nstate:" state "`nid:" hardware_id
		
		if (device > 11)
		{
			if name=LButton
			{
				if (state=1)
				{	
					if  (device = 13 || device = 14||  device = 15)
					{
						flasher = a
						trigger = b
					}
					if  (device = 12 ||  device = 16||  device = 17)
					{         
						flasher = k
						trigger = o
					}
					send %flasher%		
					sleep(triggerdelay)

					mouse.state := 2
					send(context,device,mouse,1)
					Send, {%trigger% down}
					sleep(triggerlength)	
					Send, {%trigger% up}					
				}

			}
			if name=RButton
			{
				if (state = 1)
				{	
					if  (device = 13 || device = 14||  device = 15)
						buttonA = d
					if  (device = 12 ||  device = 16||  device = 17)
						buttonA = q
					
					send, {%buttonA% down}
					sleep(triggerlength)	
					send, {%buttonA% up}
					;mouse.state := 8
					;send(context,device,mouse,1)
					;send(context,device,mouse,0)
				}
			}
			if name=MButton
			{
				if (state = 1)
				{	
					if  (device = 13 || device = 14||  device = 15)
						buttonB = 1
					if  (device = 12 ||  device = 16||  device = 17)
						buttonB = 2
					
					send, {%buttonB% down}
					sleep(triggerlength)	
					send, {%buttonB% up}
					;mouse.state := 0x020
					;send(context,device,mouse,1)
					;send(context,device,mouse,0)
				}
			}
		}
		else
		send(context,device,mouse,1)
	}
}
destroy_context(context)
return

get_keyname(o,ByRef name,ByRef state){
	Critical
	if is_keyboard(o.device)
	{
    state:=o.state
		name:=GetKeyName("sc" hex(o.code))
	  hex:=hex(o.code)
		;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 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
		}

		if state in 1,4,16,64,256 ;down
			state:=1
	  if state in 2,8,32,128,512 ;up
	    state:=0
	}
}


send_keys(device,ByRef stroke,keys*){
global
	for every, key in keys
	{
    stroke.code:=GetKeySC(key)
		send(context,device,stroke,1)
	}
}

send(context,device,stroke,nstroke){
global
Critical
	res:=DllCall(dll . "\interception_send","Ptr",context,"int",device,"ptr",stroke[],"uint",nstroke,"Cdecl Int")
return res
}

receive(context,device,ByRef key,ByRef mouse,nstroke){
	global dll
	Critical

	if !isObject(key)
	{
		_key:="
		(
		 ushort code;
		 ushort state;
		 uint information;
		 uint device;
		)"
		;varsetcapacity(key,12)
		key:= new _Struct(_key)
	}

	if !isObject(mouse)
	{
		_mouse:="
		(
		 ushort state;
		 ushort flags;
		 short rolling;
		 int x;
		 int y;
		 uint information;
		 uint device;
		)"
		;varsetcapacity(mouse,18)
		mouse:= new _Struct(_mouse)
	}


	if is_keyboard(device)
	{
		res:=DllCall(dll . "\interception_receive","Ptr",context,"int",device,"ptr",key[""],"uint",nstroke,"Cdecl Int")
		key.device:=device
	}
	else if is_mouse(device)
	{
		res:=DllCall(dll . "\interception_receive","Ptr",context,"int",device,"ptr",mouse[""],"uint",nstroke,"Cdecl Int")
		mouse.device:=device
	}
return res
}

get_hardware_id(context,device){
global dll
Critical
VarSetCapacity(buffer,500)

	if (a_ptrsize > 4)
		DllCall(dll . "\interception_get_hardware_id","Ptr",context,"int",device,"str",buffer,"Uint",500,"Cdecl Int")
	else if (a_ptrsize < 4)
  	DllCall(dll . "\interception_get_hardware_id","Ptr",context,"int",device,"ptr",&buffer,"Uint",500,"Cdecl Int")

	return a_ptrsize > 4 ? buffer : StrGet(&buffer, "UTF-16")
}

wait(context){
	global
Critical
	return DllCall(dll . "\interception_wait","Ptr",context,"Cdecl Int")
}


set_filter(context,filter,keys){
global dll
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(dll . "\interception_set_filter","ptr",context,"ptr",f, "int",keys,"Cdecl Int")
}

is_mouse(device){
	global
  Critical
  return DllCall(dll . "\interception_is_mouse","int",device)
}

is_keyboard(device){
	global
  Critical
  return DllCall(dll . "\interception_is_keyboard","int",device)
}

get_pointer(func){
	global
	return DllCall("GetProcAddress", ptr, dllh, "astr", func, ptr)
}
create_context(){
	global
	return DllCall(dll . "\interception_create_context")
}
destroy_context(context){
	global
	return DllCall(dll . "\interception_destroy_context","ptr",context)
}

load(){
	global
	dll:="interception.dll"
	dllh:=DllCall("LoadLibrary", "Str", dll, "Ptr")
}

hex(n){
SetFormat, IntegerFast, hex
n+= 0
n.= ""
SetFormat, IntegerFast, d
return n
}

dec(n){
SetFormat, Integer, D
Dec := (n) + 0
return Dec
}

key2dec(name){
hex:=GetKeySC(name)
return dec(hex)
}
Issue2: I tested with only MOUSE_BUTTON_1_UP|MOUSE_MOVE, the script worked but same results.
I think "Issue3" is not the problem, as when the flash is launched at its timing, the shoot gets correctly positioned. I tried MOUSE_MOVE_ABSOLUTE but the script didnt work with this.

Si I will go for solution for Issue1, but I'm a bit lost, can you give some example or reference, please? and many thanks for your help!
Noesis
Posts: 301
Joined: 26 Apr 2014, 07:57

Re: Creating a wrapper for interception.dll (fixed and working!)

01 Jul 2017, 08:14

Ok when I say I need to see all the code, I mean the code you've changed i.e, the entire while loop and any variables being used within it, that you've defined outside it. (the original library I don't really need, unless you change part of it, in which case I'll need to see the bit you changed). It's purely so we're on the same page as to what you're doing, when you leave stuff out, I've got no option but to guess, like for example I had no Idea you were doing stuff with the mbutton or rbutton, I also wasn't aware the guns even had those buttons.

Another thing to be wary of is using send vs send(). send() is part of the interception library it sends keys differently to ahk and ahk will never think they are fake key presses, i.e. they are generated from the device driver. send is the ahk command, it could be interpreted as fake and is generated by ahk. Other ahk scripts may or may not ignore them depending on various settings. My personal thoughts are when using interception keep things generated by the driver. I also mention this as I noticed in the code you were using sleep(triggerdelay) - there is no sleep function in ahk or in the interception library, so I have no idea what these statements were doing if anything, they should be sleep, 100 or sleep, %variable%. (I didn't fix these btw, as that code will should be moved out of this script anyway)

Code below should give you an idea of what I mean using hotkeys in a separate script. I've only changed the lbutton part, with respect to this, and left your original code commented out. Should you post this script again please delete the commented sections before doing so. Finally, there were other parts I changed like making most the if statements, else if statements, as it is more efficient that way, and adding code to actually do stuff if it isn't one of the guns, so other things will still with the script running.

Code: Select all

triggerdelay=15
triggerlength=60

load()

context:=create_context()
set_filter(context, "keyboard","KEY_ALL")
loop,5 ;everything but MOUSE_MOVE
;mouse_filter.="MOUSE_BUTTON_" a_index "_DOWN|MOUSE_BUTTON_" a_index "_UP|"
set_filter(context, "mouse", mouse_filter "MOUSE_ALL")

while ( receive(context,device:=wait(context),key,mouse,1) >0 )
{
	critical
	if is_keyboard(device)
	{
		get_keyname(key,name,state)
		if name=F12
			break
		send(context,device,key,1)
	}
	else if is_mouse(device)
	{
		get_keyname(mouse,name,state)
		;ToolTip % "device: " device "`nname:" name "`nstate:" state "`nid:" hardware_id
		
		if (device > 11)
		{
			if name=LButton
			{
				fakekey:=""
				if (device = 13 || device = 14||  device = 15)
					fakekey:=GetKeySC("F13")
				else if (device = 12 ||  device = 16||  device = 17)
					fakekey:=GetKeySC("F14")
				If (fakekey)
				{
					key.code := fakekey
					If (state=1)
						key.state:=0
					Else
						key.state:=1
					send(context, key.device, key,1)
				}
				Else
					send(context, device, mouse,1)
				; if (state=1) ; Instead of this code being here, put it in a separate script see next code block.
				; {	
					; if  (device = 13 || device = 14||  device = 15)
					; {
						; flasher = a
						; trigger = b
					; }
					; if  (device = 12 ||  device = 16||  device = 17)
					; {         
						; flasher = k
						; trigger = o
					; }
					; send %flasher%		
					; sleep(triggerdelay)

					; mouse.state := 2
					; send(context,device,mouse,1)
					; Send, {%trigger% down}
					; sleep(triggerlength)	
					; Send, {%trigger% up}					
				; }

			}
			else if name=RButton
			{
				if (state = 1)
				{	
					if  (device = 13 || device = 14||  device = 15)
						buttonA = d
					if  (device = 12 ||  device = 16||  device = 17)
						buttonA = q
					
					send, {%buttonA% down}
					sleep(triggerlength)	
					send, {%buttonA% up}
					;mouse.state := 8
					;send(context,device,mouse,1)
					;send(context,device,mouse,0)
				}
			}
			else if name=MButton
			{
				if (state = 1)
				{	
					if  (device = 13 || device = 14||  device = 15)
						buttonB = 1
					if  (device = 12 ||  device = 16||  device = 17)
						buttonB = 2
					
					send, {%buttonB% down}
					sleep(triggerlength)	
					send, {%buttonB% up}
					;mouse.state := 0x020
					;send(context,device,mouse,1)
					;send(context,device,mouse,0)
				}
			}
			else
				send(context,device,mouse,1)
		}
		else
			send(context,device,mouse,1)
	}
}
destroy_context(context)
return
And another script which you should run when the first script is running:

Code: Select all

triggerdelay=15
triggerlength=60
F13:: FirePressed("a","b")
F14:: FirePressed("k","o")

FirePressed(flasher,trigger)
{
	send, %flasher%
	sleep, %triggerdelay%
	Send, {%trigger% down}
	sleep, %triggerlength%
	Send, {%trigger% up}
}
phasermaniac
Posts: 74
Joined: 09 Apr 2017, 14:05

Re: Creating a wrapper for interception.dll (fixed and working!)

03 Jul 2017, 10:58

Many thanks, I tested it with ease, and I found that with your 1st script the crosshair is always traking, I need to block movement but on button press, so I think it must be more like this:

Code: Select all

Process, Priority, , H
SetBatchLines, -1
ListLines Off
#KeyHistory 0
SendMode Input
SetTitleMatchMode 2
SetTitleMatchMode Fast
SetKeyDelay, -1, -1
SetMouseDelay, -1
SetWinDelay, 0		; Changed to 0 upon recommendation of documentation
SetControlDelay, 0	; Changed to 0 upon recommendation of documentation
SetDefaultMouseSpeed, 0
SendMode Input

triggerdelay=15
triggerlength=60

load()

context:=create_context()
set_filter(context, "keyboard","KEY_ALL")
loop,5 ;everything but MOUSE_MOVE
;mouse_filter.="MOUSE_BUTTON_" a_index "_DOWN|MOUSE_BUTTON_" a_index "_UP|"
set_filter(context, "mouse", mouse_filter "MOUSE_ALL")

while ( receive(context,device:=wait(context),key,mouse,1) >0 )
{
	critical
	if is_keyboard(device)
	{
		get_keyname(key,name,state)
		if name=F12
			break
		send(context,device,key,1)
	}
	else if is_mouse(device)
	{
		get_keyname(mouse,name,state)
		;ToolTip % "device: " device "`nname:" name "`nstate:" state "`nid:" hardware_id
		
		if (device > 11)
		{
			if name=LButton
			{
				fakekey:=""
				if (device = 13 || device = 14||  device = 15)
					fakekey:=GetKeySC("F13")
				else if (device = 12 ||  device = 16||  device = 17)
					fakekey:=GetKeySC("F14")
				If (fakekey)
				{
					key.code := fakekey
					
					If (state=1){
						send(context,device,mouse,1)
						key.state:=0
					}
					Else{
						key.state:=1
						send(context, key.device, key,1)
					}
				}
			}
			else if name=RButton
			{
				if (state = 1)
				{	
					if  (device = 13 || device = 14||  device = 15)
						buttonA = d
					if  (device = 12 ||  device = 16||  device = 17)
						buttonA = q
						
					send, {%buttonA% down}
					sleep(triggerlength)	
					send, {%buttonA% up}
				}
			}
			else if name=MButton
			{
				if (state = 1)
				{	
					if  (device = 13 || device = 14||  device = 15)
						buttonB = 1
					if  (device = 12 ||  device = 16||  device = 17)
						buttonB = 2
					
					send, {%buttonB% down}
					sleep(triggerlength)	
					send, {%buttonB% up}
				}
			}
			else
				send(context,device,mouse,1)
		}
		else
			send(context,device,mouse,1)
	}
}
destroy_context(context)
return
this way the cursor only refresshed the coordinates when firing, but I dont get the key pressed.
Actually, see another problem, in theorically, I should refresh the mouse movement after %triggerdelay%.
So I would have to add interception to the second script and have the 1rst capturing mouse_move without delays, and the 2nd, capturing mousebuttons and delaying. May this work?
Noesis
Posts: 301
Joined: 26 Apr 2014, 07:57

Re: Creating a wrapper for interception.dll (fixed and working!)

04 Jul 2017, 05:27

What values do you get with mouse move ? remember I asked you to put a tooltip in for mouse movement and to display mouse.x and mouse.y, the act of putting in the tooltip is purely to see what kind of values you get, as it will make movement lag but it's just for diagnostics and not meant to stay there. You could be you're getting low value values (likely less than 10) with a - (minus sign) when up or left and positive when right or down, or you may be getting larger values like screen coordinates. What you get determines what needs doing.
phasermaniac
Posts: 74
Joined: 09 Apr 2017, 14:05

Re: Creating a wrapper for interception.dll (fixed and working!)

04 Jul 2017, 15:14

ok sorry, I did, and the tooltip reported absolute coordinates, from 0 to 66000 for both x and y.
Noesis
Posts: 301
Joined: 26 Apr 2014, 07:57

Re: Creating a wrapper for interception.dll (fixed and working!)

05 Jul 2017, 09:48

0 to 66000 ? are you sure about that upper limit ? what resolution is your actual windows "desktop window" (i.e. combined Monitor resolution)
Noesis
Posts: 301
Joined: 26 Apr 2014, 07:57

Re: Creating a wrapper for interception.dll (fixed and working!)

06 Jul 2017, 02:56

Ok looking at the code you changed most recently, there is a very good reason the key isn't pressed and that's because You changed the code and now you're not telling it to press. Also with the new code you are are now sending mouse button 1 down and where in the code is it released ?.

I'm not entirely sure the values you gave me are correct for the mouse.x and mouse.y can you show me the code you used to get the values ? 66000 seems excessive for a monitor with 640 pixels at most and even if it is the case being that you aren't running a square resolution I'd expect the max x value to be different to the max y value. So I'm thinking you put the tooltip in the incorrect place.
phasermaniac
Posts: 74
Joined: 09 Apr 2017, 14:05

Re: Creating a wrapper for interception.dll (fixed and working!)

06 Jul 2017, 09:57

and even if it is the case being that you aren't running a square resolution I'd expect the max x value to be different to the max y value
Yes, I found it strange... But I recheck it and I get those values.
You changed the code and now you're not telling it to press.
I did , didn't I? I feel I don't understand this part

Code: Select all

If (fakekey)
	{
		key.code := fakekey
					
		If (state=1){
			send(context,device,mouse,1)
			key.state:=0
		}
		Else{
			key.state:=1
			send(context, key.device, key,1)
		}
	}
The tooltype code:

Code: Select all

load()

context:=create_context()
set_filter(context, "keyboard","KEY_ALL")
loop,5 ;everything but MOUSE_MOVE
;mouse_filter.="MOUSE_BUTTON_" a_index "_DOWN|MOUSE_BUTTON_" a_index "_UP|"
set_filter(context, "mouse", mouse_filter "MOUSE_ALL")

while ( receive(context,device:=wait(context),key,mouse,1) >0 )
{
	critical
	if is_keyboard(device)
	{
		get_keyname(key,name,state)
		if name=F12
			break
		send(context,device,key,1)
	}
	else if is_mouse(device)
	{
		get_keyname(mouse,name,state)
		;ToolTip % "device: " device "`nname:" name "`nstate:" state "`nid:" hardware_id

		if (device > 11)
		{
			if name=LButton
			{
			fakekey:=""
				if (device = 13 || device = 14||  device = 15){
					fakekey:=GetKeySC("F13")
				name := "move"
				ToolTip % "mouse device: " device "`nname:" name "`nx:" mouse.x ", y:" mouse.y "`nid:" hardware_id
			}
				else if (device = 12 ||  device = 16||  device = 17)
					fakekey:=GetKeySC("F14")
				If (fakekey)
				{
					key.code := fakekey
					If (state=1)
						key.state:=0
					Else
						key.state:=1
					send(context, key.device, key,1)
				}
				Else
					send(context, device, mouse,1)				
			}
			else if name=RButton
			{
				if (state = 1)
				{	
					if  (device = 13 || device = 14||  device = 15)
						buttonA = d
					if  (device = 12 ||  device = 16||  device = 17)
						buttonA = q
					
					send, {%buttonA% down}
					sleep(triggerlength)	
					send, {%buttonA% up}
				}
			}
			else if name=MButton
			{
				if (state = 1)
				{	
					if  (device = 13 || device = 14||  device = 15)
						buttonB = 1
					if  (device = 12 ||  device = 16||  device = 17)
						buttonB = 2
					
					send, {%buttonB% down}
					sleep(triggerlength)	
					send, {%buttonB% up}
				}
			}
			else
				send(context,device,mouse,1)
		}
		else
			send(context,device,mouse,1)
	}
}
destroy_context(context)
return
User avatar
evilC
Posts: 4822
Joined: 27 Feb 2014, 12:30

Re: Creating a wrapper for interception.dll (fixed and working!)

07 Jul 2017, 08:12

Hey guys,
Further to my last post, I now have POC implementations for most input / output methods (DirectInput, XInput, RawInput, vJoy/vXbox and the Titan API for outputting to consoles) written as a C# DLL that wraps the various APIs.
Just about the only hurdle left that is stopping me from implementing something like UCR (But with a C# back-end) is support for keyboard / mouse (With blocking support).

So Interception is looking more and more like the most viable candidate for that...

However, rather than implementing the Interception wrapper in AHK, I would be wanting to implement it in C#, and allowing AHK to call it via CLR.
I see a c# wrapper for interception here, however it does not seem to have been updated in 4 years.

Does anyone have anything more recent? Would anyone be interested in contributing or at least helping me get started?
I would certainly be willing to write something that was not specific to my implementation, so people who just wanted to use interception from AHK could just load my DLL and call the methods.
eg I would be looking to remove the need for while (receive()) loops in your AHK code - ideally everything would be event-based callbacks, like if you were using normal AHK hotkeys.

Edit: Ah, I just noticed Noesis' spoiler in the old post. I will try to have a play with that this weekend.
Noesis
Posts: 301
Joined: 26 Apr 2014, 07:57

Re: Creating a wrapper for interception.dll (fixed and working!)

07 Jul 2017, 09:29

Hi Evil, I posted a wrapper class for CS on the first page of this thread (not sure how to link to the specific post, but it was dated 5th Apr 17). It's in the Spoiler at the bottom of the post. It's fairly similar to the one you already found (I know this because the one I did was based of that one, there is however an extra function added to mine, which implements the call to get the device string. The fact of it being 4 years old isn't huge as none of the functions in the dll used have actually changed and interception itself hasn't been updated a great deal in that time either, only a couple of bug fixes I think from memory).

I'm happy to try and help with what I can but I'm not sure how much assistance I can actually be. The main thing to consider is probably the setup prior to the while (receive()) part, i.e. the setup of the filters to use and the device handling (assuming you plan on allowing filtering for specific devices). Then there is the sending of stuff, as sending via interception dll is also lower level than ahk's send command. One last thing to consider is that the while(receive()) is essentially event based itself, in that it doesn't constantly iterate, it only does so when filtered input is received but you've probably already realized that.
Noesis
Posts: 301
Joined: 26 Apr 2014, 07:57

Re: Creating a wrapper for interception.dll (fixed and working!)

07 Jul 2017, 10:08

phasermaniac wrote:I feel I don't understand this part

Code: Select all

If (fakekey)
	{
		key.code := fakekey
					
		If (state=1){
			send(context,device,mouse,1) ; this isn't a key, it's the mouse (actually it's the current input which is the Mouse LButton for the gun) it should be faked as a key being pressed (key is an object, key.code := scancode of the key to send, key.state := 0 is key down 1 is up, key.device := device sending the key, this must be a device number for a valid keyboard), device (on it's own is mouse.device) as it's referring the mouse device that created the input, as you are in the "if is_mouse(device)" section.  key.device is a keyboard device, and the mouse object is different to the key object (i.e. last parameter), what this line is actually doing is sending the received input through as output.
			key.state:=0 ;this is setting key down again this is different to state on it's own, state on it's own is a product of the getKeyName function and is different to the actual key.state or mouse.state you need to use to send a key or mouse button - to find those codes look at the code in getKeyName().
		}
		Else{
			key.state:=1
			send(context, key.device, key,1) ; this is sending a key, it's sending the device number, and a key object.  remember a key object is different to a mouse object.  Key object contains code,device and state, which is why I was set key.code and key.state so it would be put into the key object as what was needed.
		}
	}
Thanks for the tooltype code, the tooltip wasn't in the correct position, it was in the section for button LButton presses which will give garbage values for mouse.x & mouse.y try the following code instead

Code: Select all

load()

context:=create_context()
set_filter(context, "keyboard","KEY_ALL")
loop,5 ;everything but MOUSE_MOVE
;mouse_filter.="MOUSE_BUTTON_" a_index "_DOWN|MOUSE_BUTTON_" a_index "_UP|"
set_filter(context, "mouse", mouse_filter "MOUSE_ALL")

while ( receive(context,device:=wait(context),key,mouse,1) >0 )
{
	critical
	if is_keyboard(device)
	{
		get_keyname(key,name,state)
		if name=F12
			break
		send(context,device,key,1)
	}
	else if is_mouse(device)
	{
		get_keyname(mouse,name,state)
		;ToolTip % "device: " device "`nname:" name "`nstate:" state "`nid:" hardware_id

		if (device > 11)
		{
			if name=LButton
			{
				fakekey:=""
				if (device = 13 || device = 14||  device = 15){
					fakekey:=GetKeySC("F13")
				}
				else if (device = 12 ||  device = 16||  device = 17)
					fakekey:=GetKeySC("F14")
				If (fakekey)
				{
					key.code := fakekey
					If (state=1)
						key.state:=0
					Else
						key.state:=1
					send(context, key.device, key,1)
				}
				Else
					send(context, device, mouse,1)		
			}
			else if name=RButton
			{
				if (state = 1)
				{	
					if  (device = 13 || device = 14||  device = 15)
						buttonA = d
					if  (device = 12 ||  device = 16||  device = 17)
						buttonA = q
					
					send, {%buttonA% down}
					sleep(triggerlength)	
					send, {%buttonA% up}
				}
			}
			else if name=MButton
			{
				if (state = 1)
				{	
					if  (device = 13 || device = 14||  device = 15)
						buttonB = 1
					if  (device = 12 ||  device = 16||  device = 17)
						buttonB = 2
					
					send, {%buttonB% down}
					sleep(triggerlength)	
					send, {%buttonB% up}
				}
			}
			else
			{
				send(context,device,mouse,1)
				name := "move"
				ToolTip % "mouse device: " device "`nname:" name "`nx:" mouse.x ", y:" mouse.y "`nid:" hardware_id
			}
		}
		else
			send(context,device,mouse,1)
	}
}
destroy_context(context)
return
phasermaniac
Posts: 74
Joined: 09 Apr 2017, 14:05

Re: Creating a wrapper for interception.dll (fixed and working!)

07 Jul 2017, 11:07

Thanks noesis, I tried your code and I'm getting the same values, maybe the max y is near 64500, and the x 66000, event so it don't fit with the aspect ratio.
Noesis
Posts: 301
Joined: 26 Apr 2014, 07:57

Re: Creating a wrapper for interception.dll (fixed and working!)

08 Jul 2017, 00:54

Ok I've changed the code slightly, now movement is completely separated so you should get tooltip for any mouse movement regardless of device. Want you to check with gun, make sure the device number reported is actually a gun device, if not ignore the value as it's irrelevant (you hopefully were doing that anyway), also do a check using a regular mouse, as with a mouse you should definitely be getting relative values and if you don't then something else is going on. Just a hunch but if you don't get relative values for the mouse let me know what version of windows you using 64 bit or 32 bit ? also make sure you're using same version of ahk and the interception.dll you're using is also the same version as the system, and re-check.

Code: Select all

load()

context:=create_context()
set_filter(context, "keyboard","KEY_ALL")
;loop,5 ;everything but MOUSE_MOVE
;mouse_filter.="MOUSE_BUTTON_" a_index "_DOWN|MOUSE_BUTTON_" a_index "_UP|"
set_filter(context, "mouse", mouse_filter "MOUSE_ALL")

while ( receive(context,device:=wait(context),key,mouse,1) >0 )
{
	critical
	if is_keyboard(device)
	{
		get_keyname(key,name,state)
		if name=F12
			break
		send(context,device,key,1)
	}
	else if is_mouse(device)
	{
		If (mouse.state)
		{
			get_keyname(mouse,name,state)
			if (device > 11)
			{
				if name=LButton
				{
					fakekey:=""
					if (device = 13 || device = 14||  device = 15){
						fakekey:=GetKeySC("F13")
					}
					else if (device = 12 ||  device = 16||  device = 17)
						fakekey:=GetKeySC("F14")
					If (fakekey)
					{
						key.code := fakekey
						If (state=1)
							key.state:=0
						Else
							key.state:=1
						send(context, key.device, key,1)
					}
					Else
						send(context, device, mouse,1)		
				}
				else if name=RButton
				{
					if (state = 1)
					{	
						if  (device = 13 || device = 14||  device = 15)
							buttonA = d
						if  (device = 12 ||  device = 16||  device = 17)
							buttonA = q
						
						send, {%buttonA% down}
						sleep(triggerlength)	
						send, {%buttonA% up}
					}
				}
				else if name=MButton
				{
					if (state = 1)
					{	
						if  (device = 13 || device = 14||  device = 15)
							buttonB = 1
						if  (device = 12 ||  device = 16||  device = 17)
							buttonB = 2
						
						send, {%buttonB% down}
						sleep(triggerlength)	
						send, {%buttonB% up}
					}
				}
			}
			else
				send(context,device,mouse,1)
		}
		else
		{
			send(context,device,mouse,1)
			name := "move"
			ToolTip % "mouse device: " mouse.device "`nname:" name "`nx:" mouse.x ", y:" mouse.y
		}
	}
}
destroy_context(context)
return
phasermaniac
Posts: 74
Joined: 09 Apr 2017, 14:05

Re: Creating a wrapper for interception.dll (fixed and working!)

08 Jul 2017, 08:31

Thanks, I am on win10 64 bits, ahk and interception 64 bit.
I'm getting relative values when moving a mouse, and the same values (66000 for x 64500 or so for y).

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Shifted_Right and 161 guests