1 (изменено: sabir.yanin2014, 2017-12-28 06:53:57)

Тема: AHK:Умная мышь или да здравствует хэдшот!

Известно что для более точного прицеливания нужно устанавливать меньшее DPI. С другой стороны при низком DPI перемещение курсора затратное(трудное) и становится сложно попадать по движущимся целям так как тупо не успеваешь за целью. Я постарался для себя игровой процесс сделать комфортным и за одно улучшить свои игровые достижения. Данный скрипт позволяет модифицировать мышь и сделать управление более гибким и удобным(эффективным). Что мне не нравилось в базовом интерфейсе(и что я устранил для себя):
1)Во время прицеливания чувствительность камеры в играх меняется слабо, не так как хотелось бы (претензии к разработчикам игр).
2)Первый пункт хотелось бы решить аппаратным способом, а именно изменяя настройки мыши(было бы хорошо если бы при нажатии ПКМ или даже клавиатуры чувствительность мыши снижалась требуемым образом -но таких мышей я не видел/претензии к разработчикам мышей).
3)Даже если бы и был возможен второй пункт то снижение чувствительности не решает проблему точного прицеливания так как в играх нужно стрелять по движущимся целям. А это сложно при низкой скорости мыши.Парадокс.
Наблюдая за собой я увидел что прицеливание я осуществляю в два этапа: 1)Приблизительное(быстрое) прицеливание;2)"Доцеливание"-точное прицеливание. Во время первого этапа мышь перемещается по коврику значительно -изменяя свое положение. Во время второго этапа мышь замирает и либо смещается незначительно либо вообще не двигается когда ловишь прицел с помощью WASD. Тут меня и осенило: что если скрипт сам будет проводить статистику поведения мыши и будет сам вычислять второй этап-для которого автоматически будет выбрано низкое DPI. Так мой код изменяет базовое значение DPI=800 на 400 во время прицеливания и позволяет ускорить мышь (DPI=800) при стрельбе по быстрым целям. Алгоритм следующий: в режиме прицеливания если мышь я смещаю слабо (DPI=400), если я ускоряю мышь выше заданного порога (хочу догнать цель) мышь ускоряется (DPI=800).После того как я обгоняю цель(упреждение) наступает второй этап -мышь замирает(DPI снова снижается до 400).Все -завершаю прицеливание и стреляю.
На англоязычном сайте нашел код который корректно измеряет движения мыши в играх.Он фиксирует пакеты которые формирует мышь и которые в итоге смещают камеру (MouseGetPos в играх работает неправильно).Немного доработал его.
Здесь нужно обратить внимание: что при использовании скрипта частоту опроса мыши нужно выставлять на минимум: так для моей мыши по умолчанию стоит 1000Гц -пакеты получаются маленькие, я выставил 125Гц -скрипт начал работать.
Код разбит на две части основной файл и подгружаемый "MouseDelta.ahk" который нужно расположить в директории основного.
Основной:


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;                      --Умная мышь--                  ;;;
;;;                  EasyHard, 29/11/2017г.              ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SMX:=OldSMX:=SMY:=OldSMY:=DSX:=DSY:=0
#SingleInstance force
#Persistent
#include MouseDelta.ahk
md:=new MouseDelta("MouseEvent").Start()
md.SetState(0)
SetTimer, SpeedMouse, 100


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;   Вычисление скорости перемещения физической мыши    ;;;
;;;    /автоматический выбор режима(авт.смена DPI)       ;;; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SpeedMouse:
DSX:=abs(OldSMX-SMX),OldSMX:=SMX,DSY:=abs(OldSMY-SMY),OldSMY:=SMY
if (DSX>30 or DSY>30) ;настраиваемые параметры-можно поэкспериментировать
Focus:=0 ;"быстрая мышь"-"режим-упреждение"-DPI базовый(настройка чувств.мыши/у меня 800DPI)
else 
Focus:=1 ;"точная мышь"-"режим-прицеливание"-измененный DPI(800/2=400)
Return 

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;         ПКМ-Включение режима прицеливания        ;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
*RButton::md.SetState(1)
*RButton up::md.SetState(0)

End::ExitApp

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;         Мышь-Регулирование скорости обзора       ;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MouseEvent(MouseID, x := 0, y := 0){
global SMX,SMY,Focus
	if (MouseID)
	{
	SMX+=x,SMY+=y
	if Focus
		{
		ShiftX:=x//2,ShiftY:=y//2
		DllCall("mouse_event",uint,1,int,-ShiftX,int,-ShiftY,uint,0,int,0)
		}
	}
}

MouseDelta.ahk:



