Что нового

[Мышь, клавиатура] Эмуляция кликов в GTA Online

TpeTTep

Новичок
Сообщения
45
Репутация
1
Хэй гайс. Сделал простенького бота для GTA Online. Т.к делаю для себя, то не стал париться и пошел самым примитивным путём, используя MouseMove, MouseClick. В принципе все работает, но работать за компом, когда этот бот активен не представляется возможным. Это как минимум не удобно, особенно если у тебя дома не другого ПК, который мог бы осилить GTA Online. В поисках решения наткнулся на стандартную функцию ControlClick, но в игре это не работает. Цель всего этого заставить программу кликать в определённые места в игре, когда поверх неё открыт браузер, проводник, скайп. Т.е игра в данном случае открыта в оконном режиме, но без рамки. Разумеется в таком случае она не сворачивается, а все остальные окна открываются поверх неё. Не подскажите способ реализации данного вопроса?
 

eralex

Знающий
Сообщения
64
Репутация
5
Вариантов много, вот один из них:

Код:
Func _SendMessage_Click($hWnd, $BUTTON, $X, $Y, $CLICKS = 1, $delay = 15)
;$delay - пауза между 2мя нажатиями

	Local $MK_LBUTTON = 0x0001
	Local $WM_LBUTTONDOWN = 0x0201
	Local $WM_LBUTTONUP = 0x0202
	Local $MK_RBUTTON = 0x0002
	;Const $WM_LBUTTONDBLCLK = 0x0203
	Local $WM_RBUTTONDOWN = 0x0204
	Local $WM_RBUTTONUP = 0x205
	Local $WM_MOUSEMOVE = 0x200
	Local $i = 0
	Local $BUTTONDOWN = $WM_LBUTTONDOWN
	Local $BUTTONUP = $WM_LBUTTONUP
	$button = StringLower($button)


	Local $user32 = DllOpen("user32.dll")

	If $button = "left" Then
	For $i = 1 To $CLICKS
		DllCall($user32, "int", "SendMessage", "hwnd", $hWnd, "int", $WM_MOUSEMOVE, "int", 0, "long", _MAKELONG($X, $Y))
		DllCall($user32, "int", "SendMessage", "hwnd", $hWnd, "int", $WM_LBUTTONDOWN, "int", $MK_LBUTTON, "long", _MAKELONG($X, $Y))
		DllCall($user32, "int", "SendMessage", "hwnd", $hWnd, "int", $WM_LBUTTONUP, "int", 0, "long", _MAKELONG($X, $Y))

		If $i < $CLICKS Then Sleep($delay)
	Next
	ElseIf $button = "right" Then
		For $i = 1 To $CLICKS
		DllCall($user32, "int", "SendMessage", "hwnd", $hWnd, "int", $WM_MOUSEMOVE, "int", 0, "long", _MAKELONG($X, $Y))
		DllCall($user32, "int", "SendMessage", "hwnd", $hWnd, "int", $WM_RBUTTONDOWN, "int", $MK_RBUTTON, "long", _MAKELONG($X, $Y))
		DllCall($user32, "int", "SendMessage", "hwnd", $hWnd, "int", $WM_RBUTTONUP, "int", 0, "long", _MAKELONG($X, $Y))

		If $i < $CLICKS Then Sleep($delay)
	Next
	Else
		SetError(-2)
		If $user32 <> -1 Then DllClose($user32)
		Return
	    EndIf

	If $user32 <> -1 Then DllClose($user32)
EndFunc

Func _MakeLong($LoWord,$HiWord)
  Return BitOR($HiWord * 0x10000, BitAND($LoWord, 0xFFFF))
EndFunc
 
Автор
T

TpeTTep

Новичок
Сообщения
45
Репутация
1
eralex сказал(а):
Вариантов много, вот один из них:

Код:
Func _SendMessage_Click($hWnd, $BUTTON, $X, $Y, $CLICKS = 1, $delay = 15)
;$delay - пауза между 2мя нажатиями

	Local $MK_LBUTTON = 0x0001
	Local $WM_LBUTTONDOWN = 0x0201
	Local $WM_LBUTTONUP = 0x0202
	Local $MK_RBUTTON = 0x0002
	;Const $WM_LBUTTONDBLCLK = 0x0203
	Local $WM_RBUTTONDOWN = 0x0204
	Local $WM_RBUTTONUP = 0x205
	Local $WM_MOUSEMOVE = 0x200
	Local $i = 0
	Local $BUTTONDOWN = $WM_LBUTTONDOWN
	Local $BUTTONUP = $WM_LBUTTONUP
	$button = StringLower($button)


	Local $user32 = DllOpen("user32.dll")

	If $button = "left" Then
	For $i = 1 To $CLICKS
		DllCall($user32, "int", "SendMessage", "hwnd", $hWnd, "int", $WM_MOUSEMOVE, "int", 0, "long", _MAKELONG($X, $Y))
		DllCall($user32, "int", "SendMessage", "hwnd", $hWnd, "int", $WM_LBUTTONDOWN, "int", $MK_LBUTTON, "long", _MAKELONG($X, $Y))
		DllCall($user32, "int", "SendMessage", "hwnd", $hWnd, "int", $WM_LBUTTONUP, "int", 0, "long", _MAKELONG($X, $Y))

		If $i < $CLICKS Then Sleep($delay)
	Next
	ElseIf $button = "right" Then
		For $i = 1 To $CLICKS
		DllCall($user32, "int", "SendMessage", "hwnd", $hWnd, "int", $WM_MOUSEMOVE, "int", 0, "long", _MAKELONG($X, $Y))
		DllCall($user32, "int", "SendMessage", "hwnd", $hWnd, "int", $WM_RBUTTONDOWN, "int", $MK_RBUTTON, "long", _MAKELONG($X, $Y))
		DllCall($user32, "int", "SendMessage", "hwnd", $hWnd, "int", $WM_RBUTTONUP, "int", 0, "long", _MAKELONG($X, $Y))

		If $i < $CLICKS Then Sleep($delay)
	Next
	Else
		SetError(-2)
		If $user32 <> -1 Then DllClose($user32)
		Return
	    EndIf

	If $user32 <> -1 Then DllClose($user32)
