Если я делаю перемещение не мгновенным а со скоростью 5 или 10, то мышь улетает от цели в другую сторону причем далеко а потом только стреляет. И еще как сделать чтобы мышь наводилась не на первый найденный пиксель а на центр головы(я покрасил головы противников в ксс)?
Случайно увидел тему, не смог пройти мимо... Таким способом ничего не выйдет путного, сам когда-то писал аим для Warface, вот проблемы, которые так и не получилось решить, при использовании MV.
1. MouseMove перемещает мышку в двумерном пространстве, а камера в игре - трехмерное представление, перемещение мышки в точку пикселя - в игре не переместит камеру в эту же точку, можно, конечно, с чувствительностью поиграться, но это глупо... см далее
2. Не всегда MouseMove ведет себя адекватно в окне DirectX, бывало, что даже сдвиг на 1 пиксель, от текущей точки (по экранным координатам), задирал в игре камеру под потолок.
3. Даже если что-то получится с тригонометрией и сдвиг мышки будет точно в нужную точку, то не факт, что эта точка окажется игроком, таких точек бесконечно много и в текстурах других объектов.
4. 3ую проблему можно частично решить, если использовать поиск не 1 пикселя, а группы в одном и том же месте, но этот способ, существенно загрузит систему, т.к. искать нужно не один раз, а 10 в секунду, чтобы чувствительность бота была высокой, более того и этот метод не даст 100% уверености, что бот не начнет стрелять в облако красного дыма. ( реализует поиск группы пикселей из bmp модуль <ImageSearch.au3>)
Вот собственно главные причины, почему не стоит использовать MouseMove для реализации аимов...
Но, это не значит, что совсем ничего нельзя сделать, есть проверенные библиотеки для написания любых чит-программ таких, как аим или триггер...
#include <NomadMemory.au3>
#include <WinAPI.au3>
Первая для работы с памятью (запись, чтение)
Вторая, ради функций _WinAPI_FloatToInt() и _WinAPI_IntToFloat, число с запятой в байты и наоборот.
Ну и самодельный модуль, чтобы узнать, какой адрес, является началом адресного пространства "базовый адрес"
Где параметры это...
$iPID = ProcessExists(' процесс.ехе ')
$sModule = ('процесс.exe')
1. Находится через любой редактор памяти (не знаю, можно тут писать название этой программы... ну думаю можно догадаться, она самая популярная среди редакторов...) адрес, который изменяется при наведении и отведении прицела на игрока (мишень), этот адрес называю TargetID, чаще всего он показывает ID игрока или мишени, на которого наведен прицел; так легко сделать бота, если этот адрес чему-то равен, то прицел очевидно на кого-то наведен, нужно стрелять. Алгоритм нахождения этого адреса таков: наводишь прицел на игрока, ищешь все неизвестный (unknown initial кажется) адреса; отводишь прицел в сторону, теперь ищешь адреса, которые изменились "Changed value" и.д. смысл должен быть понятен; таким образом отсеиваешь, пока не останется очевидный адрес, меняющийся при наведении на игрока, например 000B6ACC...
2. Адрес мы нашли динамичный, значит, когда мы перезапустим клиент игры, все адресное пространство изменяется, относительно базового адреса (который не меняется) и процедуру поиска динамичного адреса, придется повторить снова. Наша же главная задача, "доходить" от базового адреса по определенной цепочке (указателям, куда идти) до нужного нам адреса, при любом раскладе памяти. Образно цепь выглядит так:
от базового адреса процесса +
налево 5 шагов и посмотреть где мы +
направо 10 шагов и посмотреть где мы +
Вперед 20 шагов и посмотреть где мы +
Последний шаг: налево 10 шагов = Нужный нам адрес; (смотреть уже не обязательно, ведь мы в нужном месте)
p.s. Команды 'налево' или 'направо' - называются оффсетами или поинтами, они прибавляются к самим значениям адресов, позже покажу код...
3. Эта цепочка оффсетов находится так :
В этом же редакторе памяти добавляешь найденный адрес (TargetID) в нижнее поле, клик по адресу ПКМ, открываешь вкладку 'pointer scan for this address', откроется форма, в которой важно знать значение Max Level - это то, сколько оффсетов могут быть вложены друг в друга, больше 5 не ставить, т.к. находятся побочные цепочки и компьютер невероятно долго сканирует их, смысла в этом никакого нет... Поставили Max Level 5 и жмем ОК. В конце сканирования, будет представлена таблица, показывающая цепочки до 5 элементов, которые приводят нас к нужному адресу.
Не все они статичные, нужно отфильтровать... Сохраняем таблицу, например 1234.PTR и перезагружаем компьютер.
Заходим в редактор памяти ищем снова адрес Target ID по 1 пункту, записываем этот адрес куда-нибудь, от него переходим снова в меню 'pointer scan for this address', но теперь жмем не ОК а Cancel и в окне Pointer Scan жмем File/Open, выбираем таблицу 1234.PTR и открываем ее, как видим множество цепочек, уже не ведет к нужному нам адресу, нужно отсеять побочные цепочки. Открываем вкладку (Pointer Scanner/Rescan memory...) !Важно! ставим галочку на Address to find, а не на Value to find. В поле вводим записанный адрес. И отсеиваем, вот редактор создает очередную таблицу PTR с путями, которые и до перезагрузки вели нас к адресу TargetID и после, то есть сейчас, ведут нас к этому адресу.
P.S. Желательно этот шаг еще раз повторить...
Теперь в таблице путей остаются те пути из оффсетов, которые гарантированно, приведут нас к нужному адресу и после перезагрузки компьютера.
4. Запись в таблице например:
"client.exe"+0001A001 70 F F 0001DACC
означает, что
1.находится базовый адрес модуля client.exe
2.смещается на 0x0001A001
3.читается !значение! полученного адреса
4.к этому значению прибавляется оффсет 0x70
5.читается значение полученного адреса
6.к этому значению прибавляется оффсет 0xF
7. читается значение полученного адреса
8.к этому значению прибавляется оффсет 0хF
Больше ничего читать не нужно, прибавляя последний оффсет мы получаем нужный нам адрес 0001DACC
5. Как реализовать эти сложения и чтения в AutoIt? - Проще простого, хоть и кажется на первый взгляд сложно.
Код:
;-------Путь к Float 1.0 p.s ("client.exe"+0x000B6ACC 0x3bc 0x108 0x58 0x8 0x3C)Global$a='client.exe'; Global$b=0x000B6ACC; смещение процесса ;==Global$o0=0x3bc; 1 указатель Global$o1=0x108; 2 указатель Global$o2=0x58; 3 указатель Global$o3=0x8; 4 указатель Global$o4=0x3c; 5 указательGlobal$c=ProcessExists($a); получаем пид процессаGlobal$Mem=_MemoryOpen($c); открываем память этого процессаGlobal$float1=''; тут будет наш адресFunc_GetNewAd1float()$d=_MemoryModuleGetBaseAddress($c,$a); этой самоделкой получаем базовый адрес процесса$e=$d+$b; смещаем$f=_MemoryRead($e,$Mem); Содержимое базового адреса; Содержимое адреса ( базовый адрес + оффсет 0)$aa=$f+$o0$aa1=_MemoryRead($aa,$Mem); Содержимое адреса ( прошлый адрес + оффсет 1)$bb=$aa1+$o1$bb1=_MemoryRead($bb,$Mem); Содержимое адреса ( прошлый адрес + оффсет 2)$cc=$bb1+$o2$cc1=_MemoryRead($cc,$Mem); Содержимое адреса ( прошлый адрес + оффсет 3)$dd=$cc1+$o3$dd1=_MemoryRead($dd,$Mem); Содержимое адреса ( прошлый адрес + оффсет 4)$ee=$dd1+$o4; нужный нам адрес $float1=$ee; нужный нам адресEndFunc
После этих манипуляций получаем адрес по указанному смещению и оффсетам в $float1. В случае если мы искали TargetID, в этом адресе будет храниться какое-то значение, айди цели, если на нее наведен курсор. Можно читать и если там что-то есть, делать выстрел.
P.S. Если мы хотим работать со значением, а не просто смотреть на него. Например мы изменяем скорость выстрела (по принципу: прочли, изменили, перезаписали измененным), его необходимо представить в человеческом виде, для начала, иначе его трудно будет изменить, тут нам пригодится функция
$float1 = _WINAPI_IntToFloat($float1) ; теперь число прочитанное из памяти, например 1071644672 (int) будет выглядеть, как 1.75 (float), мы спокойно можем прибавить 0.5 получить 2.25, но так мы не запишем его обратно, нужно перевести обратно в родной вид int $float1 = _WINAPI_FloatToInt($float1), а теперь записываем
Для изменения значения получается следующий алгоритм:
1. Прочитали $скорость = _MemoryRead($float1,$Mem)
2. Перевели в удобный вид $скорость = _WINAPI_IntToFloat($скорость)
3. Изменили значение, как нам нужно, например $скорость = $скорость + 0.5
4. Перевели обратно в родной вид INT, $скорость = _WINAPI_FloatToInt(скорость)
5. Записали в память _MemoryWrite($float1, $Mem, $скорость)
Однозначно скажу, что по этому принципу можно создать любой чит, было бы желание... Если есть желание создавать 'крутые' вещи, нужно разбираться с памятью, тогда MouseMove() лишь смех будет вызывать :laugh:
Хотел ответить вкратце, получился целый мануал... Не знаю, может быть доработать и пересоздать, как тему... ;)