; Instantiate this class and pass it a func name or a Function Object
; The specified function will be called with the delta move for the X and Y axes
; Normally, there is no windows message "mouse stopped", so one is simulated.
; After 10ms of no mouse movement, the callback is called with 0 for X and Y
Class MouseDelta {
	State := 0
	__New(callback){
		;~ this.TimeoutFn := this.TimeoutFunc.Bind(this)
		this.MouseMovedFn := this.MouseMoved.Bind(this)

		this.Callback := callback
	}

	Start(){
		static DevSize := 8 + A_PtrSize, RIDEV_INPUTSINK := 0x00000100
		; Register mouse for WM_INPUT messages.
		VarSetCapacity(RAWINPUTDEVICE, DevSize)
		NumPut(1, RAWINPUTDEVICE, 0, "UShort")
		NumPut(2, RAWINPUTDEVICE, 2, "UShort")
		NumPut(RIDEV_INPUTSINK, RAWINPUTDEVICE, 4, "Uint")
		; WM_INPUT needs a hwnd to route to, so get the hwnd of the AHK Gui.
		; It doesn't matter if the GUI is showing, it still exists
		Gui +hwndhwnd
		NumPut(hwnd, RAWINPUTDEVICE, 8, "Uint")
 
		this.RAWINPUTDEVICE := RAWINPUTDEVICE
		DllCall("RegisterRawInputDevices", "Ptr", &RAWINPUTDEVICE, "UInt", 1, "UInt", DevSize )
		OnMessage(0x00FF, this.MouseMovedFn)
		this.State := 1
		return this	; allow chaining
	}
	
	Stop(){
		static RIDEV_REMOVE := 0x00000001
		static DevSize := 8 + A_PtrSize
		OnMessage(0x00FF, this.MouseMovedFn, 0)
		RAWINPUTDEVICE := this.RAWINPUTDEVICE
		NumPut(RIDEV_REMOVE, RAWINPUTDEVICE, 4, "Uint")
		DllCall("RegisterRawInputDevices", "Ptr", &RAWINPUTDEVICE, "UInt", 1, "UInt", DevSize )
		this.State := 0
		return this	; allow chaining
	}
	
	SetState(state){
		if (state && !this.State)
			this.Start()
		else if (!state && this.State)
			this.Stop()
		return this	; allow chaining
	}

	Delete(){
		this.Stop()
		;~ this.TimeoutFn := ""
		this.MouseMovedFn := ""
	}
	
	; Called when the mouse moved.
	; Messages tend to contain small (+/- 1) movements, and happen frequently (~20ms)
	MouseMoved(wParam, lParam){
		Critical
		; RawInput statics
		static DeviceSize := 2 * A_PtrSize, iSize := 0, sz := 0, pcbSize:=8+2*A_PtrSize, offsets := {x: (20+A_PtrSize*2), y: (24+A_PtrSize*2)}, uRawInput
 
		static axes := {x: 1, y: 2}
 
		; Get hDevice from RAWINPUTHEADER to identify which mouse this data came from
		VarSetCapacity(header, pcbSize, 0)
		If (!DllCall("GetRawInputData", "UPtr", lParam, "uint", 0x10000005, "UPtr", &header, "Uint*", pcbSize, "Uint", pcbSize) or ErrorLevel)
			Return 0
		ThisMouse := NumGet(header, 8, "UPtr")

		; Find size of rawinput data - only needs to be run the first time.
		if (!iSize){
			r := DllCall("GetRawInputData", "UInt", lParam, "UInt", 0x10000003, "Ptr", 0, "UInt*", iSize, "UInt", 8 + (A_PtrSize * 2))
			VarSetCapacity(uRawInput, iSize)
		}
		sz := iSize	; param gets overwritten with # of bytes output, so preserve iSize
		; Get RawInput data
		r := DllCall("GetRawInputData", "UInt", lParam, "UInt", 0x10000003, "Ptr", &uRawInput, "UInt*", sz, "UInt", 8 + (A_PtrSize * 2))
 
		x := 0, y := 0	; Ensure we always report a number for an axis. Needed?
		x := NumGet(&uRawInput, offsets.x, "Int")
		y := NumGet(&uRawInput, offsets.y, "Int")
 
		this.Callback.(ThisMouse, x, y)
 
		;~ ; There is no message for "Stopped", so simulate one
		;~ fn := this.TimeoutFn
		;~ SetTimer, % fn, -50
	}
 
	;~ TimeoutFunc(){
		;~ this.Callback.("", 0, 0)
	;~ }
 
}

2

Re: AHK:Умная мышь или да здравствует хэдшот!

Под какую игру делался скрипт?

3

Re: AHK:Умная мышь или да здравствует хэдшот!

Dworkin пишет:

Под какую игру делался скрипт?

Непринципиально, под любую.

4

Re: AHK:Умная мышь или да здравствует хэдшот!

Проверить можно в тире. Я проверял в The Evil Within 2. Результат на 2000 больше набил чем без скрипта.

5

Re: AHK:Умная мышь или да здравствует хэдшот!

Извините за вопрос, но какие переменные в скрипте отвечают за величину автозамедления и порог когда оно срабатывает. Неплохо бы сделать скрипт настраиваемым, прикрутить гуи я могу, но прочитать и понять код, моих познаний не хватает. Замедление по нажатию правой кнопки заметно, а вот автосмена DPI чето совсем не чувствуется.

6

Re: AHK:Умная мышь или да здравствует хэдшот!

Dimaryo, я же закомментировал: "настраиваемые параметры" в данном случае 30.
Фрагмент кода:


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;   Вычисление скорости перемещения физической мыши    ;;;
;;;    /автоматический выбор режима(авт.смена DPI)       ;;; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SpeedMouse:
DSX:=abs(OldSMX-SMX),OldSMX:=SMX,DSY:=abs(OldSMY-SMY),OldSMY:=SMY
if (DSX>30 or DSY>30) ;настраиваемые параметры-можно поэкспериментировать
Focus:=0 ;"быстрая мышь"-"режим-упреждение"-DPI базовый(настройка чувств.мыши/у меня 800DPI)
else 
Focus:=1 ;"точная мышь"-"режим-прицеливание"-измененный DPI(800/2=400)
....


