Что нового

Мышь, клавиатура Простейший кликер для игры

concolor

Новичок
Сообщения
4
Репутация
0
Здрасте, ребят! Я только-только начал изучать autoit - не судите пж строго. Вовсе не уверен, что моя тема относится именно к теме "продвинутой автоматизации" - формально, мне нужно написать простейший кликер для игры, но, все же, это относится именно к категории "ботов". Дело в том, что хочу играть, но не имею банально времени на добычу ресурсов в игре, чтобы вот так сидеть часами и тупо кликать по кучке руды, например) Возникла идея автоматизировать этот процесс. Всего, вроде, и требуется, чтобы с определенным интервалом времени в окно игры подавалось нажатие клавиши "f" ( Send() в цикле с задержками ). Но, не получается. Autoit ведёт себя очень капризно. При всех равных он то посылает в игру нужное нажатие, то нет. Принципа понять не могу. А в цикле вообще не получается выполнить дальше первого действия. Я сталкивался и с c++, и с php. и с javascript, но тут не могу понять логики. В общем, если подскажете, как корректно тут написать код - буду оч признателен. Может я просто тупо что-то не понимаю ещё. Публикую код, упрощённый до неузнаваемости) Если что - запускаю exeшник с правами администратора и всё такое.

Код:
Global $name="ArcheAge"
Global $process="ArcheAge.exe"
Global $hWnd
Opt("SendKeyDownDelay", 40)
Opt("WinTitleMatchMode", 2)                         ; чтобы с каждым обновлением не переделывать, так как в title окна входит build и дата

If ProcessExists($process) Then                      ; если игра запущена..
    $hWnd = WinActivate($name)                     ; активируем окно игры..
    WinWaitActive($hWnd, "", 10)                      ; ждём
    If Not $hWnd Then                                        ; если что, сообщаем, что не удалось и выходим
        MsgBox(4096, 'Info', 'Not Actived')
        Exit
    EndIf
        While 1                                                        ; иначе запускаем бесконечный цикл..
            Send("f")                                                 ; чтобы гномик ковырял руду))    
        WEnd
Else
    Exit
EndIf


И, кстати да, у игры есть защита от ботов. Называется VK Play Anti-Cheat service. Но, думаю, если бы в этом было дело - античит гасил бы все мои старания, а не только некоторые. Как уже сказал - то Send() работает, то нет.
Сообщение автоматически объединено:

Ребят, ну!) Неужели никто не поможет со скриптом? Неужели нет никаких идей, почему он может работать так нестабильно?
 
Последнее редактирование:

Prog

Продвинутый
Сообщения
537
Репутация
65
Неужели нет никаких идей, почему он может работать так нестабильно?
Я сталкивался и с c++, и с php. и с javascript, но тут не могу понять логики.
Если бы вы с ними сталкивались, то знали что нет смысла заспамнивать окно миллионами эмуляций в секунду.
Окно может стать неактивным, а в скрипте нет проверки такой ситуации.
Неудивительно что работает нестабильно.

Прочитайте справку https://autoit-script.ru/docs/functions/send.htm
В частности про паузы
Opt("SendKeyDelay",...) изменяет продолжительность паузы между эмулированными нажатиями клавиш.
Opt("SendKeyDownDelay",...) изменяет продолжительность нажатого состояния клавиши, перед тем как её отпустить.
В цикл добавьте Sleep().
 

All2khoff

Продвинутый
Сообщения
352
Репутация
65
Чуть чуть переделал заготовку. Все проверки на наличие окна и активность окна в цикле и если они пройдены то жать кнопку 10 раз в секунду.
Код:
Global $name="ArcheAge"
Global $process="ArcheAge.exe"
Global $hWnd
Opt("SendKeyDownDelay", 40)
Opt("WinTitleMatchMode", 2)                         ; чтобы с каждым обновлением не переделывать, так как в title окна входит build и дата

While 1
    If ProcessExists($process) Then                    ; если игра запущена..
        $hWnd = WinActivate($name)                    ; активируем окно игры..
        WinWaitActive($hWnd, "", 10)                ; ждём
        If Not $hWnd Then                            ; если что, сообщаем в кренсоль, что не удалось
            ConsoleWrite( 'Not Actived'&@CRLF)
            Sleep("10000")                            ;Ждем 10 секунд если акно не активно
        EndIf
        Send("f")                                    ; чтобы гномик ковырял руду))
        Sleep("100")
    EndIf
WEnd
 
Автор
C

concolor

