Null movement

Ask gaming related questions
afawfwa
Posts: 1
Joined: 22 Jul 2024, 21:03

Null movement

Post by afawfwa » 22 Jul 2024, 21:21

As the name of the post suggests: I'm looking for an improved null movement script.

There is one, made in v1.1, but it has problems and is limited on only A and D.

I've made some (very) amateur changes to the script to allow it between A and D, W and S, Left and Right & Up and Down.

It (mostly) works, however there's times where some a key is still pressed and I begin to move to the some random direction; this gets fixed by pressing the direction I'm being moved to.

The idea of the script is: if, for example, A is pressed, but I start pressing D while A is being press, D will be prioritezed and, while A is pressed down, I'll press D and instead of going left I'll start to go right in the game - if I stop pressing D, I'll continue going left with A pressed. Basically, it prevents you from being still while holding both adjacent movement keys.

This is something you can do in the Source 1 and 2 engines, but other games tend to not have this feature.

Code: Select all

#SingleInstance
#NoEnv
#MaxHotkeysPerInterval 99000000
#HotkeyInterval 99000000
#KeyHistory 0
ListLines Off
Process, Priority, , A


; Null Movement Script
; This updates the A and D keys so that only one is held down at a time
; This avoids the situation where game engines treat holding both strafe keys as not moving
; Insead holding both strafe keys will cause you to move in the direction of the last one that was pressed

a_held := 0 ; Variable that stores the actual keyboard state of the a key
d_held := 0 ; Variable that stores the actual keyboard state of the d key
a_scrip := 0 ; Variable that stores the state of the a key output from the script
d_scrip := 0 ; Variable that stores the state of the d key output from the script

*$a:: ; Every time the a key is pressed, * to include occurences with modifiers (shift, control, alt, etc)
	a_held := 1 ; Track the actual state of the keyboard key
	
	if (d_scrip){ 
		d_scrip := 0
		Send {Blind}{d up} ; Release the d key if it's held down, {Blind} so it includes any key modifiers (shift primarily)
	}
	
	if (!a_scrip){
		a_scrip := 1
		Send {Blind}{a down} ; Send the a down key
	}
	return

*$a up:: ; Every time the a key is released
	a_held := 0
	
	if (a_scrip){
		a_scrip := 0
		Send {Blind}{a up} ; Send the a up key
	}
		
	if (d_held AND !d_scrip){
		d_scrip := 1
		Send {Blind}{d down} ; Send the d down key if it's held
	}
	return

*$d:: ; Every time the d key is pressed
	d_held := 1
	
	if (a_scrip){
		a_scrip := 0
		Send {Blind}{a up}
	}
	
	if (!d_scrip){
		d_scrip := 1
		Send {Blind}{d down}
	}
	return

*$d up:: ; Every time the d key is released
	d_held := 0
	
	if (d_scrip){
		d_scrip := 0
		Send {Blind}{d up}
	}
	
	if (a_held AND !a_scrip){
		a_scrip := 1
		Send {Blind}{a down}
	}
	return

; W and S

w_held := 0 ; Variable that stores the actual keyboard state of the w key
s_held := 0 ; Variable that stores the actual keyboard state of the s key
w_scrip := 0 ; Variable that stores the state of the w key output from the script
s_scrip := 0 ; Variable that stores the state of the s key output from the script

*$w:: ; Every time the w key is pressed, * to include occurences with modifiers (shift, control, alt, etc)
	w_held := 1 ; Track the actual state of the keyboard key
	
	if (s_scrip){ 
		s_scrip := 0
		Send {Blind}{s up} ; Release the s key if it's held down, {Blind} so it includes any key modifiers (shift primarily)
	}
	
	if (!w_scrip){
		w_scrip := 1
		Send {Blind}{w down} ; Send the w down key
	}
	return

*$w up:: ; Every time the a key is released
	w_held := 0
	
	if (w_scrip){
		w_scrip := 0
		Send {Blind}{w up} ; Send the w up key
	}
		
	if (s_held AND !s_scrip){
		s_scrip := 1
		Send {Blind}{s down} ; Send the s down key if it's held
	}
	return

*$s:: ; Every time the s key is pressed
	s_held := 1
	
	if (w_scrip){
		w_scrip := 0
		Send {Blind}{w up}
	}
	
	if (!s_scrip){
		s_scrip := 1
		Send {Blind}{s down}
	}
	return

*$s up:: ; Every time the s key is released
	s_held := 0
	
	if (s_scrip){
		s_scrip := 0
		Send {Blind}{s up}
	}
	
	if (w_held AND !w_scrip){
		w_scrip := 1
		Send {Blind}{w down}
	}
	return