Если вы хотите увеличить "чувствительность" скрипта нужно уменьшить величину порога. Смысл: скрипт через каждые 100 мс проверяет на сколько сместилась физическая мышь. Условно говоря 30 это пороговая скорость мыши 30пкс/100мс. Если вместо 30 выставить 10 то мышь будет "срываться" -ускоряться до 800 DPI при меньшем смещении мыши. Если выставить 60 то мышь станет более "грубая" т.е. чтобы включить автоускорение нужно сильно и быстро сместить мышь. Поэтому экспериментируйте -меняйте оба параметра так: "if (DSX>60 or DSY>60)".
И снизьте частоту опроса мыши на минимум.

7 (изменено: sabir.yanin2014, 2017-12-28 07:00:38)

Re: AHK:Умная мышь или да здравствует хэдшот!

Dimaryo, возможно вы были правы и мой код у вас не работал. Я отредактировал скрипт и вы можете проверить.
Нужно было в начале кода обнулить переменные.

8 (изменено: sabir.yanin2014, 2017-12-28 07:30:20)

Re: AHK:Умная мышь или да здравствует хэдшот!

Мышь-Джойстик

Возникла идея превратить мышь в "джойстик": при нажатии ключевой клавиши-блокировать камеру, а на смещение мыши реагировать нажатием клавиши. Таким образом получается аналог джойстика с четырьмя направлениями которые можно "забиндить" под четыре клавиши:


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;                     -Мышь-Джойстик-                  ;;;
;;;                  EasyHard, 28/12/2017г.              ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SMX:=OldSMX:=SMY:=OldSMY:=DSX:=DSY:=0
#SingleInstance force
#Persistent
#include MouseDelta.ahk
md:=new MouseDelta("MouseEvent").Start()
md.SetState(0)
SetTimer, SpeedMouse, 100


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;                Мышь-режим джойстика              ;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SpeedMouse:
DSX:=SMX-OldSMX,OldSMX:=SMX,DSY:=SMY-OldSMY,OldSMY:=SMY
if (DSX>50) ;смещение вправо
send {vk33}
if (DSX<-50) ;смещение влево
send {vk31}
if (DSY>50) ;смещение вниз
send {vk34}
if (DSY<-50) ;смещение вверх
send {vk32}
Return 

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;          Пробел-Включение мыши-джойстика         ;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
*Space::md.SetState(1)
*Space up::md.SetState(0)

End::ExitApp

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;               Мышь-блокировка камеры             ;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MouseEvent(MouseID, x := 0, y := 0){
global SMX,SMY
	if (MouseID)
	{
	SMX+=x,SMY+=y
	DllCall("mouse_event",uint,1,int,-x,int,-y,uint,0,int,0)
	}
}

В этом коде частота опроса мыши роли почти не играет, но мышь работает лучше (меньше смещение камеры во время блокировки) на частоте 1000Гц. Здесь также нужен в директории скрипта файл MouseDelta.ahk.

9

Re: AHK:Умная мышь или да здравствует хэдшот!

Мышь-джойстик
Вот рабочий вариант предыдущего кода:

 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;                     -Мышь-Джойстик-                  ;;;
;;;                  EasyHard, 28/12/2017г.              ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SMX:=OldSMX:=SMY:=OldSMY:=DSX:=DSY:=0
#SingleInstance force
#Persistent
#include MouseDelta.ahk
md:=new MouseDelta("MouseEvent").Start()
md.SetState(0)
SetTimer, SpeedMouse, 100


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;                Мышь-режим джойстика              ;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SpeedMouse:
DSX:=SMX-OldSMX,OldSMX:=SMX,DSY:=SMY-OldSMY,OldSMY:=SMY
if (DSX>50)
{
send {e down}
SetTimer, SpeedMouse, Off
SetTimer, Right1, -50
}

if (DSX<-50)
{
send {q down}
SetTimer, SpeedMouse, Off
SetTimer, Left1, -50
}

if (DSY>50)
{
send {s down}
SetTimer, SpeedMouse, Off
SetTimer, Down1, -50
}

if (DSY<-50)
{
send {w down}
SetTimer, SpeedMouse, Off
SetTimer, Up1, -50
}
Return 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;                        Метки                     ;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Right1:
send {e up}
SetTimer, Right2, -250
Return 
Right2: 
OldSMX:=SMX
SetTimer, SpeedMouse, On
Return  

Left1:
send {q up}
SetTimer, Left2, -250
Return 
Left2: 
OldSMX:=SMX
SetTimer, SpeedMouse, On
Return  

Down1:
send {s up}
SetTimer, Down2, -250
Return 
Down2: 
OldSMY:=SMY
SetTimer, SpeedMouse, On
Return

Up1:
send {w up}
SetTimer, Up2, -250
Return 
Up2: 
OldSMY:=SMY
SetTimer, SpeedMouse, On
Return   
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;              Включение мыши-джойстика            ;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
*x::
send {LAlt Down}
md.SetState(1)
Return 
*x up::
send {LAlt Up}
md.SetState(0)
Return 

