WASD key combo to numpad movement? Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
User avatar
Shadrach
Posts: 18
Joined: 18 Nov 2017, 08:02

WASD key combo to numpad movement?

08 May 2018, 08:40

Hi,
I've been using a relatively simple script to remap WASD to the arrow keys for a game. However, the game also supports six-directional movement with the numpad, so I'd like to add Numpad7,9,1,3 to the script for completeness.

Code: Select all

;WASD keys
w::Up
s::Down
a::Left
d::Right
So I tried to add this first just for testing:

Code: Select all

w & a::Numpad7
As per the documentation on combinations:
https://autohotkey.com/docs/Hotkeys.htm#combo

However this only triggers with holding down w *first* and pressing a. And it makes my w::Up remap not work as expected, as it only triggers on release.

I've also tried:

Code: Select all

w & a::
  Send {Numpad7}
  Return
This doesn't appear to work at all.

I'm pretty new to AHK, I've browsed the documentation, but there might be some modifiers I have to use to make the combination of two keys simultaneously map to a single key?

Or isn't this what AHK is really meant for, and it can't be done like this? I really don't want to map all the keys around WASD (i.e QEZC) for the same result...
User avatar
Exaskryz
Posts: 2882
Joined: 17 Oct 2015, 20:28

Re: WASD key combo to numpad movement?

08 May 2018, 08:55

I may be shortsighted, and this issue has come up before on the forums (check out the gaming section), but try something like this:

Code: Select all

w::Up ; Numpad8?
a::Left ; Numpad4?
~w & a::Numpad7
~a & w::Numpad7
; starts a comment on the line. This uses the ~ modifier to permit the native action of w and a, in this case, being remapped to up and left. Including both the w then a and a then w combination hotkeys should resolve the issue of needing one key down first by making both options.

The one problem I see happening is that if you press and hold w, then press a and release a, the w::Up remap may stop working. I do not know the best way to handle that. I've got to run so I'll leave it at that unfortunately, I do apologize for an incomplete answer. Hopefully it's not an issue in game because games can handle these key inputs differently. I had only done some quick testing in Notepad.
User avatar
evilC
Posts: 4823
Joined: 27 Feb 2014, 12:30

Re: WASD key combo to numpad movement?  Topic is solved

08 May 2018, 11:47

You are never gonna get an elegant solution by trying to say "This input key maps directly to that output key".
What instead you need to do is define a concept of a vector (A value of -1, 0 or 1) for each of the two axes (x and y) and tell the code what effect each input key has on each vector.
eg
pressing a sets the x axis vector to -1
releasing a sets the x axis vector to 0
pressing d sets the x axis vector to 1
pressing w sets the y axis vector to -1
pressing d sets the y axis vector to 1

Then, given both the x and y values are either -1, 0, or 1, you can build a matrix that tells you what the output key is.

eg
x = -1 and y = -1 (up left) is Numpad7
x = 1 and y = 1 (down right) is Numpad3

So given that you know the last and new vectors are for each axis x, we can tell what action to take
eg x/y was -1,-1 (up left = Numpad7) and is now 0,-1 (up = Numpad8) we know to release Numpad7 and hold Numpad8

Code: Select all

outputKeys := {-1: {-1: "Numpad7", 0: "Numpad4", 1: "Numpad1"}
				, 0: {-1: "Numpad8", 0:"", 1: "Numpad2"}
				, 1: {-1: "Numpad9", 0: "Numpad6", 1: "Numpad3"}}

w::
ProcessKeys("y", -1)
return

s::
ProcessKeys("y", 1)
return

w up::
s up::
ProcessKeys("y", 0)
return

a::
ProcessKeys("x", -1)
return

d::
ProcessKeys("x", 1)
return

a up::
d up::
ProcessKeys("x", 0)
return

^Esc::
	ExitApp

ProcessKeys(axis, vector){
	static keyVectors := {x: 0, y: 0}
	static otherAxes := {x: "y", y: "x"}
	global outputKeys
	
	otherAxis := otherAxes[axis]
	newVectors := {}
	newVectors[axis] := vector
	newVectors[otherAxis] := keyVectors[otherAxis]
	
	oldKey := outputKeys[keyVectors.x, keyVectors.y]
	newKey := outputKeys[newVectors.x, newVectors.y]
	
	if (newKey != oldKey){
		if (oldKey != ""){
			str := "{Blind}{" oldKey " up}"
			Send % str
			;~ ToolTip % str
		}
		if (newKey != ""){
			str := "{Blind}{" newKey " down}"
			Send % str
			;~ ToolTip % str
		}
		keyVectors[axis] := vector
	}
}
User avatar
Shadrach
Posts: 18
Joined: 18 Nov 2017, 08:02