; Arrows

up_held := 0 ; Variable that stores the actual keyboard state of the up key
down_held := 0 ; Variable that stores the actual keyboard state of the down key
up_scrip := 0 ; Variable that stores the state of the up key output from the script
down_scrip := 0 ; Variable that stores the state of the down key output from the script

*$up:: ; Every time the up key is pressed, * to include occurences with modifiers (shift, control, alt, etc)
	up_held := 1 ; Track the actual state of the keyboard key
	
	if (down_scrip){ 
		down_scrip := 0
		Send {Blind}{down up} ; Release the down key if it's held down, {Blind} so it includes any key modifiers (shift primarily)
	}
	
	if (!up_scrip){
		up_scrip := 1
		Send {Blind}{up down} ; Send the up down key
	}
	return

*$up up:: ; Every time the up key is released
	up_held := 0
	
	if (up_scrip){
		up_scrip := 0
		Send {Blind}{up up} ; Send the up up key
	}
		
	if (down_held AND !down_scrip){
		down_scrip := 1
		Send {Blind}{down down} ; Send the down down key if it's held
	}
	return

*$down:: ; Every time the down key is pressed
	down_held := 1
	
	if (up_scrip){
		up_scrip := 0
		Send {Blind}{up up}
	}
	
	if (!down_scrip){
		down_scrip := 1
		Send {Blind}{down down}
	}
	return

*$down up:: ; Every time the down key is released
	down_held := 0
	
	if (down_scrip){
		down_scrip := 0
		Send {Blind}{down up}
	}
	
	if (up_held AND !up_scrip){
		up_scrip := 1
		Send {Blind}{up down}
	}
	return

; Left and Right

left_held := 0 ; Variable that stores the actual keyboard state of the left key
right_held := 0 ; Variable that stores the actual keyboard state of the right key
left_scrip := 0 ; Variable that stores the state of the left key output from the script
right_scrip := 0 ; Variable that stores the state of the right key output from the script

*$left:: ; Every time the left key is pressed, * to include occurences with modifiers (shift, control, alt, etc)
	left_held := 1 ; Track the actual state of the keyboard key
	
	if (right_scrip){ 
		right_scrip := 0
		Send {Blind}{right up} ; Release the right key if it's held down, {Blind} so it includes any key modifiers (shift primarily)
	}
	
	if (!left_scrip){
		left_scrip := 1
		Send {Blind}{left down} ; Send the left down key
	}
	return

*$left up:: ; Every time the left key is released
	left_held := 0
	
	if (left_scrip){
		left_scrip := 0
		Send {Blind}{left up} ; Send the left up key
	}
		
	if (right_held AND !right_scrip){
		right_scrip := 1
		Send {Blind}{right down} ; Send the right down key if it's held
	}
	return

*$right:: ; Every time the right key is pressed
	right_held := 1
	
	if (left_scrip){
		left_scrip := 0
		Send {Blind}{left up}
	}
	
	if (!right_scrip){
		right_scrip := 1
		Send {Blind}{right down}
	}
	return

*$right up:: ; Every time the right key is released
	right_held := 0
	
	if (right_scrip){
		right_scrip := 0
		Send {Blind}{right up}
	}
	
	if (left_held AND !left_scrip){
		left_scrip := 1
		Send {Blind}{left down}
	}
	return
This is the code for null movement I'm using. This is not made 100% by me, I found this and added W and S and the arrow keys to it. Here you have the original link: https://github.com/Qiasfah/Null-Movement-Script/blob/master/Null%20Movement.ahk