End::ExitApp

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;               Мышь-блокировка камеры             ;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MouseEvent(MouseID, x := 0, y := 0){
global SMX,SMY
	if (MouseID)
	{
	SMX+=x,SMY+=y
	DllCall("mouse_event",uint,1,int,-x,int,-y,uint,0,int,0)
	}
}

10

Re: AHK:Умная мышь или да здравствует хэдшот!

Моя древняя мышь не поддерживает почему-то деление DPI, за то прекрасно умножает его. sabir.yanin2014 Немного переделал твой скрипт, теперь он постоянно ускоряет мышь, а по нажатию кнопки, возвращает ей нормальную скорость. В итоге выкручиваю в игре чувствительность на минимум и настраиваю переменные скрипта под свои нужды, получается подобие SniperButton. Двойное нажатие LWin выключает данную ф-ию.


SMX:=OldSMX:=SMY:=OldSMY:=DSX:=DSY:=0
#SingleInstance force
#Persistent
#include MouseDelta.ahk
md:=new MouseDelta("MouseEvent").Start()
md.SetState(1)
SetTimer, SpeedMouse, 10

slow:=1		;Пониженная скорость(slow <= 1)
smid:=2.5 	;Средняя множитель скорости мыши
shig:=5 	;Повышенный множитель скорости мыши
sstand:=smid	;Постоянный множитель скорости мыши


Focus := 0
sp := sstand
LWin:: Gosub, PressCount            ; Запускается счётчик нажатий.

LWin(1):                            ; Код для одиночного нажатия LWin.
  Focus := 1
Return

LWin(2):                            ; Код для двойного нажатия LWin.
  Focus := 0
Return

XButton2:: sp := slow
XButton2 up:: sp := sstand

~LAlt:: sp := shig
~LAlt up:: sp := sstand

SpeedMouse:
DSX:=abs(OldSMX-SMX),OldSMX:=SMX
DSY:=abs(OldSMY-SMY),OldSMY:=SMY
Return
MouseEvent(MouseID, x := 0, y := 0){
global SMX,SMY,Focus,sp
	if (MouseID)
	{
	SMX+=x
	SMY+=y
	if Focus
		{
		ShiftX:=x*sp
		ShiftY:=y*sp
		DllCall("mouse_event",uint,1,int,ShiftX,int,ShiftY,uint,0,int,0)
		}
	}
}




PressCount:
  Pause_=200     ; Если пауза меньше этого количества миллисекунд, то нажатие
                 ; двойное. Если больше, то оно расценивается как 2 одиночных.
  If not Second
  {
    Second=1
    SetTimer, DoublePress, -%Pause_%
  }
  Else
  {
    Second=0
    SetTimer, %A_ThisHotkey%(2), -1
  }
Return

DoublePress:
  If not Second
    Return
  Second=0
  SetTimer, %A_ThisHotkey%(1), -1
Return

Insert::Reload
End::ExitApp

11 (изменено: sabir.yanin2014, 2018-01-02 16:04:08)

Re: AHK:Умная мышь или да здравствует хэдшот!

Yasen', в принципе так и было задумано автором. Но мне не понравилось умножение потому что картинка постоянно дергается-раздражает. При делении такое меньше происходит. Картинка плавнее, практически незаметно вмешательство. Я думаю все таки возможно мой код, незначительно переделав, приспособить под деление и на высоких частотах опроса мыши - для этого нужно формировать пакеты: суммировать их до тех пор пока не станет возможным деление.

12

Re: AHK:Умная мышь или да здравствует хэдшот!

Доработал код, теперь частоту опроса мыши можно не настраивать- работает с любой мышью.


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;                      --Умная мышь--                  ;;;
;;;                  EasyHard, 21/12/2018г.              ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SMX:=OldSMX:=SMY:=OldSMY:=DSX:=DSY:=PacX:=PacY:=0
#SingleInstance force
#Persistent
#include MouseDelta.ahk
md:=new MouseDelta("MouseEvent").Start()
md.SetState(0)
SetTimer, SpeedMouse, 50

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;   Вычисление скорости перемещения физической мыши    ;;;
;;;    /автоматический выбор режима(авт.смена DPI)       ;;; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SpeedMouse:
DSX:=abs(OldSMX-SMX),OldSMX:=SMX,DSY:=abs(OldSMY-SMY),OldSMY:=SMY
if (DSX>30 or DSY>30) ;настраиваемые параметры-можно поэкспериментировать
Focus:=0 ;"быстрая мышь"-"режим-упреждение"-DPI базовый(настройка чувств.мыши/у меня 800DPI)
else 
Focus:=1 ;"точная мышь"-"режим-прицеливание"-измененный DPI(800/2=400)
Return 

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;         ПКМ-Включение режима прицеливания        ;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
*RButton::md.SetState(1)
*RButton up::md.SetState(0)

End::ExitApp

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;         Мышь-Регулирование скорости обзора       ;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MouseEvent(MouseID, x := 0, y := 0){
global SMX,SMY,Focus,PacX,PacY
	if (MouseID)
	{
	SMX+=x,SMY+=y
	if Focus
	PacX+=x,PacY+=y
	else
	PacX:=0,PacY:=0
	if (Focus and abs(PacX)>=4)
		{
		ShiftX:=PacX//2
		DllCall("mouse_event",uint,1,int,-ShiftX,int,0,uint,0,int,0)
		PacX:=0
		}
	if (Focus and abs(PacY)>=4)
		{
		ShiftY:=PacY//2
		DllCall("mouse_event",uint,1,int,0,int,-ShiftY,uint,0,int,0)
		PacY:=0
		}
	}
}