Новичок
Сообщения
4
Репутация
0
Если бы вы с ними сталкивались, то знали что нет смысла заспамнивать окно миллионами эмуляций в секунду.
Окно может стать неактивным, а в скрипте нет проверки такой ситуации.
Неудивительно что работает нестабильно.
Дружище, вот зачем Вы так?) Вы ставите под сомнение мои слова, не задумываясь, какой мне вообще смысл тут кого-то обманывать? Другой вопрос - то что последний свой код я писал достаточно давно и сейчас сильно порастерял навыки. И да, естественно, я в первую очередь начал экспериментировать со "слипами" и длиной задержки. У меня даже в посте это явно прописано - "... Send() в цикле с задержками... " Но я же написал, вроде, что очень сильно упростил код и оставил только основное? Хотя, да, возможно и sleep() тоже нужно было оставить. А насчёт того, что окно может терять фокус и это нужно проверять каждую итерацию - дельная мысль, за это спасибо!
Чуть чуть переделал заготовку. Все проверки на наличие окна и активность окна в цикле и если они пройдены то жать кнопку 10 раз в секунду.
Огромное спасибо! Теперь вижу, что так будет правильнее! Проверю, о результате отпишусь!

Кстати, возникла тут мысля... Анти-чит же может проверять поступающие в игру данные на "человечность"? Может быть имеет смысл попробовать рандомизировать длину всех нажатий и паузы между ними? И/или вставить в какие-то произвольные движения мышью, например, внутри цикла? Может быть именно поэтому срабатывает только первый вход символа "f" в окно, а последующие нет? Как считаете?
 
Последнее редактирование:

SealAlbinos

Продвинутый
Сообщения
154
Репутация
57
я бы еще предложил отказаться от send
и использовать другую эмуляцию нажатия keybd_event
Код:
#RequireAdmin
$dll = DllOpen("user32.dll")
$keyCode = 70 ; f
sleep(1000)
DllCall($dll,"int","keybd_event","int",$keyCode,"int",0,"long",0,"long",0) ; - нажатие
DllCall($dll,"int","keybd_event","int",$keyCode,"int",0,"long",2,"long",0) ; - отжатие
DllClose($dll)
 

All2khoff

Продвинутый
Сообщения
352
Репутация
65
поступающие в игру данные на "человечность"? Может быть имеет смысл попробовать рандомизировать
редкое явление... но всегда можно сделать отслеживание сложнее.
Код:
Send("f")                                    ; чтобы гномик ковырял руду))
Sleep(Random(100-50,100+50,1))
 
Автор
C

concolor

Новичок
Сообщения
4
Репутация
0
Такой вот вариант не работает:

Код:
Global $name="ArcheAge"
Global $process="ArcheAge.exe"
Global $hWnd
Opt("SendKeyDownDelay", 40)
Opt("WinTitleMatchMode", 2)                         ; чтобы с каждым обновлением не переделывать, так как в title окна входит build и дата

While 1
    If ProcessExists($process) Then                    ; если игра запущена..
        $hWnd = WinActivate($name)                    ; активируем окно игры..
        WinWaitActive($hWnd, "", 10)                ; ждём
        If Not $hWnd Then                            ; если что, сообщаем в консоль, что не удалось
            ConsoleWrite( 'Not Actived'&@CRLF)
            Sleep("10000")                            ;Ждем 10 секунд если окно не активно
        EndIf
        Send("f")                                    ; чтобы гномик ковырял руду))
        Sleep(Random(100-50,100+50,1))
    EndIf
WEnd


Срабатывает в лучшем случае только первая отправка нажатия клавиши в окно. Значит дело не в том, что окно теряет фокус, как минимум. Далее попробую уйти от Send() совету SealAlbinos. Как проверю - отпишусь.
Сообщение автоматически объединено:

Проверил вариант с вызовом функции dll - абсолютно та же картина: окно игры открывается, персонаж выполняет первое действие и дальше стоит, как истукан. Однако же я заметил одну очень любопытную деталь, которая, возможно, позволит понять, что же идёт не по плану. Дело в том, как уже говорил, персонаж выполняет лишь первое действие (первое нажатие 'f') и дальше может стоять хоть часами - ничего не произойдёт. Но вот если попробовать отобрать фокус у окна игры (открыть, например, другое окно, свернуть окно), сценарий тут же снова активирует окно игры обратно и персонаж снова выполняет первое действие и снова остаётся стоять и бездельничать. То есть, в принципе, можно сделать вполне рабочий код, который просто перед тем как отослать в целевое окно нажатие клавиши, сначала бы просто сворачивал это окно, а потом тут же открывал назад. Однако, этот вариант очень уж похож на костыль для говнокода. К тому же мельтешение окна при работе скрипта будет изрядно раздражать. Хотелось бы понять, как всё же сделать правильно?
 
Последнее редактирование:

All2khoff

