Торговый бот для Diablo 3

21st Февраль 2014 | Категории: AutoIT | Метки: ,

15 мая 2012 года вышел очередной шедевр компании Blizzard. Игра из легендарной серии – Diablo 3. Сегодня не будем говорить о самом процессе игры, а поговорим о написании бота. В начале июня 2012 ко мне обратился один мой знакомый с просьбой написать бота для Аукциона. В то время можно было делать неплохие деньги, выискивая вещи по заниженной цене и продавая их.

Изначально я хотел анализировать сетевые пакеты, но быстро понял что идея не выгорит. Установил Delphi, попробовал сделать примитивный кликер в этой среде. Но всё было очень сложно… И тут я вспомнил о программе для автоматизации действий пользователя — AutoIT. Главное, что она умела из коробки: перемещать курсор, кликать, вводить значения… Оставалось научить её распознавать образы с экрана…

Для распознавания образов уже был готов модуль: ImageSearch.
Почти весь бот построен на вызове функции _ImageSearchArea, которая ищет в указанной области картинку-шаблон. Пример использования функции:

Local $x, $y
$pattern = "img\game\Disconnect.bmp"
$result = _ImageSearchArea($pattern, 1, 330, 250, 490, 270, $x, $y, 100)

Если картинка-образец найдена, то $result будет равен 1, а в $x и $y будут координаты совпадения.

Для удобства работы конечного пользователя было решено вынести настройки в файл конфигурации. Для работы с конфигами есть функция IniRead. Пример: из файла config.ini, секции config получить значение параметра ItemsCount, иначе установить значение 1.

$ItemsCount	= IniRead("config.ini", "config", "CanBuyout", "0")

И сам файл:

[config]
ItemsConfig="items.ini"
CanBuyout="1"
 
Check2Page="1"
CheckManyItems="3"
 
SleepAfterSearch="2"
SleepBeforTtansaction="3"
Rrepeat="1"

Для задания параметров покупки вещей использовалась подобная схема. В конфиге задавались все значения искомых предметов, которые и забивались в фильтр

[config]
ItemsCount="42"
 
[item1]
Class="dh"
Type="4"
Item="12"
lvl1="47"
lvl2="60"
Qual="6"
Stat1="aspd"
Val1="7"
Stat2="crit_chanse"
Val2="3"
Stat3="dex"
Val3="100"
BuyOut="2500000"
 
[item2]
Class="dh"
Type="4"
Item="12"
lvl1="47"
lvl2="60"
Qual="6"
Stat1="aspd"
Val1="7"
Stat2="crit_chanse"
Val2="2"
Stat3="dex"
Val3="70"
BuyOut="750000"

Загрузка данных из конфига предметов осуществлялась в цикле:

; Инициализируем глобальные переменные
Global $ItemNum
Global $iClass, $iType, $iItem, $ilvl1, $ilvl2, $iQual, $iStat1, $iVal1, $iStat2, $iVal2, $iStat3, $iVal3, $iBuyOut
 
; бесконечный цикл
While 1 = 1
   ; перебираем все предметы от первого, до последнего (обычный цикл for)
   For $ItemNum = 1 To $ItemsCount Step 1
      initItem() ; функция для инициализации параметров предмета
      ; операции по проверке и покупке
   Next
WEnd
 
Func initItem()
   $config_item = "item" & $ItemNum;
   $iClass	=	IniRead($ItemsConfig, $config_item, "Class", "")
   $iType	=	IniRead($ItemsConfig, $config_item, "Type", "")
   ; аналогично заполняются остальные 11 элементов конфига
 
EndFunc

Заполнение значений в форму поиска аукциона.
Для каждого элемента поиска я создал отдельную функцию. Разберем на примере выбора класса героя.

Func pClass($class)
   Local $x = 0, $y = 0
   $img = "img\class\" & $class & ".bmp"
   $img_w = "img\class\" & $class & "_w.bmp"
 
   ; проверяем, что у нас уже выбрано
   If Not _ImageSearchArea($img_w, 1, 80, 180, 200, 200, $x, $y, 100) Then
          ; Раскрываем выпадающий список 
	  MouseClick("left", 110, 195, 1, 3)
	  RandSleep()
 
          ; Ищем название класса
	  If _ImageSearchArea($img, 1, 75, 200, 220, 480, $x, $y, 100) Then
		 ; Если нашли - щелкаем по нему
		 MouseClick("left", $x, $y, 1, 3)
	  Else
		 FileWrite($file, $img & ": not found " & @CRLF)
	  EndIf
   EndIf
 
   RandSleep()
EndFunc

По своей сути получившийся бот – это комбинация приведенных методов: пытаемся найти… нашли? – кликнули.

При разработке, большую часть времени я потратил на отладку координат и подготовку картинок-шаблонов.

ps. Бот успешно работал на протяжении месяца и принес неплохие барыши своему заказчику.

Subscribe without commenting


Пока комментариев нет.