Автор Тема: Перемещение персонажа по контрольным точкам в 3Д играх с видом от 3го лица  (Прочитано 903 раз)

0 Пользователей и 1 Гость просматривают эту тему.

ya12

  • Освоившийся
  • **
  • Сообщений: 34
    • Просмотр профиля
Код: Clickermann
  1. //Скрипт осуществляет перемещение персонажа (стрелки вперед и поворот вправо-влево) по контрольным точкам в 3Д игре с видом от 3го лица
  2. //координатная сетка: слева -X, cправа +X, сверху -Y, снизу +Y
  3. //адреса в памяти программы тип hex; X,Y - координаты тип float
  4. //$_Sx,$_Sy - координаты камеры от 3го лица
  5. //$_Ax,$_Ay - текущие координаты персонажа
  6. //$_Bx,$_By - координаты текущей контрольной точки
  7.  
  8. #ps2_keyboard
  9. // отключить NumLock (Кликер с включенным глючит)
  10. #include "float.cms"     //подключение процедуры переводящей hex 4 байта во float 4 байта
  11. #include "azimut.cms"    //вызятие азимута
  12. wait(1)
  13. $_ms1g =  1.02 * 6684 / 360   //поворот  (1.02 - поправочный коэф; 6684 - время в мс за которое персонаж повернется на 360 градусов)
  14.  
  15. EXECUTE("pid.exe") //получение PID игры и запись в Find_PID.ini(привязка по названию окна)
  16. WAIT(2)
  17. $_pid = INT(INIREAD("Find_PID.ini", "pid"))
  18. $_addr = readmem($_pid, 0x102D19F0, 4) //не базовый адрес, но некоторое время начальный адрес здесь храниться
  19. $_addrX = $_addr + 0x000003E0          //Х координаты перса в HEX
  20. $_addrY = $_addr + 0x000003E4          //y
  21. $_addrXs = $_addr + 0x00000950         //х координаты камеры от 3-го лица
  22. $_addrYs = $_addr + 0x00000954         //у
  23.  
  24. $_a025 = RND(200,220)   //время минимально возможной задержки
  25. $_a1 = RND(1000,1100)
  26.  
  27. KEYDOWN(#TAB)    //что бы можно было стрелками управлять персонажем
  28. waitms($_a025)
  29. KEYUP(#TAB)
  30. waitms($_a025)
  31.  
  32. KEYDOWN(#TAB)
  33. waitms($_a025)
  34. KEYUP(#TAB)
  35. waitms($_a025)
  36.  
  37. KEYDOWN(#UP)        //сразу после загрузки (по адресу в памяти) координаты персонажа 0, после короткой пробежки сервер пересылает текущие координаты
  38. waitms($_a025)
  39. KEYUP(#UP)
  40. waitms($_a01)
  41.  
  42. $_ks = TFCOUNT("loc.txt") + 1  
  43. FOR($_loc = 1, $_loc < $_ks, 2)  
  44.   $kl = 1
  45.   $_Bx =  INT(TFREAD("loc.txt", $_loc))            //чтение координат текущей контрольной точки
  46.   $_By =  INT(TFREAD("loc.txt", ($_loc + 1)))
  47.   WHILE($kl = 1)
  48.      $_Ax = readmem($_pid, $_addrX, 4)           //чтение координат текущей координаты перса
  49.      int_to_Float($_Ax)
  50.      $_Ax = int($float)
  51.  
  52.      $_Ay = readmem($_pid, $_addrY, 4)
  53.      int_to_Float($_Ay)
  54.      $_Ay = int($float)
  55.  
  56.      $_Sx = readmem($_pid, $_addrXs, 4)                  ////чтение координат камеры от 3го лица
  57.      int_to_Float($_Sx)
  58.      $_Sx = int($float)
  59.  
  60.      $_Sy = readmem($_pid, $_addrYs, 4)
  61.      int_to_Float($_Sy)
  62.      $_Sy = int($float)
  63.  
  64.      azimut($_Ax,$_Ay,$_Bx,$_By)  //взятие азимута с текущей координаты перса на текущую контрольную точку
  65.      $_AzAB = $angle                
  66.      $_Dab = $_Dt1t2              //дистанция до контрольной точки
  67.  
  68.      azimut($_Sx,$_Sy,$_Ax,$_Ay)  //взятие азимута с координаты камеры от 3го лица на текущуие координаты перса
  69.      $_AzSA = $angle
  70.  
  71.      $_deltaAz = abs($_AzSA - $_AzAB)  //дельта между азимутами
  72.  
  73.      if (($_AzSA < $_AzAB) and ($_deltaAz < 180)  //какой поворот ближе туда и повернет навычесленный угол
  74.         KEYDOWN(#RIGHT)
  75.         waitms(int(($_deltaAz) * $_ms1g))
  76.         KEYUP(#RIGHT)
  77.      END_IF
  78.      if (($_AzSA > $_AzAB) and ($_deltaAz < 180)
  79.         KEYDOWN(#LEFT)
  80.         waitms(int(($_deltaAz * $_ms1g))
  81.         KEYUP(#LEFT)
  82.      END_IF
  83.      if (($_AzSA > $_AzAB) and ($_deltaAz >= 180)
  84.         KEYDOWN(#RIGHT)
  85.         waitms(int((360 - $_deltaAz) * $_ms1g))
  86.         KEYUP(#RIGHT)
  87.      END_IF
  88.      if (($_AzSA < $_AzAB) and ($_deltaAz >= 180)
  89.         KEYDOWN(#LEFT)
  90.         waitms(int((360 - $_deltaAz) * $_ms1g))
  91.         KEYUP(#LEFT)
  92.      END_IF
  93.  
  94.      IF ($_Dab > 50)        //50 - минимальная дистанция до контрольной точки, после достижения которой можно получить новую
  95.         KEYDOWN(#UP)
  96.         waitms(int($_Dab / 0.14))  //(бег) 0.14 - скорость(точки в мс), при паспортной скорости перса в 129 (0.185-170?)
  97.         KEYUP(#UP)
  98.         $kl = 1
  99.      else
  100.         $kl = 0
  101.      end_if
  102.  
  103.      waitms($_a1)
  104.   END_CYC
  105. END_CYC
  106.  
  107. halt
  108.  

Vint - автор идеи с расчетом азимута (с геометрией у меня не очень процедуру переписал чтоб понятней было)

Код: Clickermann
  1. SUB(azimut,$t1x,$t1y,$t2x,$t2y) //=============================================
  2.  
  3.      $_Dt1t2 = DIST($t1x,$t1y,$t2x,$t2y)
  4.      $_Dt1az = DIST($t1x,$t1y,$t1x,$t2y)
  5.      $_Dt2az = DIST($t2x,$t2y,$t1x,$t2y)
  6.  
  7.      if ($_Dt1t2 = 0)   //на 0 делить нельзя, может кто предложит более изящную идею
  8. $_Dt1t2 = 0,1
  9.      end_if
  10.      if ($_Dt1az = 0)
  11. $_Dt1az = 0,1
  12.      end_if
  13.  
  14.      $_DV = POW($_Dt1az, 2) + POW($_Dt1t2, 2) - POW($_Dt2az, 2)
  15.      $_DN = 2 * $_Dt1t2 * $_Dt1az
  16.  
  17.      $beta = arccos($_DV / $_DN)
  18.  
  19.      if (($t1x > $t2x) and ($t1y > $t2y))
  20.         $angle = 360 - $beta
  21.       end_if
  22.      if (($t1x <= $t2x) and ($t1y >= $t2y))
  23.         $angle = $beta
  24.       end_if
  25.       if (($t1x < $t2x) and ($t1y < $t2y))
  26.         $angle = 180 - $beta
  27.       end_if
  28.       if (($t1x > $t2x) and ($t1y < $t2y))
  29.         $angle = 180 + $beta
  30.       end_if
  31. END_SUB
  32.  
  33.  

dramster - автор процедуры перевода HEX 4 байта во FLOAT 4 байта

Код: Clickermann
  1.    //перевод числа в двоичную строку $BIN  (строка выйдет длиной в 32бит)
  2.    SUB(dec_to_BIN, $DEC)
  3.       $BIN = ""
  4.  
  5.       IF($DEC > 0)   //если положительное
  6.          WHILE($DEC > 0)
  7.             $DEC = $DEC/2
  8.             IF($DEC > int($DEC))
  9.                $BIN = STRCONCAT("1", $BIN)
  10.             else
  11.                $BIN = STRCONCAT("0", $BIN)
  12.             END_IF
  13.             $DEC = int($DEC)
  14.          END_CYC
  15.          WHILE(STRLEN ($BIN) < 32)       //4 байта
  16.             $BIN = STRCONCAT("0", $BIN)
  17.          END_CYC
  18.       ELSE               //если отрицательное
  19.          $DEC = abs($DEC+1)
  20.          WHILE($DEC > 0)
  21.             $DEC = $DEC/2
  22.             IF($DEC > int($DEC))
  23.                $BIN = STRCONCAT("0", $BIN)
  24.             else
  25.                $BIN = STRCONCAT("1", $BIN)
  26.             END_IF
  27.             $DEC = int($DEC)
  28.          END_CYC
  29.          WHILE(STRLEN ($BIN) < 32)       //4 байта
  30.             $BIN = STRCONCAT("1", $BIN)
  31.          END_CYC
  32.       END_IF
  33.  
  34.    END_SUB
  35.  
  36.  
  37.    //перевод из двоичной строки в десятичное число $DEC
  38.    SUB(bin_to_DEC, $BIN_str)
  39.       $DEC = 0
  40.       IF(ARRSIZE ($arr) = 0)
  41.          $num_arr = 1
  42.          FOR($i=0,$i<32)
  43.             arrpush($arr, $num_arr)
  44.             $num_arr = $num_arr*2
  45.          END_CYC
  46.       END_IF
  47.  
  48.       FOR($i=0,$i < STRLEN($BIN_str))
  49.          $DEC = $DEC + ($arr[$i]*int(STRCUT($BIN_str, STRLEN($BIN_str)-$i, 1)))
  50.       END_CYC
  51.    END_SUB
  52.  
  53.    //перевод из целочисленного в дробное $float. целочисленное 4 байт -  long (Signed int) от -2147483648 до 2147483647
  54.    SUB(int_to_Float, $int_in)
  55.  
  56.       dec_to_BIN($int_in)
  57.  
  58.       bin_to_DEC(STRCUT ($BIN,2, 8))
  59.       $exp = $DEC   //экспонента в десятичном
  60.  
  61.       bin_to_DEC(STRCUT ($BIN,10, 32))
  62.       $mant = $DEC   //мантиса в десятичном
  63.  
  64.       $float =  POW(-1,int(STRCUT ($BIN,1,1))) * pow(2,$exp-127) * (1+($mant/POW(2,23)))
  65.  
  66.    END_SUB
  67.  
  68.    ///////////////////////////////////////////////////////////////////////////////
  69.    //основной код
  70.  
  71.   // int_to_Float(-979615744)
  72.   // print($float)  //  -5000
  73.  
  74.  

Скрипт записывающий в файл loc.txt координаты контрольных точек

Код: Clickermann
  1. //ALT - запись X,Y координат контрольной точки
  2. //ESC - выход
  3. #name "loc"
  4. #ps2_keyboard
  5.  
  6. $_sp = 0
  7. $_pid = 0
  8.  
  9. THREAD(T1, 0)  //поток считывающий координаты из памяти процесса и записывающий их в файл loc.txt
  10.   #include "float.cms"
  11.  
  12.   $_Ax = readmem($_pid, $_addrX, 4)
  13.   $_Ay = readmem($_pid, $_addrY, 4)
  14.   IF($_sp = 1)  
  15.      int_to_Float($_Ax)
  16.      TFWRITE("loc.txt", int($float))
  17.  
  18.      int_to_Float($_Ay)
  19.      TFWRITE("loc.txt", int($float))
  20.      $_sp = 0
  21.   END_IF
  22.  
  23.   WAIT(1)
  24. END_THREAD
  25.  
  26. THREAD(T2, 0)  //поток обрабатывающий нажатие клавиш
  27.   IF(iskeydown(#ALT)=1)
  28.      $_sp = 1
  29.   END_IF
  30.   IF(iskeydown(#esc)=1)
  31.      halt
  32.   END_IF
  33.  
  34.   waitms(200)
  35. END_THREAD
  36.  
  37. EXECUTE("pid.exe") //получение PID и запись его в файл Find_PID.ini
  38. WAIT(2)
  39. $_pid = INT(INIREAD("Find_PID.ini", "pid"))
  40. $_addr = readmem($_pid, 0x102D19F0, 4)
  41. $_addrX = $_addr + 0x000003E0
  42. $_addrY = $_addr + 0x000003E4
  43.  
  44. SETTHREAD (T1, 1)
  45. SETTHREAD (T2, 1)
  46. wait(600000)
  47.  
  48.  

Поиск Базового Адреса осуществлен в Cheat Engine. Средствами Кликера до БА добраться не смог, нашел адрес в памяти где указатель на начало структуры некоторое время храниться.
PID.exe сделан в AutoIT
« Последнее редактирование: Февраль 03, 2018, 12:51:09 am от ya12 »

dramster

  • Герой форума
  • *****
  • Сообщений: 658
    • Просмотр профиля
вижу, что используешь одну из последних бет 4.13. а значит и не обязательно использовать сторонние утилиты для определения pid.
HGETPID (hwnd) - Функция. Возвращает pid идентификатор родительского процесса по hwnd дочернего окна.

и в место поворота перса с помощью кнопок и выдерживания какихто задержек с коэффициентами, попробуй использовать MOVER (rx, ry). он поворачивает камеру на нужный (рассчитанный) тебе угол, не зависимо от фпс и лагов в игре.



отличный подход, тоже всегда стараюсь не привязываться к неточным данным с картинки на экране, а читать нужное в памяти. жаль, что не всегда это возможно  :(.

Цитировать
$_addr = readmem($_pid, 0x102D19F0, 4) //не базовый адрес, но некоторое время начальный адрес здесь храниться
адрес на указатель меняется? и нужно каждый раз заново искать его? пробуй искать указатель на указатель, или указатель со смещением. если не как, то адрес в модуле. только кликер с модулями не работает, может помочь автоит.

по такому же принципу перемещения по контрольным точкам отлично работает езда на транспорте в 3д играх. если хорошо отладить, то даже лучше ездит чем в ручную  :D , и на высоких скоростях.






ya12

  • Освоившийся
  • **
  • Сообщений: 34
    • Просмотр профиля
MOVER (rx, ry) не подходит. У меня только 1 PS/2 порт на нем висит клава. Если не использовать PS/2 режим, через некоторое время защита с сервера выкинет.

PID по HWND прикручу, когда все части скрипта соберу вместе.

БА зависит от адреса загруженной DLL. Средствами кликера адрес загруженной DLL не получить. К тому же между БА и адресом структуры хранящей координаты находятся 2 смещения представляющие индексные массивы. У каждого персонажа свои смещения. Цифры не большие поэтому поиск выдает тысячи адресов. Ну и защита не спит. Бряки поставленные на адреса начинающиеся с 00 зачастую приводят к отключению от сервера.
До телепортации по адресу 102D19F0 лежит адрес начала структуры. После загрузки персонажа один раз получить содержимое адреса, а потом уже не важно.

dramster

  • Герой форума
  • *****
  • Сообщений: 658
    • Просмотр профиля
БА зависит от адреса загруженной DLL. Средствами кликера адрес загруженной DLL не получить. К тому же между БА и адресом структуры хранящей координаты находятся 2 смещения представляющие индексные массивы. У каждого персонажа свои смещения. Цифры не большие поэтому поиск выдает тысячи адресов. Ну и защита не спит. Бряки поставленные на адреса начинающиеся с 00 зачастую приводят к отключению от сервера.
До телепортации по адресу 102D19F0 лежит адрес начала структуры. После загрузки персонажа один раз получить содержимое адреса, а потом уже не важно.
адрес загруженной dll это и есть модуль в памяти. зная имя модуля, находим его в памяти с помощью автоита, _MEMORYMODULEGETBASEADDRESS - библиотека RMemory.au3 во вложении. в модуле будет указатель, либо указатель на указатель, возможно со смещением.  Cheat Engine не использую, считаю что проще найти нужное в артмани, пока не подводила.

MOVER (rx, ry) не подходит. У меня только 1 PS/2 порт на нем висит клава. Если не использовать PS/2 режим, через некоторое время защита с сервера выкинет.
я хз, вроде MOVER (rx, ry) работает не зависимо от PS/2. даже если защита от кликов и нажатий в игре есть, MOVER (rx, ry) работает не зависимо от режима PS/2. другое дело если защита выкидывает из игры, ну тогда уж ничего не поделаешь.

James

  • Зашел в гости
  • *
  • Сообщений: 16
    • Просмотр профиля
Ув. dramster, а не подскажешь оптимальные и быстрые пути поиска указателей на значения? Либо менее быстрые и оптимальные, но более простые для восприятия
Мне бы очень много где пригодилось чтение из памяти игры, чтобы получать значения не с экрана, а как есть и потом уже с ними работать. Если это делается с помощью той au3 библиотеки или Артмани, не подскажешь алгоритм работы? Я пробовал с CheatEgine, и, либо я мало старался, либо я тормоз и не совладал с этим
Спасибо!
« Последнее редактирование: Февраль 28, 2018, 04:27:28 pm от James »

kiril

  • Герой форума
  • *****
  • Сообщений: 1036
    • Просмотр профиля
Ув. dramster, а не подскажешь оптимальные и быстрые пути поиска указателей на значения? Либо менее быстрые и оптимальные, но более простые для восприятия
Мне бы очень много где пригодилось чтение из памяти игры, чтобы получать значения не с экрана, а как есть и потом уже с ними работать. Если это делается с помощью той au3 библиотеки или Артмани, не подскажешь алгоритм работы? Я пробовал с CheatEgine, и, либо я мало старался, либо я тормоз и не совладал с этим
Спасибо!
попробуй другую версию CheatEgine, там на разных версиях можно найти более понятный обучающий курс. /
Кроме того в клиентских играх есть защиты, сообщающие на сайт о попытках обращения к игровым адресам сторонних программ или просто блокирующие любые такие попытки.
Трейнеруйся на кошках. Оптимальных и быстрых путей поиска значений не существует, тут только опыт, а чтоб его получить нужно ковырять всё подряд, со временем не останется вообще ни каких сложностей.

dramster

  • Герой форума
  • *****
  • Сообщений: 658
    • Просмотр профиля
в справке артмани все доступно расписано по поиску указателей (на примере игры "Warcraft 3"). справка отдельно есть на оффсайте, либо с прогой.

James

  • Зашел в гости
  • *
  • Сообщений: 16
    • Просмотр профиля
Спасибо за ответы, ребят

ya12

  • Освоившийся
  • **
  • Сообщений: 34
    • Просмотр профиля
Как я нашел БА в Cheat Engine 6.7 рус.

Возможно выбор настроек не оптимальный.
В Настройки - Параметры отладчика : Использовать VEH отладчик
                    - Дополнительно : Процедуры обращения к региону памяти
                                                : Чтение/Запись Памяти Процесса

Выбрать процесс и найти какой-нибудь изменяемый вручную параметр(типа HP,MP,внутри-игровых координат).

ПКМ:Найти инструкции обращающиеся по этому адресу.
Получаем начало структуры и смещение.

ПКМ:Найти указатель на этот адрес(начало структуры). Перед каждым поиском и отсевом выбирается куда сохранить результат.
Получили миллионы указателей.
Чем больше максимальный уровень смещений тем дольше искать(по умолчанию уровень 5).

Для отсева неправильных указателей нужно изменить адрес начала структуры(выбрать другого персонажа на этом аккаунте, перелогиниться, перезагрузить игру или компьютер).
После чего опять найти новый адрес структуры. В поиске указателей загрузить сохраненный результат и произвести отсев с новым адресом.
Повторять пока есть что отсеивать. Можно повторить отсев на разных компах, ОС.
В итоге от 0 до нескольких тысяч БА со смещениями. Я предпочитаю БА со смещением от загруженной в память DLL.
Если 0, то увеличивать уровень смещений, до тех пор пока время поиска не превысит разумные пределы.

James

  • Зашел в гости
  • *
  • Сообщений: 16
    • Просмотр профиля
Как я нашел БА в Cheat Engine 6.7 рус.

Возможно выбор настроек не оптимальный.
В Настройки - Параметры отладчика : Использовать VEH отладчик
                    - Дополнительно : Процедуры обращения к региону памяти
                                                : Чтение/Запись Памяти Процесса

Выбрать процесс и найти какой-нибудь изменяемый вручную параметр(типа HP,MP,внутри-игровых координат).

ПКМ:Найти инструкции обращающиеся по этому адресу.
Получаем начало структуры и смещение.

ПКМ:Найти указатель на этот адрес(начало структуры). Перед каждым поиском и отсевом выбирается куда сохранить результат.
Получили миллионы указателей.
Чем больше максимальный уровень смещений тем дольше искать(по умолчанию уровень 5).

Для отсева неправильных указателей нужно изменить адрес начала структуры(выбрать другого персонажа на этом аккаунте, перелогиниться, перезагрузить игру или компьютер).
После чего опять найти новый адрес структуры. В поиске указателей загрузить сохраненный результат и произвести отсев с новым адресом.
Повторять пока есть что отсеивать. Можно повторить отсев на разных компах, ОС.
В итоге от 0 до нескольких тысяч БА со смещениями. Я предпочитаю БА со смещением от загруженной в память DLL.
Если 0, то увеличивать уровень смещений, до тех пор пока время поиска не превысит разумные пределы.
Спасибо, что не прошли мимо и все расписали) Эта информация будет несомненно полезной!

ya12

  • Освоившийся
  • **
  • Сообщений: 34
    • Просмотр профиля
На скрине красные стрелки - это мана. Зеленые - адрес где начинается таблица и смещение от него. Справа в записях видно что HP,MP,CP max и текущие идут подряд со смещение 4 байта. Дальше ищем указатели на это адрес в разделе сканирование указателей и т.д.

Если все найденные указатели БА после перезагрузки оказались ошибочными - придется пройти по цепочке в ручном режиме.
Там скорее всего адрес формируется из нескольких неизвестных (пример   mov [eax + edi*4 + 38],ecx ).
В примере еах - адрес от которого можно выйти к БА, а edi - смещения в таблице. Найти как формируется edi сложно, но возможно...