13

Re: AHK:Умная мышь или да здравствует хэдшот!

Что интересно все тачпады ноутбуков работают по такому же алгоритму:
скорость курсора = скорости перемещения пальца в квадрате.
Причем там это все сделано на уровне драйверов и никак не регулируется.

14 (изменено: sabir.yanin2014, 2018-04-15 16:51:40)

Re: AHK:Умная мышь или да здравствует хэдшот!

Новый улучшенный код.
В основе лежит все та же идея - автоматический мониторинг активности мыши: при быстром перемещении мыши скрипт не вмешивается в её работу; при замедленном движении скрипт снижает чувствительность мыши что позволяет делать ее более точной. Данный код я настраивал на сайте, что позволило мне объективно увидеть эффективность кода: я набил на 7000 больше чем обычно.
Мышь стала более точной, и теперь я могу попадать в более мелкие цели. Базовая настройка DPI=800. В режиме фокуса этот параметр скрипт снижает до 400 (точная мышь).
В отличии от предыдущих версий кода режим прицеливания включается автоматически, а не при нажатии горячей клавиши (т.е. скрипт работает постоянно с момента запуска). Данный подход дает преимущества в играх где нет явного прицеливания например: "Prey" или  онлайн-игры ("Doom" и др.).


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;                    --Умная мышь--                  ;;;
;;;                 Claus555, 15/04/2018г.             ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
#Persistent
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;              Создание  таймера 7,8(мс)           ;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ZX:=0
;приближение к таймеру 10 мс 
SetTimer, S1, 15 
loop {
++ZX
if (ZX=18720) 
Break   
}
SetTimer, S2, 15

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;                      MouseDelta                  ;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PacX:=PacY:=SMX:=SMY:=0,ArrSMX:=[],ArrSMY:=[],Focus:=1
#include MouseDelta.ahk
md:=new MouseDelta("MouseEvent").Start()
md.SetState(1)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;              Мышь-Переключение фокуса            ;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
S1:
S2:
ArrSMX.Push(SMX),ArrSMY.Push(SMY),SpTime:=40 ; 40*7,8 = 312мс-период расчета скорости
if (ArrSMX.Length()=SpTime and ArrSMY.Length()=SpTime){
DSX:=ArrSMX[SpTime]-ArrSMX[1],DSY:=ArrSMY[SpTime]-ArrSMY[1]
Speed:=sqrt(DSX*DSX+DSY*DSY)
ArrSMX.RemoveAt(1),ArrSMY.RemoveAt(1)
}
While if (ArrSMX.Length()>SpTime-1)
ArrSMX.RemoveAt(1)
While if (ArrSMY.Length()>SpTime-1)
ArrSMY.RemoveAt(1)

if (Speed>=50)
Focus:=0

START1:=(Speed<50)?1:0 ;пуск таймера
START:=T(D("START1"),"START",100) ;таймер 100мс
if (U("START") and Speed<50) ;если по оканчании 100мс скорость ниже 50
Focus:=1 ;мышь замедлилась-включить фокус

Return

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;         Мышь-Регулирование скорости обзора       ;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MouseEvent(MouseID, x := 0, y := 0){
global SMX,SMY,Focus,PacX,PacY
	if (MouseID)
	{
	SMX+=x,SMY+=y
	if Focus
	PacX+=x,PacY+=y
	else
	PacX:=0,PacY:=0
	if (Focus and abs(PacX)>=2)
		{
		ShiftX:=PacX//2
		DllCall("mouse_event",uint,1,int,-ShiftX,int,0,uint,0,int,0)
		PacX:=0
		}
	if (Focus and abs(PacY)>=2)
		{
		ShiftY:=PacY//2
		DllCall("mouse_event",uint,1,int,0,int,-ShiftY,uint,0,int,0)
		PacY:=0
		}
	}
}

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;                    Срабатывание                  ;;;;                                                                                                                                                                                                                                      ;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
D(X)
{
local Z
Z:=(%X%!=d%X% and %X%)?1:0,d%X%:=%X%
Return Z
}

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;                      Отпадание                   ;;;;                                                                                                                                                                                                                                      ;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
U(X)
{
local Z
Z:=(%X%!=u%X% and u%X%)?1:0,u%X%:=%X%
Return Z
}

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;                       Таймер                     ;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
T(X,Y,V)
{
global 
if (X and !T1%Y%)
T1%Y%:=1,T2%Y%:=A_TickCount

if (T2%Y%="" or A_TickCount-T2%Y%>=V)
T1%Y%:=0

Return T1%Y%
}

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;            Завершение работы скрипта             ;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
End::ExitApp 

Код разбит на две части основной файл и подгружаемый "MouseDelta.ahk" который нужно расположить в директории основного.
"MouseDelta.ahk":