Продвинутый
Сообщения
352
Репутация
65
Поставил эту игру... поведение странное... клик мышки или кнопки проходит но единожды... затем игра бне дает ничего делать? даже с ручной сменой фокуса скрипт возвращаясь к окну игры хоть и рапортует что нажал кнопку, но игра нажатие не принимает.
В качестве эксперимента отключил все проверки окон и тупо "спамил" кнопку F на разный лад... срабатывает только в 1й раз или вообще не срабатывает.
Чередовал нажатие F и нажатие мышкой на значок шестеренки... пробовал оконный и полноэкранный режим.
по всей видимости, какая-то защита все же есть у игры.
вот вариант со сменой фокуса окна и всеми испробованными вариантами нажатия... блокнот открывается сам
Код:
#RequireAdmin
HotKeySet("{ESC}", "Terminate")

Global $name1='- ArcheAge -'
Global $name2='Безымянный – Блокнот'

While 1
win($name1)
win1($name2)
WEnd

Func win($name)
    MouseClick("left",400,400)    ;клик мышкой по координатам  гдето
    WinActivate($name)
    Sleep(100)
    If WinActive($name) Then
        ConsoleWrite("окно "&$name&" в фокусе"&@CRLF)
        Send("f")                    ;обычное нажатие F
        Sleep(1000)
        ControlSend($name,'','',"f");целевое нажатие F в окно игры
        Sleep(1000)
        MouseClick("left",916,721)    ;клик мышкой по координатам шестеренки
        Sleep(1000)
        $dll = DllOpen("user32.dll")
        $keyCode = 70 ; f
        DllCall($dll,"int","keybd_event","int",$keyCode,"int",0,"long",0,"long",0) ; - нажатие
        DllCall($dll,"int","keybd_event","int",$keyCode,"int",0,"long",2,"long",0) ; - отжатие
        DllClose($dll)
    Else
        ConsoleWrite("окно "&$name&" не в фокусе"&@CRLF)
    EndIf
    Sleep(1000)
EndFunc

Func win1($name)
    If WinExists($name) Then
        WinActivate($name)
        Sleep(100)
        If WinActive($name) Then
;~         ConsoleWrite("окно "&$name&" в фокусе"&@CRLF)
        Else
            ConsoleWrite("окно "&$name&" не в фокусе"&@CRLF)
        EndIf
    Else
        Run("notepad.exe")
    EndIf
    Sleep(1000)
EndFunc

Func Terminate()
    Exit 0
EndFunc
 
Последнее редактирование:
Автор
C

concolor

Новичок
Сообщения
4
Репутация
0
Ого! Реально серьёзная работа! Огромное спасибо за труд! У Вас примерно тот же результат, что и у меня. С принудительной сменой фокуса на окне игры - всё так - работает через раз, один раз не сработало - может сработать при следующей итерации. Но все же какой-то результат может быть. Еще слышал, что при работе скрипта существуют флаги, которые могут для анти-чита "палить" эмуляцию. Речь о LLKHF_LOWER_IL_INJECTED и LLKHF_INJECTED. Здесь же, на форуме. Но это для меня пока сложно - пока не разобралсо)
 

Prog

Продвинутый
Сообщения
537
Репутация
65
Можно попробовать аппаратный эмулятор клавиатуры (гуглите). Возможно сработает ведь для игры это будет обычная клавиатура, а не программная эмуляция.
 

Sergy

Новичок
Сообщения
25
Репутация
1
А не пробовали вызвать экранную клавиатуру и в ней жамкать на букву? Вдруг прокатит :smile:
 

All2khoff

Продвинутый
Сообщения
352
Репутация
65
вызвать экранную клавиатуру
Крайне редко когда экранная клавиатура вывозит там где не справляется отправка буквы в активный экран.
Но чуть позже попробую ради вопля Пушного...
UPD...
Проверил игра полностью игнорирует экранную клавиатуру...
 
Последнее редактирование:

eXeTerm

Новичок
Сообщения
1
Репутация
0
Если что - запускаю exeшник с правами администратора и всё такое.
Касаемо прав администратора.
Попробуй exe-шник запускать не требующих прав админа, если найдешь такой лаунчер в папке с игрой.
Просто я столкнулся со схожей проблемой как мне кажется, хоть и в другой игре - скрипт нормально работал с обычными окнами проводника и других приложений, но когда открывалось окно с игрой скрипт приостанавливался.
Пробовал на скрипте с кликером и переключением окон. Остановка происходила именно когда скрипт переключался на окно с игрой, стоило сделать активным другое окно, скрипт продолжал работу. Exe-шник изначально запускался с правами администратора. В папке нашел обычный лаунчер - с ним всё стало отлично работать.
 
Верх