So, I would like to know: how could I improve on it, fix the random key being pressed down and also port it to v2? If any of you reading this would like to fix it yourself, that would not be a problem too (I would also prefer that, since I'm a bit lazy XD).

Thanks for your guys help in advance.

User avatar
mikeyww
Posts: 28741
Joined: 09 Sep 2014, 18:38

Re: Null movement

Post by mikeyww » 24 Jul 2024, 20:12

Welcome to this AutoHotkey forum!

A few ideas are below.

Code: Select all

#Requires AutoHotkey v2.0
str  := '|'

a::
d::
Left:: {
 If !InStr(str, '|' ThisHotkey '|') {
  Global str .= ThisHotkey '|'
  ToolTip str
  Send '{' ThisHotkey ' down}'
  SoundBeep 1500
 }
}

a Up::
d Up::
Left Up:: {
 Static regex := '.*\|(.+?)\|'
 Send '{' ThisHotkey '}'
 pos1 := RegExMatch(str, regex, &last1)
 Global str := StrReplace(str, StrReplace(ThisHotkey, ' Up') '|')
 pos2 := RegExMatch(str, regex, &last2)
 ToolTip str
 If pos1 && pos2 && last1[1] != last2[1] {
  Send '{' last2[1] ' down}'
  SoundBeep 2500
 }
}

User avatar
j46
Posts: 25
Joined: 23 Apr 2022, 10:29

Re: Null movement

Post by j46 » 25 Jul 2024, 13:22

Not tested in game because I dont have any..
But I was gonna propose something basic like this:

Code: Select all

*a::{									; a down
	if getkeystate("d")					; If d-key logical state is down
	send "{d up}"						; Set it to up, now that "a down" was pressed (a takes priority since it's the most rescent key-press). Any release of a button should probably come first, before another key is pressed.
	send "{a down}"						; Now that "d" is released, send "a down"
}

*a up::{								; a up
	send "{a up}"						; Release "a". Any release of a button should probably come first, before another key is pressed.
	if getkeystate("d", "P")			; If d-key physical state is down (i.e it was held during the a-press)
	send "{d down}"						; Put it back down now that "a" was released
}

*d::{
	if getkeystate("a")
	send "{a up}"
	send "{d down}"
}

*d up::{

	send "{d up}"
	if getkeystate("a", "P")
	send "{a down}"
}

User avatar
Noitalommi_2
Posts: 384
Joined: 16 Aug 2023, 10:58

Re: Null movement

Post by Noitalommi_2 » 25 Jul 2024, 14:34

Hi.

The script from the GitHub link in the initial post already contains a working V2 script with the desired functionality. It was probably updated after afawfwa posted here.

niCode
Posts: 333
Joined: 17 Oct 2022, 22:09

Re: Null movement

Post by niCode » 01 Aug 2024, 10:47

As someone who was an admin on kz servers in CSGO for years where nulls were frowned upon, it feels wrong to offer a solution but I guess people are gonna find ways to use it now so I'll just throw my rendition into the ring.

Code: Select all

#Requires AutoHotkey v2.0

Nulls('ahk_exe Code.exe', 'a', 'd', 'w', 's', 'Up', 'Down', 'Left', 'Right')
$F1::Nulls.Toggle()


/**
 * @param {func/string} criteria context when it should be active
 * @param {string*} keys pairs of keys to nullify each other e.g. key1 and key2, key3 and key4, key5 and key6, etc.
 */
class Nulls {
    static enabled := true
    static Enable()  => this.enabled := true
    static Disable() => this.enabled := false
    static Toggle()  => this.enabled ^= 1


    __New(criteria := () => true, keys*) {
        if keys.length = 0 {
            keys.Push('a', 'd')
        } else if Mod(keys.length, 2) != 0 {
            throw Error('Invalid amount of keys passed')
        }

        if criteria is String {
            criteria := WinActive.Bind(criteria)
        }

        HotIf((*) => Nulls.enabled and criteria())
        for key1, key2 in Map(keys*) {
            Hotkey('*' key1, ObjBindMethod(this, 'KeyDown', key1, key2))
            Hotkey('*' key1 ' up', ObjBindMethod(this, 'KeyUp', key1, key2))

            Hotkey('*' key2, ObjBindMethod(this, 'KeyDown', key2, key1))
            Hotkey('*' key2 ' up', ObjBindMethod(this, 'KeyUp', key2, key1))
        }
        HotIf()
    }

    KeyDown(key1, key2, *) {
        Hotkey('*' key1, 'Off')
        key2 := GetKeyState(key2) ? '{' key2 ' up}' : ''
        Send('{Blind}' key2 '{' key1 ' down}')
    }

    KeyUp(key1, key2, *) {
        Hotkey('*' key1, 'On')
        key2 := GetKeyState(key2, 'P') and not GetKeyState(key2) ? '{' key2 ' down}' : ''
        Send('{Blind}{' key1 ' up}' key2 )
    }
}
First parameter of Nulls is either a func obj that resolves to true or string that is a valid WinTitle that is used with WinActive to determine when the hotkeys should be active if you want the hotkeys only active in a particular game. In the given example, the hotkeys only work in my code editor.
The rest of the parameters should be in increments of 2 (or none to default to a and d). The example allows a and d to nullify each other, Up and Down, etc.

The $F1 hotkey is an example of how to toggle the hotkeys if you need to do that.

Post Reply

Return to “Gaming Help (v2)”