|
; Tales of Ar'Okés v1.1 |
|
; June 2019 - @obskyr (https://twitter.com/obskyr) |
|
; |
|
; Do you have a tenkeyless keyboard? Are you not stuck in the 1970s? |
|
; Then finally, your prayers are answered. |
|
; This handy script lets you use arrow keys in Tales of Maj'Eyal (and other |
|
; grid-based numpad-controlled games) and still reliably walk diagonally! |
|
; |
|
; Changelog: |
|
; v1.1 (June 2019) |
|
; Pressing two opposite arrow keys at once now presses 5 on the numpad |
|
; (in order to wait in place in games where that's a thing 5 does). |
|
; v1.0 (June 2019) |
|
; It's alive! |
|
|
|
; ========= Settings ========= |
|
; (Times are in milliseconds.) |
|
; The grace period for pressing another arrow key to produce a diagonal. |
|
DIAGONAL_WAIT := 200 |
|
|
|
; How long to hold the arrow key(s) until key repeat kicks in. |
|
TYPEMATIC_DELAY := 250 |
|
|
|
; How long between key repeats ("run speed", more or less). |
|
; Setting this much lower than 100 may result in unreliability. |
|
TYPEMATIC_REPEAT := 100 |
|
|
|
; Windows to activate the script in. |
|
; Add other games you want to use the script with here! |
|
; Format: "GroupAdd, NumpadMovementWindow, <WinTitle>" |
|
; Info on the WinTitle parameter can be found here: |
|
; https://www.autohotkey.com/docs/misc/WinTitle.htm |
|
GroupAdd, NumpadMovementWindow, ahk_exe t-engine.exe |
|
GroupAdd, NumpadMovementWindow, ahk_exe t-engine-debug.exe |
|
|
|
; ============================ |
|
|
|
pressedArrowKeys := {"Up": GetKeyState("Up", "P") |
|
, "Down": GetKeyState("Down", "P") |
|
, "Left": GetKeyState("Left", "P") |
|
, "Right": GetKeyState("Right", "P")} |
|
|
|
ghostArrowKeys := {"Up": 0 |
|
, "Down": 0 |
|
, "Left": 0 |
|
, "Right": 0} |
|
|
|
waitActive := False |
|
|
|
arrowKeyPressed(key) |
|
{ |
|
global pressedArrowKeys |
|
global ghostArrowKeys |
|
global DIAGONAL_WAIT |
|
global waitActive |
|
|
|
if (pressedArrowKeys[key]) { |
|
; Gotta ignore typematic repeats. |
|
return |
|
} |
|
pressedArrowKeys[key] := 1 |
|
|
|
keysToCheck := {"Up": True |
|
, "Down": True |
|
, "Left": True |
|
, "Right": True} |
|
keysToCheck[key] := False |
|
|
|
for keytoCheck, chk in keysToCheck { |
|
if (chk and pressedArrowKeys[keyToCheck]) { |
|
; This makes the keypress trigger immediately if a second arrow |
|
; key is pressed while another is already held. If it turns out |
|
; that the desired behavior if for the DIAGONAL_WAIT to be |
|
; fully waited for even when a diagonal is pressed is desired, |
|
; ghostArrowKeys can be used to trigger the press later instead. |
|
updateNumpad() |
|
return |
|
} |
|
} |
|
|
|
ghostArrowKeys[key] := 1 |
|
|
|
if (not waitActive) { |
|
waitActive := True |
|
wait := -DIAGONAL_WAIT |
|
SetTimer, updateNumpad, %wait%, 1 |
|
} |
|
} |
|
|
|
arrowKeyReleased(key) |
|
{ |
|
global pressedArrowKeys |
|
global ghostArrowKeys |
|
global DIAGONAL_WAIT |
|
global waitActive |
|
global curNumpadKey |
|
|
|
if (not pressedArrowKeys[key]) { |
|
; Reduntant, but to be safe...! |
|
return |
|
} |
|
pressedArrowKeys[key] := 0 |
|
|
|
keysStillHeld := False |
|
for k, held in pressedArrowKeys { |
|
if (held) { |
|
keysStillHeld := True |
|
break |
|
} |
|
} |
|
|
|
if (keysStillHeld) { |
|
; Key state is cleared here too - this makes sure that if you hold |
|
; a diagonal but release one of the keys less than DIAGONAL_WAIT ms |
|
; before the current TYPEMATIC_DELAY or TYPEMATIC_REPEAT elapses, |
|
; another press of the previous keys won't occur. This does create |
|
; some weird behavior when holding incompatible keys, though - for |
|
; example, holding left and right and subsequently letting go of right |
|
; will make the typematic for walking left re-trigger from the start. |
|
clearTypematicTimers() |
|
curNumpadKey := |
|
|
|
wait := -DIAGONAL_WAIT |
|
SetTimer, updateNumpad, %wait%, 1 |
|
} else { |
|
if (waitActive) { |
|
pressOnNumpad(arrowKeysToNumber(ghostArrowKeys)) |
|
clearGhostArrowKeys() |
|
waitActive := False |
|
} |
|
clearTypematicTimers() |
|
curNumpadKey := |
|
} |
|
} |
|
|
|
curNumpadKey := |
|
|
|
doNumpad() |
|
{ |
|
global curNumpadKey |
|
pressOnNumpad(curNumpadKey) |
|
} |
|
|
|
pressOnNumpad(num) |
|
{ |
|
if (not num) { |
|
; For debugging: |
|
; throw "Called pressOnNumpad without a number!" |
|
clearTypematicTimers() |
|
waitActive := False |
|
} else { |
|
Send {Blind}{Numpad%num%} |
|
} |
|
} |
|
|
|
arrowKeysToNumber(keys) |
|
{ |
|
if (keys["Left"]) { |
|
if (keys["Up"]) { |
|
return 7 |
|
} else if (keys["Down"]) { |
|
return 1 |
|
} else if (keys["Right"]) { |
|
return 5 |
|
} else { |
|
return 4 |
|
} |
|
} else if (keys["Right"]) { |
|
if (keys["Up"]) { |
|
return 9 |
|
} else if (keys["Down"]) { |
|
return 3 |
|
} else { |
|
return 6 |
|
} |
|
} else if (keys["Up"]) { |
|
if (keys["Down"]) { |
|
return 5 |
|
} else { |
|
return 8 |
|
} |
|
} else if (keys["Down"]) { |
|
return 2 |
|
} else { |
|
return |
|
} |
|
} |
|
|
|
updateNumpad() |
|
{ |
|
global pressedArrowKeys |
|
global curNumpadKey |
|
global waitActive |
|
|
|
clearGhostArrowKeys() |
|
|
|
newNumpadKey := arrowKeysToNumber(pressedArrowKeys) |
|
if (newNumpadKey != curNumpadKey) { |
|
curNumpadKey := newNumpadKey |
|
clearTypematicTimers() |
|
if (curNumpadKey) { |
|
startNumpadTypematic() |
|
} |
|
} |
|
|
|
waitActive := False |
|
} |
|
|
|
startNumpadTypematic() |
|
{ |
|
global TYPEMATIC_DELAY |
|
doNumpad() |
|
delay := -TYPEMATIC_DELAY |
|
SetTimer, runNumpadRepeat, %delay%, 1 |
|
} |
|
|
|
runNumpadRepeat() |
|
{ |
|
global TYPEMATIC_REPEAT |
|
doNumpad() |
|
SetTimer, doNumpad, %TYPEMATIC_REPEAT%, 1 |
|
} |
|
|
|
clearTypematicTimers() { |
|
SetTimer, updateNumpad, Off |
|
SetTimer, runNumpadRepeat, Off |
|
SetTimer, doNumpad, Off |
|
} |
|
|
|
clearGhostArrowKeys() |
|
{ |
|
global ghostArrowKeys |
|
ghostArrowKeys["Up"] := 0 |
|
ghostArrowKeys["Down"] := 0 |
|
ghostArrowKeys["Left"] := 0 |
|
ghostArrowKeys["Right"] := 0 |
|
} |
|
|
|
#IfWinActive, ahk_group NumpadMovementWindow |
|
|
|
SendMode Input |
|
|
|
*$Up:: |
|
*$Down:: |
|
*$Left:: |
|
*$Right:: |
|
arrowKeyPressed(LTrim(A_ThisHotkey, "$*")) |
|
return |
|
|
|
*$Up Up:: |
|
*$Down Up:: |
|
*$Left Up:: |
|
*$Right Up:: |
|
arrowKeyReleased(StrSplit(A_ThisHotkey, A_Space, "$*", 2)[1]) |
|
return |