; Instantiate this class and pass it a func name or a Function Object
; The specified function will be called with the delta move for the X and Y axes
; Normally, there is no windows message "mouse stopped", so one is simulated.
; After 10ms of no mouse movement, the callback is called with 0 for X and Y
Class MouseDelta {
	State := 0
	__New(callback){
		;~ this.TimeoutFn := this.TimeoutFunc.Bind(this)
		this.MouseMovedFn := this.MouseMoved.Bind(this)

		this.Callback := callback
	}

	Start(){
		static DevSize := 8 + A_PtrSize, RIDEV_INPUTSINK := 0x00000100
		; Register mouse for WM_INPUT messages.
		VarSetCapacity(RAWINPUTDEVICE, DevSize)
		NumPut(1, RAWINPUTDEVICE, 0, "UShort")
		NumPut(2, RAWINPUTDEVICE, 2, "UShort")
		NumPut(RIDEV_INPUTSINK, RAWINPUTDEVICE, 4, "Uint")
		; WM_INPUT needs a hwnd to route to, so get the hwnd of the AHK Gui.
		; It doesn't matter if the GUI is showing, it still exists
		Gui +hwndhwnd
		NumPut(hwnd, RAWINPUTDEVICE, 8, "Uint")
 
		this.RAWINPUTDEVICE := RAWINPUTDEVICE
		DllCall("RegisterRawInputDevices", "Ptr", &RAWINPUTDEVICE, "UInt", 1, "UInt", DevSize )
		OnMessage(0x00FF, this.MouseMovedFn)
		this.State := 1
		return this	; allow chaining
	}
	
	Stop(){
		static RIDEV_REMOVE := 0x00000001
		static DevSize := 8 + A_PtrSize
		OnMessage(0x00FF, this.MouseMovedFn, 0)
		RAWINPUTDEVICE := this.RAWINPUTDEVICE
		NumPut(RIDEV_REMOVE, RAWINPUTDEVICE, 4, "Uint")
		DllCall("RegisterRawInputDevices", "Ptr", &RAWINPUTDEVICE, "UInt", 1, "UInt", DevSize )
		this.State := 0
		return this	; allow chaining
	}
	
	SetState(state){
		if (state && !this.State)
			this.Start()
		else if (!state && this.State)
			this.Stop()
		return this	; allow chaining
	}

	Delete(){
		this.Stop()
		;~ this.TimeoutFn := ""
		this.MouseMovedFn := ""
	}
	
	; Called when the mouse moved.
	; Messages tend to contain small (+/- 1) movements, and happen frequently (~20ms)
	MouseMoved(wParam, lParam){
		Critical
		; RawInput statics
		static DeviceSize := 2 * A_PtrSize, iSize := 0, sz := 0, pcbSize:=8+2*A_PtrSize, offsets := {x: (20+A_PtrSize*2), y: (24+A_PtrSize*2)}, uRawInput
 
		static axes := {x: 1, y: 2}
 
		; Get hDevice from RAWINPUTHEADER to identify which mouse this data came from
		VarSetCapacity(header, pcbSize, 0)
		If (!DllCall("GetRawInputData", "UPtr", lParam, "uint", 0x10000005, "UPtr", &header, "Uint*", pcbSize, "Uint", pcbSize) or ErrorLevel)
			Return 0
		ThisMouse := NumGet(header, 8, "UPtr")

		; Find size of rawinput data - only needs to be run the first time.
		if (!iSize){
			r := DllCall("GetRawInputData", "UInt", lParam, "UInt", 0x10000003, "Ptr", 0, "UInt*", iSize, "UInt", 8 + (A_PtrSize * 2))
			VarSetCapacity(uRawInput, iSize)
		}
		sz := iSize	; param gets overwritten with # of bytes output, so preserve iSize
		; Get RawInput data
		r := DllCall("GetRawInputData", "UInt", lParam, "UInt", 0x10000003, "Ptr", &uRawInput, "UInt*", sz, "UInt", 8 + (A_PtrSize * 2))
 
		x := 0, y := 0	; Ensure we always report a number for an axis. Needed?
		x := NumGet(&uRawInput, offsets.x, "Int")
		y := NumGet(&uRawInput, offsets.y, "Int")
 
		this.Callback.(ThisMouse, x, y)
 
		;~ ; There is no message for "Stopped", so simulate one
		;~ fn := this.TimeoutFn
		;~ SetTimer, % fn, -50
	}
 
	;~ TimeoutFunc(){
		;~ this.Callback.("", 0, 0)
	;~ }
 
}

Для тех кто не знает что такое #include, вот полный код c "MouseDelta". Он работоспособен и не требует дополнительных файлов.


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;                    --Умная мышь--                  ;;;
;;;                 Claus555, 15/04/2018г.             ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
#Persistent
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;              Создание  таймера 7,8(мс)           ;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ZX:=0
;приближение к таймеру 10 мс 
SetTimer, S1, 15 
loop {
++ZX
if (ZX=18720) 
Break   
}
SetTimer, S2, 15

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;                      MouseDelta                  ;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PacX:=PacY:=SMX:=SMY:=0,ArrSMX:=[],ArrSMY:=[],Focus:=1