Re: WASD key combo to numpad movement?

08 May 2018, 12:20

Thank you both for the very nice and thorough replies.

I tried Exaskryz's solution first, and it either refused to do anything or sometimes very rarely went active and scrolled in the right direction if I managed to press the keys exactly simultaneously, I think.

Also tried evilC's very complex solution - I really do appreciate the complexity, I think maybe it might be overkill for this, but I am willing to give it a go.
I replaced my entire script with it - I wanted to test just this part without any possible interference, but while the scrolling UDLR still worked, the combinations did not work as well.

I of course would like it to scroll while being held down, and it seems it does only send the Numpad presses once every press. Could probably change it to hold down but not sure how to do it - might have to wait for Up on *both* keys, not sure if that even can be done. Probably with a lot of code?
User avatar
evilC
Posts: 4823
Joined: 27 Feb 2014, 12:30

Re: WASD key combo to numpad movement?

08 May 2018, 12:27

That is correct. It does not repeat - that is by design.
It is not "complex". It's actually quite simple and elegant. Trying to make it work properly (Transitioning from up-left to up performs the correct key sequence) without using a technique like this would probably result in way more complexity, or dirty cludges.
What are you intending to use it for? I wrote it mainly with gaming in mind, which does not tend to need key repeats.

Here is a version that repeats when you hold the keys:

Code: Select all

outputKeys := {-1: {-1: "Numpad7", 0: "Numpad4", 1: "Numpad1"}
				, 0: {-1: "Numpad8", 0:"", 1: "Numpad2"}
				, 1: {-1: "Numpad9", 0: "Numpad6", 1: "Numpad3"}}

w::
ProcessKeys("y", -1)
return

s::
ProcessKeys("y", 1)
return

w up::
s up::
ProcessKeys("y", 0)
return

a::
ProcessKeys("x", -1)
return

d::
ProcessKeys("x", 1)
return

a up::
d up::
ProcessKeys("x", 0)
return

^Esc::
	ExitApp

ProcessKeys(axis, vector){
	static keyVectors := {x: 0, y: 0}
	static otherAxes := {x: "y", y: "x"}
	global outputKeys
	
	otherAxis := otherAxes[axis]
	newVectors := {}
	newVectors[axis] := vector
	newVectors[otherAxis] := keyVectors[otherAxis]
	
	oldKey := outputKeys[keyVectors.x, keyVectors.y]
	newKey := outputKeys[newVectors.x, newVectors.y]
	
	if (newKey != oldKey){
		if (oldKey != ""){
			str := "{Blind}{" oldKey " up}"
			Send % str
			;~ ToolTip % str
		}
	}
	if (newKey != ""){
		str := "{Blind}{" newKey " down}"
		Send % str
		;~ ToolTip % str " @ " A_TickCount
	}
	keyVectors[axis] := vector
}
Last edited by evilC on 09 May 2018, 04:12, edited 1 time in total.
User avatar
Shadrach
Posts: 18
Joined: 18 Nov 2017, 08:02

Re: WASD key combo to numpad movement?

08 May 2018, 12:55

Wow - that last one actually does work - thanks a lot! :clap: :D
I'll try to go through the code and figure out what it does, I hate having to just copy+paste stuff without understanding what it does.

Also; it appears I have to add the variable/function definition outside the #If WinActive directive, otherwise it won't know the variable when reloading, right?

But works a charm so far, even with the other overrides I have. And probably a much more elegant solution than just simply overriding keys. I was having problems with key lockups, that might be gone now, have to test.

The game is TOAW4:
http://www.matrixgames.com/products/587 ... .of.War.IV
It does not use WASD, nor does it support changing of keys, and has a terrible old mouse scrolling, so I had to learn AHK to be play it effectively. Also the game has serious key-press detection/thread problems, so there's that to contend with as well.

I've run a script for some time now, but I was thinking it would be cool if it could scroll in all directions :)

This is the script I was using until now, it worked fine but maybe not very elegant:
https://pastebin.com/ZJFQyZcX

Thanks for your help!

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: makdc96, RandomBoy, Rohwedder and 178 guests