EndFunc

Func _MakeLong($LoWord,$HiWord)
  Return BitOR($HiWord * 0x10000, BitAND($LoWord, 0xFFFF))
EndFunc

Это не работает. Да и подобный вариант я уже использовал. Самое интересное, что этот даже в проводнике не работает
 

eralex

Знающий
Сообщения
64
Репутация
5
Возможно вы неправильно определяете hWnd, куда надо кликать.
Была у меня проблема с этим в одной онлайн-игре.
Сравните хэндлы, которые выдаёт ваша программа и autoit window info.
 
Автор
T

TpeTTep

Новичок
Сообщения
45
Репутация
1
eralex сказал(а):
Возможно вы неправильно определяете hWnd, куда надо кликать.
Была у меня проблема с этим в одной онлайн-игре.
Сравните хэндлы, которые выдаёт ваша программа и autoit window info.

Handle сравнил, они одинаковые
 

eralex

Знающий
Сообщения
64
Репутация
5
Тогда сделай так - есть прога Spy++.

Посмотри в ней какие команды идут при клике мыши в игре.

В меню Spy - Log Messages - через Finder Tool наводишь мишеньку на окно с игрой,
а в следующей вкладке оставь галочку только на событиях от мыши, остальные сними
 
Автор
T

TpeTTep

Новичок
Сообщения
45
Репутация
1
eralex сказал(а):
Тогда сделай так - есть прога Spy++.

Посмотри в ней какие команды идут при клике мыши в игре.

В меню Spy - Log Messages - через Finder Tool наводишь мишеньку на окно с игрой,
а в следующей вкладке оставь галочку только на событиях от мыши, остальные сними

Это сработало. Вот что из этого получилось. Попутно я так же снял события типа MouseMove,MouseActive,Setcursor и оставил только клики. Не знаю насколько правильно это, просто эти события слишком сильно засоряли лог.

Самое интересное, что если запустить скрипт и поставить программу на отслеживание, то она ловит запросы, который посылает туда Autoit. Но что-то меня настораживает вот эти Return'ы c Result'ом 00000000. В общем клик в игре не проходит(
 

Вложения

  • 2018-06-04_204649.png
    2018-06-04_204649.png
    9.4 КБ · Просмотры: 13
  • 2018-06-04_213512.png
    2018-06-04_213512.png
    42.1 КБ · Просмотры: 21

eralex

Знающий
Сообщения
64
Репутация
5
Так, а ты окно с игрой делал активным, именно активным?

У меня была таже проблема в одной онлайн-игре(Drakensang Online), пока не догадался тупо кликнуть внутри игры (по банке со здоровьем).
Только после этого программные клики мыши внутри игры заработали.
 
Автор
T

TpeTTep

Новичок
Сообщения
45
Репутация
1
eralex сказал(а):
Так, а ты окно с игрой делал активным, именно активным?

У меня была таже проблема в одной онлайн-игре(Drakensang Online), пока не догадался тупо кликнуть внутри игры (по банке со здоровьем).
Только после этого программные клики мыши внутри игры заработали.

Да, я как только не пытался клик поймать. Мне кажется, что перед запросами на движение мышки и клики нужно посылать ещё какой-то запрос. Не спроста же он на каждый запрос Result 00000000 возвращает. Причем если самому кликать, то таких Return'ов нет.
 

eralex

Знающий
Сообщения
64
Репутация
5
Скинь скрин с этими resulta-ми, никогда не видел
 
Автор
T

TpeTTep

Новичок
Сообщения
45
Репутация
1
eralex сказал(а):
Скинь скрин с этими resulta-ми, никогда не видел

Я выше приложил 2 скрина. На втором после каждого запроса идет Return с Result'ом 00000000. Другими словами тебе намекают, что операция не прошла. По крайней мере я это так понимаю.
 

eralex

Знающий
Сообщения
64
Репутация
5
Ну тут мои познания заканчиваются, надо гуру спрашивать.
Там ответ сервера приходит, что типа всё нормально, команда принята.
 

nowost

Знающий
Сообщения
178
Репутация
17
вроде, на сколько я помню, игра не должна быть свернутой, тоесть она должна быть развернута, пусть даже поверх неё открыты другие приложения.
 
Верх