; Instantiate this class and pass it a func name or a Function Object
; The specified function will be called with the delta move for the X and Y axes
; Normally, there is no windows message "mouse stopped", so one is simulated.
; After 10ms of no mouse movement, the callback is called with 0 for X and Y
Class MouseDelta {
	State := 0
	__New(callback){
		;~ this.TimeoutFn := this.TimeoutFunc.Bind(this)
		this.MouseMovedFn := this.MouseMoved.Bind(this)

		this.Callback := callback
	}

	Start(){
		static DevSize := 8 + A_PtrSize, RIDEV_INPUTSINK := 0x00000100
		; Register mouse for WM_INPUT messages.
		VarSetCapacity(RAWINPUTDEVICE, DevSize)
		NumPut(1, RAWINPUTDEVICE, 0, "UShort")
		NumPut(2, RAWINPUTDEVICE, 2, "UShort")
		NumPut(RIDEV_INPUTSINK, RAWINPUTDEVICE, 4, "Uint")
		; WM_INPUT needs a hwnd to route to, so get the hwnd of the AHK Gui.
		; It doesn't matter if the GUI is showing, it still exists
		Gui +hwndhwnd
		NumPut(hwnd, RAWINPUTDEVICE, 8, "Uint")
 
		this.RAWINPUTDEVICE := RAWINPUTDEVICE
		DllCall("RegisterRawInputDevices", "Ptr", &RAWINPUTDEVICE, "UInt", 1, "UInt", DevSize )
		OnMessage(0x00FF, this.MouseMovedFn)
		this.State := 1
		return this	; allow chaining
	}
	
	Stop(){
		static RIDEV_REMOVE := 0x00000001
		static DevSize := 8 + A_PtrSize
		OnMessage(0x00FF, this.MouseMovedFn, 0)
		RAWINPUTDEVICE := this.RAWINPUTDEVICE
		NumPut(RIDEV_REMOVE, RAWINPUTDEVICE, 4, "Uint")
		DllCall("RegisterRawInputDevices", "Ptr", &RAWINPUTDEVICE, "UInt", 1, "UInt", DevSize )
		this.State := 0
		return this	; allow chaining
	}
	
	SetState(state){
		if (state && !this.State)
			this.Start()
		else if (!state && this.State)
			this.Stop()
		return this	; allow chaining
	}

	Delete(){
		this.Stop()
		;~ this.TimeoutFn := ""
		this.MouseMovedFn := ""
	}
	
	; Called when the mouse moved.
	; Messages tend to contain small (+/- 1) movements, and happen frequently (~20ms)
	MouseMoved(wParam, lParam){
		Critical
		; RawInput statics
		static DeviceSize := 2 * A_PtrSize, iSize := 0, sz := 0, pcbSize:=8+2*A_PtrSize, offsets := {x: (20+A_PtrSize*2), y: (24+A_PtrSize*2)}, uRawInput
 
		static axes := {x: 1, y: 2}
 
		; Get hDevice from RAWINPUTHEADER to identify which mouse this data came from
		VarSetCapacity(header, pcbSize, 0)
		If (!DllCall("GetRawInputData", "UPtr", lParam, "uint", 0x10000005, "UPtr", &header, "Uint*", pcbSize, "Uint", pcbSize) or ErrorLevel)
			Return 0
		ThisMouse := NumGet(header, 8, "UPtr")

		; Find size of rawinput data - only needs to be run the first time.
		if (!iSize){
			r := DllCall("GetRawInputData", "UInt", lParam, "UInt", 0x10000003, "Ptr", 0, "UInt*", iSize, "UInt", 8 + (A_PtrSize * 2))
			VarSetCapacity(uRawInput, iSize)
		}
		sz := iSize	; param gets overwritten with # of bytes output, so preserve iSize
		; Get RawInput data
		r := DllCall("GetRawInputData", "UInt", lParam, "UInt", 0x10000003, "Ptr", &uRawInput, "UInt*", sz, "UInt", 8 + (A_PtrSize * 2))
 
		x := 0, y := 0	; Ensure we always report a number for an axis. Needed?
		x := NumGet(&uRawInput, offsets.x, "Int")
		y := NumGet(&uRawInput, offsets.y, "Int")
 
		this.Callback.(ThisMouse, x, y)
 
		;~ ; There is no message for "Stopped", so simulate one
		;~ fn := this.TimeoutFn
		;~ SetTimer, % fn, -50
	}
 
	;~ TimeoutFunc(){
		;~ this.Callback.("", 0, 0)
	;~ }
 
}

md:=new MouseDelta("MouseEvent").Start()
md.SetState(1)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;              Мышь-Переключение фокуса            ;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
S1:
S2:
ArrSMX.Push(SMX),ArrSMY.Push(SMY),SpTime:=40 ; 40*7,8 = 312мс-период расчета скорости
if (ArrSMX.Length()=SpTime and ArrSMY.Length()=SpTime){
DSX:=ArrSMX[SpTime]-ArrSMX[1],DSY:=ArrSMY[SpTime]-ArrSMY[1]
Speed:=sqrt(DSX*DSX+DSY*DSY)
ArrSMX.RemoveAt(1),ArrSMY.RemoveAt(1)
}
While if (ArrSMX.Length()>SpTime-1)
ArrSMX.RemoveAt(1)
While if (ArrSMY.Length()>SpTime-1)
ArrSMY.RemoveAt(1)

if (Speed>=50)
Focus:=0

START1:=(Speed<50)?1:0 ;пуск таймера
START:=T(D("START1"),"START",100) ;таймер 100мс
if (U("START") and Speed<50) ;если по оканчании 100мс скорость ниже 50
Focus:=1 ;мышь замедлилась-включить фокус

Return

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;         Мышь-Регулирование скорости обзора       ;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MouseEvent(MouseID, x := 0, y := 0){
global SMX,SMY,Focus,PacX,PacY
	if (MouseID)
	{
	SMX+=x,SMY+=y
	if Focus
	PacX+=x,PacY+=y
	else
	PacX:=0,PacY:=0
	if (Focus and abs(PacX)>=2)
		{
		ShiftX:=PacX//2
		DllCall("mouse_event",uint,1,int,-ShiftX,int,0,uint,0,int,0)
		PacX:=0
		}
	if (Focus and abs(PacY)>=2)
		{
		ShiftY:=PacY//2
		DllCall("mouse_event",uint,1,int,0,int,-ShiftY,uint,0,int,0)
		PacY:=0
		}
	}
}

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;                    Срабатывание                  ;;;;                                                                                                                                                                                                                                      ;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
D(X)
{
local Z
Z:=(%X%!=d%X% and %X%)?1:0,d%X%:=%X%
Return Z
}

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;                      Отпадание                   ;;;;                                                                                                                                                                                                                                      ;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
U(X)
{
local Z
Z:=(%X%!=u%X% and u%X%)?1:0,u%X%:=%X%
Return Z
}

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;                       Таймер                     ;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
T(X,Y,V)
{
global 
if (X and !T1%Y%)
T1%Y%:=1,T2%Y%:=A_TickCount

if (T2%Y%="" or A_TickCount-T2%Y%>=V)
T1%Y%:=0

Return T1%Y%
}

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;            Завершение работы скрипта             ;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
End::ExitApp 

Пусть кто нибудь ответит. Интересно чужое мнение .

15 (изменено: Leone_Galante, 2018-04-17 21:22:00)

Re: AHK:Умная мышь или да здравствует хэдшот!

Очень интересная идея! Но боюсь моих знаний не хватит хотя бы попробовать данный скрипт.  Принцип понял, наверное )) попробую. По результатам отпишусь.

16

Re: AHK:Умная мышь или да здравствует хэдшот!

Потестил в игре, комфортней играть.

17

Re: AHK:Умная мышь или да здравствует хэдшот!

Скрипт очень полезен не только для игр, но и приятней попадать мышкой по кнопкам интерфеса страиниц, окон и тд. Как  еще больше уменьшить степень чувствительности при выцеливании?

18

Re: AHK:Умная мышь или да здравствует хэдшот!

Существует аналог - GGGlide - Mouse Pointer Momentum.

19 (изменено: stealzy, 2018-07-15 22:47:56)

Re: AHK:Умная мышь или да здравствует хэдшот!

Если вести мышь на границе заданной скорости курсор двигается рывками из-за резкого перехода из режима в режим. Надо бы сгладить переход, а то прыжки раздражают.
UPD: Добавил SetBatchLines -1.

20 (изменено: sabir.yanin2014, 2019-02-03 22:03:52)

Re: AHK:Умная мышь или да здравствует хэдшот!

Последняя, стабильная версия. Убрал все лишнее. Как обычно эффективность прицеливания проверял на сайте. Результаты хорошие. Отдельное спасибо stealzy за его замечания, рывки убрал. Использовать SetBatchLines -1 не вижу необходимости, не такие уж тут бешенные вычисления.


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;                    --Умная мышь--                  ;;;
;;;                      28/07/2018г.                  ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
#Persistent
SetTimer, S1, 15 

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;                      MouseDelta                  ;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PacX:=PacY:=SMX:=SMY:=0,ArrSMX:=[],ArrSMY:=[],Focus:=1
#include MouseDelta.ahk
md:=new MouseDelta("MouseEvent").Start()
md.SetState(1)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;              Мышь-Переключение фокуса            ;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
S1:
ArrSMX.Push(SMX),ArrSMY.Push(SMY),SpTime:=20 ; 20*15,6 = 312мс-период расчета скорости
if (ArrSMX.Length()=SpTime and ArrSMY.Length()=SpTime){
DSX:=ArrSMX[SpTime]-ArrSMX[1],DSY:=ArrSMY[SpTime]-ArrSMY[1]
Speed:=sqrt(DSX*DSX+DSY*DSY)
ArrSMX.RemoveAt(1),ArrSMY.RemoveAt(1)
}
While if (ArrSMX.Length()>SpTime-1)
ArrSMX.RemoveAt(1)
While if (ArrSMY.Length()>SpTime-1)
ArrSMY.RemoveAt(1)


if (Speed>=100) ;мышь ускорилась-отключить фокус
Focus:=0

if (Speed<5) 
Focus:=1 ;мышь замедлилась-включить фокус

Return

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;         Мышь-Регулирование скорости обзора       ;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MouseEvent(MouseID, x := 0, y := 0){
global SMX,SMY,Focus,PacX,PacY
	if (MouseID)
	{
	SMX+=x,SMY+=y
	if Focus
	PacX+=x,PacY+=y
	else
	PacX:=0,PacY:=0
	if (Focus and abs(PacX)>=2)
		{
		ShiftX:=PacX//2
		DllCall("mouse_event",uint,1,int,-ShiftX,int,0,uint,0,int,0)
		PacX:=0
		}
	if (Focus and abs(PacY)>=2)
		{
		ShiftY:=PacY//2
		DllCall("mouse_event",uint,1,int,0,int,-ShiftY,uint,0,int,0)
		PacY:=0
		}
	}
}

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;            Завершение работы скрипта             ;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
End::ExitApp