Что нового

[Drakensang-Online] Бот для игры

Автор
sebun

sebun

Знающий
Сообщения
81
Репутация
5
Вот функция, которую написал Dellroc.

Код:
Func be_CoordsToRotation($bectr_X1, $bectr_Y1, $bectr_X2, $bectr_Y2)
    Local $bectr_DX = $bectr_X2-$bectr_X1
    Local $bectr_DY = $bectr_Y2-$bectr_Y1
    Local $bectr_AXY = Abs(ATan($bectr_DX/$bectr_DY))
    Local $bectr_AYX = Abs(ATan($bectr_DY/$bectr_DX))
    Local $bectr_hpi = ATan(1)*2
    Local $bectr_Angle = 0

    If $bectr_X1 > $bectr_X2 Then
        $bectr_Angle += 2*$bectr_hpi
        If $bectr_Y1 > $bectr_Y2 Then
            $bectr_Angle += $bectr_AXY
        ElseIf $bectr_Y1 = $bectr_Y2 Then
            $bectr_Angle += $bectr_hpi
        ElseIf $bectr_Y1 < $bectr_Y2 Then
            $bectr_Angle += $bectr_hpi
            $bectr_Angle += $bectr_AYX
        EndIf
    ElseIf $bectr_X1 = $bectr_X2 Then
        If $bectr_Y1 > $bectr_Y2 Then
            $bectr_Angle += 2*$bectr_hpi
        EndIf
    ElseIf $bectr_X1 < $bectr_X2 Then
        If $bectr_Y1 > $bectr_Y2 Then
            $bectr_Angle += $bectr_hpi
            $bectr_Angle += $bectr_AYX
        ElseIf $bectr_Y1 = $bectr_Y2 Then
            $bectr_Angle += $bectr_hpi
        ElseIf $bectr_Y1 < $bectr_Y2 Then
            $bectr_Angle += $bectr_AXY
        EndIf
    EndIf
    Local $R = Round(Sqrt(($bectr_X1 - $bectr_X2) ^ 2 + ($bectr_Y1 - $bectr_Y2) ^ 2),4)
    $bectr_Angle = Round($bectr_Angle*45/ATan(1),4)
    Local $lR[2] = [$bectr_Angle,$R]
    Return $lR
EndFunc

Пытаюсь понять как он находит угол?

Код:
$bectr_Angle = Round($bectr_Angle*45/ATan(1),4)


Откуда число 45? У меня эта функция возвращает неверные значения. К примеру:
Код:
; координаты на миникарте
    $X1=215 ; текущее положение персонажа
    $Y1=235
    $X2=211 ; куда ему надо пойти
    $Y2=231


Как поправить код Dellroсa, что бы выдавал нужный результат? Пытался по формулам сделать, но некорректно получается.
И сразу второй вопрос по движению: правильно ли будет расчитывать движение по алгоритму Dellroсa

Код:
$mX = $persPos[0] + $lRadius * Cos(($tCTR[0]-90)*4*atan(1)/180)
$mY = $persPos[1] + $lRadius * Sin(($tCTR[0]-90)*4*atan(1)/180)


или же писать свой по формулам:

X = X + A * cos(Angle * PI / 180);
Y = Y + A * sin(Angle * PI / 180);

хотя это помоему одно и то же, только с добавлением радиуса к позиции персонажа... Но что за число 90?
 

lirikmel

Продвинутый
Сообщения
226
Репутация
84
Вот функция, которую написал Dellroc
Эту функцию написал Dwerf , а вот как это выглядит полностью запусти и это тебе поможет разобраться
Код:
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
$gui = GUICreate('winkeltest', 520, 550)
$input1 = GUICtrlCreateInput(Random(-100, 100, 1), 10, 10, 25, 20)
$input2 = GUICtrlCreateInput(Random(-100, 100, 1), 45, 10, 25, 20)
$input3 = GUICtrlCreateInput(Random(-100, 100, 1), 80, 10, 25, 20)
$input4 = GUICtrlCreateInput(Random(-100, 100, 1), 115, 10, 25, 20)
$button1 = GUICtrlCreateButton('go', 150, 10, 40, 20)
$button2 = GUICtrlCreateButton('random', 200, 10, 40, 20)
$button3 = GUICtrlCreateButton('neu', 250, 10, 40, 20)
$graphic = GUICtrlCreateGraphic(10, 40, 500, 500)
GUICtrlSetBkColor(-1, 0x000000)
GUICtrlSetGraphic(-1, $GUI_GR_COLOR, 0xFFFFFF, 0x000000)

GUICtrlSetGraphic(-1, $GUI_GR_MOVE, 000, 250)
GUICtrlSetGraphic(-1, $GUI_GR_LINE, 500, 250)

GUICtrlSetGraphic(-1, $GUI_GR_MOVE, 000, 250)
GUICtrlSetGraphic(-1, $GUI_GR_LINE, 010, 245)

GUICtrlSetGraphic(-1, $GUI_GR_MOVE, 000, 250)
GUICtrlSetGraphic(-1, $GUI_GR_LINE, 010, 255)

GUICtrlSetGraphic(-1, $GUI_GR_MOVE, 250, 000)
GUICtrlSetGraphic(-1, $GUI_GR_LINE, 250, 500)

GUICtrlSetGraphic(-1, $GUI_GR_MOVE, 250, 000)
GUICtrlSetGraphic(-1, $GUI_GR_LINE, 245, 010)

GUICtrlSetGraphic(-1, $GUI_GR_MOVE, 250, 000)
GUICtrlSetGraphic(-1, $GUI_GR_LINE, 255, 010)

GUICtrlSetGraphic(-1, $GUI_GR_CLOSE)
GUISetState()
While 1
    Switch GUIGetMsg()
        Case -3
            Exit
        Case $button2
            GUICtrlSetData($input1, Random(-100, 100, 1))
            GUICtrlSetData($input2, Random(-100, 100, 1))
            GUICtrlSetData($input3, Random(-100, 100, 1))
            GUICtrlSetData($input4, Random(-100, 100, 1))
        Case $button3
            If @Compiled Then
                ShellExecute(@ScriptFullPath)
            Else
                ShellExecute(@AutoItExe, '"' & @ScriptFullPath & '"')
            EndIf
            Exit
        Case $button1
            $x1 = Int(GUICtrlRead($input1))
            $y1 = Int(GUICtrlRead($input2))
            $x2 = Int(GUICtrlRead($input3))
            $y2 = Int(GUICtrlRead($input4))

;~          $angle = 0

;~          $dx = $x2-$x1
;~          $dy = $y2-$y1
;~          MsgBox(0,'','ATan($dx/$dy) = ' & ATan($dx/$dy) & @CRLF & 'ATan($dy/$dx) = ' & ATan($dy/$dx))
;~          If $x1 > $x2 Then
;~              $angle += 180
;~              If $y1 > $y2 Then
;~                  $angle += Abs(ATan($dx/$dy)*45/ATan(1))
;~              ElseIf $y1 = $y2 Then

;~              ElseIf $y1 < $y2 Then
;~                  $angle += 90
;~                  $angle += Abs(ATan($dy/$dx)*45/ATan(1))
;~              EndIf
;~          ElseIf $x1 = $x2 Then
;~              If $y1 > $y2 Then
;~                  $angle += 180

;~              ElseIf $y1 = $y2 Then
;~                  ContinueLoop
;~              ElseIf $y1 < $y2 Then

;~              EndIf
;~          ElseIf $x1 < $x2 Then
;~              If $y1 > $y2 Then
;~                  $angle += 90
;~                  $angle += Abs(ATan($dy/$dx)*45/ATan(1))
;~              ElseIf $y1 = $y2 Then
;~                  $angle += 90

;~              ElseIf $y1 < $y2 Then
;~                  $angle += Abs(ATan($dx/$dy)*45/ATan(1))
;~              EndIf
;~          EndIf

            $angle = be_CoordsToRotation($x1, $y1, $x2, $y2)*45/ATan(1)

            $x1z = $x1*-2+249
            $x2z = $x2*-2+249
            $y1z = $y1*-2+249
            $y2z = $y2*-2+249

            GUICtrlSetGraphic($graphic, $GUI_GR_COLOR, 0x00FFFF, 0x00FFFF)
            GUICtrlSetGraphic($graphic, $GUI_GR_ELLIPSE, $x1z-5, $y1z-5, 10, 10)
            GUICtrlSetGraphic($graphic, $GUI_GR_ELLIPSE, $x2z-3, $y2z-3, 5, 5)

            GUICtrlSetGraphic($graphic, $GUI_GR_COLOR, 0x0000FF, $GUI_GR_NOBKCOLOR)
            GUICtrlSetGraphic($graphic, $GUI_GR_MOVE, $x1z, $y1z)
            GUICtrlSetGraphic($graphic, $GUI_GR_LINE, $x2z, $y2z)
            GUICtrlSetGraphic($graphic, $GUI_GR_CLOSE)

            GUICtrlSetGraphic($graphic, $GUI_GR_COLOR, 0xFF0000, $GUI_GR_NOBKCOLOR)
            GUICtrlSetGraphic($graphic, $GUI_GR_MOVE, $x1z, $y1z)
            GUICtrlSetGraphic($graphic, $GUI_GR_LINE, $x2z, $y1z)
            GUICtrlSetGraphic($graphic, $GUI_GR_LINE, $x2z, $y2z)
            GUICtrlSetGraphic($graphic, $GUI_GR_CLOSE)

            GUICtrlSetGraphic($graphic, $GUI_GR_COLOR, 0x00FF00, $GUI_GR_NOBKCOLOR)
            GUICtrlSetGraphic($graphic, $GUI_GR_MOVE, $x1z, $y1z)
            GUICtrlSetGraphic($graphic, $GUI_GR_LINE, $x1z, 0)
            GUICtrlSetGraphic($graphic, $GUI_GR_PIE, $x1z, $y1z, 30, 90, $angle)
            GUICtrlSetGraphic($graphic, $GUI_GR_CLOSE)

            GUICtrlSetGraphic($graphic, $GUI_GR_REFRESH)
            MsgBox(0,'', 'P1 (' & $x1 & ';' & $y1 & ')' & @CRLF & 'P2 (' & $x2 & ';' & $y2 & ')' & @CRLF & 'Winkel: ' & $angle)

;~          MsgBox(0,'', $x1z & '/' & $y1z & @CRLF & $x2z & '/' & $y2z)
    EndSwitch
WEnd

Func be_CoordsToRotation($bectr_X1, $bectr_Y1, $bectr_X2, $bectr_Y2)
    Local $bectr_DX = $bectr_X2-$bectr_X1
    Local $bectr_DY = $bectr_Y2-$bectr_Y1
    Local $bectr_AXY = Abs(ATan($bectr_DX/$bectr_DY))
    Local $bectr_AYX = Abs(ATan($bectr_DY/$bectr_DX))
    Local $bectr_hpi = ATan(1)*2
    Local $bectr_Angle = 0

;~  MsgBox(0, '', _
;~  '$bectr_X1 = ' & $bectr_X1 & @CRLF & _
;~  '$bectr_Y1 = ' & $bectr_Y1 & @CRLF & _
;~  '$bectr_X2 = ' & $bectr_X2 & @CRLF & _
;~  '$bectr_Y2 = ' & $bectr_Y2 & @CRLF & _
;~  '$bectr_DX = ' & $bectr_DX & @CRLF & _
;~  '$bectr_DY = ' & $bectr_DY & @CRLF & _
;~  '$bectr_AXY = ' & $bectr_AXY & @CRLF & _
;~  '$bectr_AYX = ' & $bectr_AYX & @CRLF & _
;~  '$bectr_hpi = ' & $bectr_hpi & @CRLF & _
;~  '$bectr_Angle = ' & $bectr_Angle & @CRLF & _
;~  '')

    If $bectr_X1 > $bectr_X2 Then
        $bectr_Angle += 2*$bectr_hpi
        If $bectr_Y1 > $bectr_Y2 Then
            $bectr_Angle += $bectr_AXY
        ElseIf $bectr_Y1 = $bectr_Y2 Then
            $bectr_Angle += $bectr_hpi
        ElseIf $bectr_Y1 < $bectr_Y2 Then
            $bectr_Angle += $bectr_hpi
            $bectr_Angle += $bectr_AYX
        EndIf
    ElseIf $bectr_X1 = $bectr_X2 Then
        If $bectr_Y1 > $bectr_Y2 Then
            $bectr_Angle += 2*$bectr_hpi
;~      ElseIf $bectr_Y1 = $bectr_Y2 Then
;~      ElseIf $bectr_Y1 < $bectr_Y2 Then
        EndIf
    ElseIf $bectr_X1 < $bectr_X2 Then
        If $bectr_Y1 > $bectr_Y2 Then
            $bectr_Angle += $bectr_hpi
            $bectr_Angle += $bectr_AYX
        ElseIf $bectr_Y1 = $bectr_Y2 Then
            $bectr_Angle += $bectr_hpi
        ElseIf $bectr_Y1 < $bectr_Y2 Then
            $bectr_Angle += $bectr_AXY
        EndIf
    EndIf
    Return $bectr_Angle
EndFunc
 
Автор
sebun

sebun

Знающий
Сообщения
81
Репутация
5
Спасибо, lirikmel. Я нашел пост Dwerf-а на этом форуме, где он выложил этот код. Благодаря программке понял, как у него происходит расчет координат. Жаль, что там одна страница и мало обсуждений и комментов. Dellroc в этой функции немного добавил наглядности. Пока мой перс бегает по моему линейному алгоритму, там нет градуса, пишу тестовый код.

Кстати, а есть готовые примеры с реализованной изометрией? В принципе, я пока в этом не вижу необходимости, так как считаю, что по любой модели пространства можно построить двумерную модель. Скажем, в Drakensang Online примером служит миникарта, и по ней я ориентируюсь. Координаты не слишком точные, но мне точность там и не важна. Есть поинт, перс бежит на поинт. Пока так. Если возникнет необходимость наращивать логику, например, самостоятельно принимать решения относительно направления движения или выбирать тактику боя, то тогда можно добавить что то еще, но опять же, это можно сделать и на двумерной модели. Я, например, просто взял и в фотошопе измерил линейкой расстояние между точками в игре и точками на миникарте, определил, чему равен один шаг, ну и дальше перс смотрит миникарту и бегает по ней. Изврат, но добавляет азарта, так как здесь работа производится исключительно с графикой.

Я уже спрашивал, но все же еще раз задам вопрос: кто нибудь знает, как быстро определять движение на экране? Скажем, нужно отследить траекторию полета стрелы и уклонится от нее. Объект может быть определен по скорости движения, так как мобы бегают всегда медленее, чем стреляют. Но вот как это реализовать. Понимаю, что тут нужна dll, но Belfigor вроде как на С перешел ;)


Добавлено:
Сообщение автоматически объединено:

Все таки я тормоз. Простите за жесткую самокритику, но я так и не смог реализовать движение. Написал скрипт, который должен был определить угол и навести мышку на точку, которую я задал, расчитав ее положение по углу.
Код:
HotKeySet('{ESC}', '_Exit') ; определяем клавишу выхода из бота
HotKeySet('{SPACE}', '_Go') ; определяем клавишу старта



While 1
	ToolTip("Нажми пробел...", 0, 0)

WEnd


Func _Go() ; показать точку
	GoPointNew(100, 100, 0)
EndFunc   ;==>_Go


Func GoPointNew($pointX = 0, $pointY = 0, $justPos = 0)

	
		Local $aCoords[2]
		$aCoords[0] = 200
		$aCoords[1] = 200	
		
		Local $tCTR = CoordsToRotation($aCoords[0], $aCoords[1], $pointX, $pointY) ;угол и расстояние до цели
		
		Local $lRadius=$tCTR[1] ; радиус окружности (поставил дистанцию до точки)
		
		$mX = $aCoords[0] + $lRadius * Cos(($tCTR[0]-90)*4*atan(1)/180)
		$mY = $aCoords[1] + $lRadius * Sin(($tCTR[0]-90)*4*atan(1)/180)
		
		
        ToolTip('Движение к цели'&@CRLF&'Текущие X = '&$aCoords[0]&', Y = '&$aCoords[1]&' , Угол = '&$tCTR[0]&@CRLF _
        &'Заданные X = '&$pointX&', Y = '&$pointY&' , Дистанция = '&$tCTR[1]&@CRLF _
		&'Направление: mX='&$mX&' mY='&$mY,0,0)

        MouseMove($mX, $mY, 0) ;показать точку
        Sleep(3000)
EndFunc   ;==>GoPoint
cb1fdf579282.gif


Синяя точка - начальные координаты. Красная - цель, на которую нужно навести мышку. Функция от Dwerf-а возвращает угол по оси Y (зеленый). У меня красная точка находится под углом 45 градусов относительно синей в обычной системе координат, x1=200, y1=200 (синяя), x2=100, y2=100 (красная), но функция возвращает 225, а должно быть 315 градусов (360-45). Проблема еще в том, что не получается рассчитать координаты этой точки по углу. Так, я знаю, что y = R*sin(угол) а x = R*cos(угол). Но у меня угол другой, а у Dellroc-а вообще как то странно:

Код:
$mX = $aCoords[0] + $lRadius * Cos(($tCTR[0]-90)*4*atan(1)/180)
$mY = $aCoords[1] + $lRadius * Sin(($tCTR[0]-90)*4*atan(1)/180)


$aCoords у меня - текущие координаты синей точки. В качестве $lRadius задаю расстояние до точки. Но мышь крутится куда угодно, только не в нужном направлении. Почему?
 

Dellroc

Осваивающий
Сообщения
151
Репутация
31
Все таки я тормоз. Простите за жесткую самокритику, но я так и не смог реализовать движение. Написал скрипт, который должен был определить угол и навести мышку на точку, которую я задал, расчитав ее положение по углу.
Синяя точка - начальные координаты. Красная - цель, на которую нужно навести мышку. Функция от Dwerf-а возвращает угол по оси Y (зеленый). У меня красная точка находится под углом 45 градусов относительно синей в обычной системе координат, x1=200, y1=200 (синяя), x2=100, y2=100 (красная), но функция возвращает 225, а должно быть 315 градусов (360-45). Проблема еще в том, что не получается рассчитать координаты этой точки по углу. Так, я знаю, что y = R*sin(угол) а x = R*cos(угол). Но у меня угол другой, а у Dellroc-а вообще как то странно:
Не совсем понятно как ты хочешь угол определить. Нарисуй где у тебя должен быть 0,90,180,270 градусов.
Если у тебя 0 вверху, то тебе нужно по другому определять угол.
Вот тебе код для:
Код:
          0
270             90
         180
Код:
Func _CoordsToRotation($cX,$cY,$tX,$tY)
Local $Pi = 4 * ATan(1)
Local $R = Sqrt(($cX - $tX) ^ 2 + ($cY - $tY) ^ 2)
Local $A = ASin(($tX - $cX) / $R)
If $tY > $cY Then $A = $Pi - $A
If $A < 0 Then $A += 2 * $Pi
If $A=360 Then $A=0
Local $tAngle=($A * 180 / $Pi)
$tAngle=Round($tAngle)
$R=Round($R)
Local $tReturn[2]=[$tAngle,$R]
Return $tReturn
EndFunc

и -90 убрать
Код:
$mX = $persPos[0] + $lRadius * Cos(($tCTR[0])*4*atan(1)/180)
$mY = $persPos[1] + $lRadius * Sin(($tCTR[0])*4*atan(1)/180)

$persPos - это координаты персонажа относительно игрового окна, т.е. примерно центр окна у него в ногах.
Я не представляю как ты получаешь текущие координаты, по этому написать алгоритм определения направления за тебя немножко сложновато. Так что делись этим кодом и переделаю под тебя.
Функцию движения я взял из своего другого бота... Она в принципе универсальна. Для неё самое главное получать текущие координаты персонажа.
 

bugaj

Знающий
Сообщения
140
Репутация
11
Я уже спрашивал, но все же еще раз задам вопрос: кто нибудь знает, как быстро определять движение на экране? Скажем, нужно отследить траекторию полета стрелы и уклонится от нее. Объект может быть определен по скорости движения, так как мобы бегают всегда медленее, чем стреляют. Но вот как это реализовать. Понимаю, что тут нужна dll, но Belfigor вроде как на С перешел ;)

берем скриншот 1, затем скриншот2, сравниваем их попиксельно, то чем они отличаются - это то что сдвинулось. Дальше остается распознать в этом свой объект.

или так, берем скриншот 1, ищем там свой объект, засекаем координаты. Берем скриншот 2, ищем там свой объект засекаем координаты и сравниваем со скриншотом 1. Наверное так будет быстрее и проще ) т.к. при перекрытии объекта самим собой в первом способе он не будет полностью отрисован на картинке-разнице.
 
Автор
sebun

sebun

Знающий
Сообщения
81
Репутация
5
bugaj сказал(а):
берем скриншот 1, затем скриншот2, сравниваем их попиксельно, то чем они отличаются - это то что сдвинулось.
Спасибо за совет, но это и так понятно. Кроме того, мне известны принципы построения таких алгоритмов. Вопрос в другом. Я пользуюсь dll FastFind для работы со скриншотами и поиском нужного мне изображения. Но в ней нет нужного мне функционала. Например, функция FFIsDifferent будет всегда возвращать true. Вот FFLocalizeChanges более интересна. Признаться, пока не пробовал ее, сейчас задача чуть другая стоит - заменить свой линейный алгоритм на нормальный. Но есть сомнения относительно эффективности использования этой функции. Она должна непрерывно "смотреть" локу, нагрузка на проц будет серьезная. ИМХО.

Dellroc сказал(а):
Я не представляю как ты получаешь текущие координаты, по этому написать алгоритм определения направления за тебя немножко сложновато. Так что делись этим кодом и переделаю под тебя.
Я не привык к тому, что бы за меня что то делали. Я просто хотел понять алгоритм. Сейчас попробую то, что ты написал, попробую примеры, которые написал Yashied в этом посте, и, если не получится, выложу скрипты. Надеюсь, я не настолько туп, что бы не решить такую простейшую задачу :whistle:


Добавлено:
Сообщение автоматически объединено:

Покажу, что хочу получить:

de3afef01031.gif


Имеется миникарта. Зеленая точка - мой перс с координатами $cX=216 и $cY=235. На карте стоит поинт (красная точка) с координатами $tX=211 и $tY=231. Задача: навести мышь на этот поинт, то есть на красную точку. Берем алгоритм, предложенный Yashied-ом (ну и ты то же самое предложил).

Код:
Func _CoordsToRotation($cX,$cY,$tX,$tY)
Local $Pi = 4 * ATan(1)
Local $R = Sqrt(($cX - $tX) ^ 2 + ($cY - $tY) ^ 2)
Local $A = ASin(($tX - $cX) / $R)
If $tY > $cY Then $A = $Pi - $A
If $A < 0 Then $A += 2 * $Pi
If $A=360 Then $A=0
Local $tAngle=($A * 180 / $Pi)
$tAngle=Round($tAngle)
$R=Round($R)
Local $tReturn[2]=[$tAngle,$R]
Return $tReturn
EndFunc

Этот алгоритм показывает, что угол равен 309°, радиус (дистанция до точки) равен 6. Применяем формулу:

Код:
$mX = $cX + $lRadius * Cos(($tCTR[0])*4*atan(1)/180)
$mY = $cY + $lRadius * Sin(($tCTR[0])*4*atan(1)/180)


и получаем, что $mX=219 а $mY=230 (желтая), что за пределами координат. А вот если делать как ты написал, отнять от угла 90°, то направление показывает верно. Вроде. Сегодня допилю функцию и посмотрим. А задача такая - сделать шаг к поинту на 1/4 длины радиуса и далее уже мелким шагом подойти к точке, при этом не постоянно удерживая кнопку мыши нажатой, а нажимая ее периодически, так как если оставшееся расстояние он побежит за три шага, то, если на его пути вдруг выскочит моб, нажатие этой кнопки вместо бега активирует один из атакующих скиллов.


Добавлено:
Сообщение автоматически объединено:

Допилил. Нормально определяет градус и координаты по градусу. Стал шустрее бегать. Так что я, оказывается, не совсем тупой, как подумал о себе вначале :IL_AutoIt_1:
 

Belfigor

Модератор
Локальный модератор
Сообщения
3,608
Репутация
941
Та карта что ты привел, она же и Диаблы. Там координаты располагаются не так как ты указал, они находятся под углом 45 градусов
 
Автор
sebun

sebun

Знающий
Сообщения
81
Репутация
5
Та карта что ты привел, она же и Диаблы. Там координаты располагаются не так как ты указал, они находятся под углом 45 градусов

А смысл городить огород? Мне приятнее работать с привычной системой координат, все равно ведь данные я получаю не из памяти, а с окна. Ну и движение по поинтам не критично к такой системе координат. Есть две точки, направление получено, перс побежал. Пока все пучком. Единственное, что заметил - это проблема с _IsPressed (уперся в моба и стоит), но ее буду решать путем вставки дополнительных условий, скажем, по дистанции и количеству интераций цикла.

Сейчас доделываю логику, это довольно просто. Единственное, что напрягает - 1. корректное определение дропа и 2. распознавания мобов.

Начну со второго. Я уже писал, что мой алгоритм примитивен и работает так: область игры разбивается на регионы, затем по экрану носится курсор и идет поиск цвета, которым закрашивается моб при наведении мышки. Функция корректно работает, но мне не нравится, так как на проход курсора по экрану тратится время. Хочу заюзать FFLocalizeChanges, но что то не найду примеров. В любом случае нужно научить бота быстро определять моба, иначе грош ему цена.

По поводу первого вопроса тоже писал в данной теме. Пока он определяет по цветам некоторые вещи. Появилась идея распознавать текст, который выводится при наведении курсора на дроп. Но может есть наработки в этой области получше? Я же, по сути, велосипед изобретаю...
 

lirikmel

Продвинутый
Сообщения
226
Репутация
84
хммм FFLocalizeChanges, видел как используют http://filesd.net/kibor/finddynamic.php , по сути работает на том же ,и обьясняет
принцип работы но не для autoit , мне даже интересно стало, хотя думаю поиск будет еще медленнее, буду пробывать но на другой игре. Если надо о результатах сообщу
 
Автор
sebun

sebun

Знающий
Сообщения
81
Репутация
5
lirikmel сказал(а):
Если надо о результатах сообщу
Ты шутишь? Конечно надо! Я даже на Кибор хотел перейти только ради одной этой функции, но лень учить новый язык и переписывать бота, который уже больше 800 Кб кода имеет. В качестве примера можно посмотреть эту работу.
 
Автор
sebun

sebun

Знающий
Сообщения
81
Репутация
5
Вот еще вопрос: в мануале про FFComputeMeanValues написано, что функция полезна для обнаружения измененных областей. Что то не придумаю, как ее использовать. :scratch:
 

Guezt

Продвинутый
Сообщения
335
Репутация
82
sebun
Будет несколько просьб к тебе:
Если не сложно покажи свой кусок кода на запуск и автологин клиента (мне интересно про кнопку "новая попытка" - она же ошибка любая и выбор конкретного перса в списке если есть список )
и второе я года три не писал ничего, но многое можно решить очень просто - писал ботов под игры 1 был вообще вместо клиента у меня и работал на прямых запросах к серверу из трея. кушал меньше игры точнее всего 8 мегабайт памяти проц не грузил вообще, функционал автомат был 99% игры, до релиза не дошло дело т.к. прямые запросы убрали в игре пол года полировки клиента причем круглосуточного теста убил переход с прямых запросов на SSL ))) . Второй работал с флешем. А вот в ДСО я забыл что такое боты - т.к. раньше было интересно в нее играть - сейчас она уже не то, и я вижу что это у тебя будет бот на багнутый квест "Медленная смерть" ) так вот сколько же тебе интересно заплатили, если это так за такого бота и второе он ориентирован на премиум аккаунт или чисто на подойди сам подбери ины ? :smile: Кстати есть другой квест более выгодный, но он одноразовый суть в том что там 13 минибоссов, берешь кв делаешь его и вместо сдать - удаляешь вот такой смысл - но не знаю как долго он будет существовать кв находится в руднике, называется изо льда или как то так в общем он справа от оружейника за углом сразу у нпс сам не видел этот кв но там раза в 2-3 быстрее ины набирать по 50к делают за вечер :smile:
 
Автор
sebun

sebun

Знающий
Сообщения
81
Репутация
5
Guezt Gutsy сказал(а):
я вижу что это у тебя будет бот на багнутый квест "Медленная смерть"
Ошибаешься, я никогда не делаю прог, юзающих баги, это, имхо, не перспективное направление. Мой бот пока оттачивается на одной локации. Как только будет отработано движение, быстрое определение мобов и собственно сама логика, бот будет бегать абсолютно по любой локации, независимо от того, где она расположена. Ну за исключением арены (пока). После того, как код будет отточен, добавлю арену.

Guezt Gutsy сказал(а):
сколько же тебе интересно заплатили
Мало ;) Но с условием, что я сам могу его продавать на своих условиях.

Guezt Gutsy сказал(а):
он ориентирован на премиум аккаунт или чисто на подойди сам подбери ины ?
Он премиума не касается. Кто богат, тот и без ботов прокачается. Мой бот прежде всего для тех, кто хочет, что бы их персонаж фармил в их отсутствии. И не только ины собирал. Но и деньги, и шмот, и еще что бы бегал ремонтировался, шмот плавил, камни крафтил и т.д. Пока не весь функционал реализован, но работа идет. Как говориться, были бы кости, а мясо нарастет.

Guezt Gutsy сказал(а):
Если не сложно покажи свой кусок кода на запуск и автологин клиента (мне интересно про кнопку "новая попытка" - она же ошибка любая и выбор конкретного перса в списке если есть список )
Начну с конца. Каждое окно в игре имеет какие-то радикальные различия. Первое различие - это Title данного окна. Соответственно отдельная функция у меня определяет, какое конкретно окно на экране и к этому окну применяется нужное действие. Может не самое лучшее решение, но свою задачу выполняет:
Код:
; Список окон (TITLE)
	$win_game   = "[CLASS:QWidget; TITLE:Drakensang Online: браузерная онлайн-игра в стиле фэнтези]"
	$win_full   = "[CLASS:Nebula3::MainWindow; TITLE:Drakensang Online]"
	$win_start  = "[CLASS:QWidget; TITLE:Drakensang Online | Эпическая онлайн-игра в стиле фентези » Стартовая]"
	$win_server = "[CLASS:QWidget; TITLE:» Стартовая]"
	$win_error  = "[CLASS:QWidget; TITLE:Ошибка]"
	$win_reg    = "[TITLE:Register » Стартовая; CLASS:QWidget]"
	
	Local $WinState[2] ; возвращаемый массив (дескриптор и статус окна)
	
	If WinExists($win_game) Then
		
		If WinExists($win_full) Then
			
			$iState  = WinGetState($win_full, "")

			; Проверка развернуто ли окно на весь экран
			If BitAND($iState, 2) Then
				$WinState[0] = WinGetHandle($win_full)
				$WinState[1] = "full"  ; на весь экран
				Return $WinState
			Else
				$WinState[0] = WinGetHandle($win_game)
				$WinState[1] = "game" ; свернуто
				Return $WinState
			EndIf

		EndIf

		$WinState[0] = WinGetHandle($win_game)
		$WinState[1] = "game" ; свернуто
		Return $WinState

	ElseIf WinExists($win_start) Then
		$WinState[0] = WinGetHandle($win_start)
		$WinState[1] = "start" ; форма авторизации
		Return $WinState
		
	ElseIf WinExists($win_server) Then
		$WinState[0] = WinGetHandle($win_server)
		$WinState[1] = "server" ; выбор сервера
		Return $WinState
		
	ElseIf WinExists($win_error) Then
		$WinState[0] = WinGetHandle($win_error)
		$WinState[1] = "error" ; ошибка
		Return $WinState
		
	ElseIf WinExists($win_reg) Then
		$WinState[0] = WinGetHandle($win_reg)
		$WinState[1] = "reg" ; сброс авторизации
		Return $WinState
		
	Else
		Return 0 ; окно не определено
		
	EndIf

Ну а автологин - самое простое. Показываю:
Код:
; Выполняем авторизацию:
	Sleep(500)	  
	MouseMove ( 614, 228 )          ; навести мышь на логин	  
	MouseClick("left", 614, 228, 1) ; клик на поле логина (если там есть текст, он будет выделен весь)
	Send("^a")                      ; выделяем весь текст в поле (Ctrl+A)
	Send("{DELETE}")                ; стираем весь текст
	Sleep(100)
	Send($GameLogin)                ; пишем логин
	Sleep(700)
	MouseMove ( 614, 258 )          ; навести мышь на пароль
	MouseClick("left", 614, 258, 1) ; клик на поле пароля
	Send("^a")
	Send("{DELETE}")
	Sleep(100)
	Send($GamePassword)             ; пишем пароль
	MouseMove ( 780, 260 )          ; навести мышь на кнопку входа
	MouseClick("left", 780, 260, 1) ; клик на кнопке

	$hWnd = WinWait("» Стартовая", "", 10) ; ждем запуска окна выбора сервера
	Sleep(4000)                            ; ждем подгрузки интерфейса

Выбор перса еще проще. Код даже показывать не буду, там три строчки всего. Если ты, как ты говоришь, писал раньше ботов, то наверняка поймешь, как эту фишку реализовать. Только вот читал-читал, так и не въехал: 1 был вообще вместо клиента у меня и работал на прямых запросах к серверу из трея... И при этом в памяти сидело аж 8 метров этого бота? Жесть! У меня файлик из 300 строк кода весит 10 кило. У тебя 8 метров. (8*1024)*(300/10)=245760 строк кода. Ну минус массивы, минус резерв... Все равно ЖЕСТЬ! Если бы не твоя репа на этом форуме, я бы тебе не поверил! :whistle:
 

Guezt

Продвинутый
Сообщения
335
Репутация
82
sebun
про окна вроде норм код, а вот про ввод пароля и логина ну совсем как-то по детски а если выскочит окно между этим делом какое ? :smile: или еще у тебя кликает мышка просто по координатам и никак от окна не зависит :smile: еще учти что окно у всех в разном месте открывается при запуске :smile:
и кликать лучше не просто через send, а либо через controlsend либо вообще я подозреваю, что можно запуск организовать БЕЗ этих первых окон где ты запускаешь сам клиент вводишь пароль и выбираешь сервер )

да и перед запуском лучше проверить сразу есть или нет копия игры в памяти ) ну много ньюансов )) мне вот интересно в свернутое окно игры можно кликать или нет :smile:

квест багнутый назвал лишь потому, что на нем легко фармить ины нехило за час 1-2к игровой валюты )) при условии что 3-4к это почти 100 рублей реальных денег :smile:

ну а про то что не веришь, нет строк кода поменьше но я даже соврал 13 мегабайт занимает в памяти да бот очень большой там только функций 145кб текстом 4к строк памяти кушает столько думаю потому что COM объекты браузера подключает на post\get запросы для сравнения самой игре надо было 1 гиг свободной памяти - это браузерка да на обычном флеше ))) ))) фулл клиент был, нельзя было только кое какие фишки делать типа украшательства - ну это уже лишнее, я думаю ты не будешь в свой бот 101% вводить покраску вещей так же и я не стал ))
 
Автор
sebun

sebun

Знающий
Сообщения
81
Репутация
5
Смотри. Там у меня не только проверка копии, но и проверка версии операционки, разрешение экрана и т.д. Так что с этим все пучком. По поводу окон. Первое - я определяю, какое окно на экране и получаю дескриптор. По дескриптору обращаюсь к окну и неважно, где оно находится. Я знаю, что окно авторизации лично на моем буке всегда одного размера. Ну можно сразу задать ему размер, но я с этим не стал заморачиваться, так как если разраб сменит интерфейс, то тут придется переделывать все. Никаких дополнительных окон там не выскочит. Единственное, что может произойти - интерфейс будет грузиться дольше обычного и тогда функция начнет ввод логина и пароля до того, как прогрузится графика. Это уже зависит от отдачи игрового сервака. Вот в этом случае появится окошечко, что данные введены неверно. Спасибо за подсказку на счет СontrolSend, сегодня поэкспериментирую. Пока игра в этом случае просто перезапускается.

Далее. После того, как произошло открытие окна, функция ждет еще 5 сек для того, что бы подгрузился сам графический интерфейс. Время ожидания лучше вынести в настройки в некий коэффициент, что бы пользователь мог сам настроить бота под пропускной канал своего инета. Ну далее да, согласен, Сенд выглядит по детски, нет проверки наличия формы, но мне еще ни разу не довелось увидеть сбой на стадии авторизации. Так что все просто и работает как ожидалось. После того, как нажата кнопка Войти, опять ожидание и далее, пока бот не выберет перса и не зайдет в город. Вот в городе уже другая логика запускается. Все функции, работающие с окном игры, юзают показанную мной функцию проверки окна и, если возникает нештатная ситуация, бот просто перезагружает игру и самого себя и продолжает играть. Так что с этим у меня проблем нет. Проблема с определением мобов. Поскольку, как я уже писал, я не лезу в память, а работаю исключительно с графикой, стараясь для каждого действия написать как можно больше рандомов, то определение моба - довольно сложный процесс. Почти в любой локации мобы имеют почти такой же цвет, как и фон. Решил использовать ту особенность, что моб становиться красным при наведении мыши. Написал алгоритм. Работает. Но боссы и без наведения имеют красный круг под ногами, часто перса мочат потому, что он стреляет мимо, в этот красный круг, не обращая внимания на других мобов. В принципе вопрос решаем, просто нужно подумать, как с этим разобраться. lirikmel обещал попробовать написать детектор движения, очень полезная была бы фича.
мне вот интересно в свернутое окно игры можно кликать или нет
Пока я знаю одно - свернутого окна не существует. То есть сам процесс замораживается виндой и память высвобождается. А вот если окно висит на заднем плане, позади другого окна, то клики в нем работают. Может я не прав, пусть тогда меня поправят.
 

bugaj

Знающий
Сообщения
140
Репутация
11
У тебя 8 метров. (8*1024)*(300/10)=245760 строк кода. Ну минус массивы, минус резерв... Все равно ЖЕСТЬ! Если бы не твоя репа на этом форуме, я бы тебе не поверил!

:laugh: у меня бот в памяти 100+ мб занимает
 
Автор
sebun

sebun

Знающий
Сообщения
81
Репутация
5
ну он сказал что бот сидит в трее. Хотя, в принципе лаконичное решение...
Кстати проблема нарисовалась. На чужих компах происходит ошибка при авторизации, мой скрипт не может корректно удалить написанный логин (по ходу не нажимается ctr+a). Кмментирую ввод логина (один фиг он там по умолчанию ставится) - вводит пароль - ошибка, не правильно пишет пароль. Крайне странно. У меня все работает, у человека на таком же ноуте но с украинской раскладкой клавы - проблема. Переключаю в EN, все работает, переключаю в RU или UK, все, не пашет, хотя буквы те же. Что делать? Почитал этот топик. Но хотелось бы определить, какая раскладка у пользователя включена и переключить в инглиш.
 
Автор
sebun

sebun

Знающий
Сообщения
81
Репутация
5
Я написал свою из кода, который нашел здесь.
Код:
Func Set_ENG_Laguage($hWnd = 0)
	Local $sLayoutID = 0x0409
	
	If @KBLayout = 00000409 Or @KBLayout = 0409 Or @KBLayout = 0809  Or @KBLayout = 00000809 Then
		Return 1 ; раскладка уже стоит английская
	Else
	
		Local Const $WM_INPUTLANGCHANGEREQUEST = 0x50
		Local $aRet = DllCall("user32.dll", "long", "LoadKeyboardLayoutW", "wstr", Hex($sLayoutID, 8), "int", 0)
   
		If Not @error And $aRet[0] Then
			If $hWnd = 0 Then
				$hWnd = WinGetHandle(AutoItWinGetTitle())
			EndIf
       
			DllCall("user32.dll", "ptr", "SendMessage", "hwnd", $hWnd, "int", $WM_INPUTLANGCHANGEREQUEST, "int", 1, "int", $aRet[0])
			Return 1
		EndIf
   
		Return SetError(1)
		
	EndIf
	
EndFunc


Теперь проблема с отправкой комбинаций клавиш. Курю дальше форум... :-X


Добавлено:
Сообщение автоматически объединено:

Нашел :ok:
 
Автор
sebun

sebun

Знающий
Сообщения
81
Репутация
5
Возникла проблема - FFColorCount всегда возвращает одно и то же число :'(

Код:
Local $aColorArray[3] = [0xd60000, 0xf22529, 0xac0503]
	Local $IMGpos[4] = [798, 14, 824, 30]

	FFAddColor($aColorArray)
	FFSnapShot($IMGpos[0], $IMGpos[1], $IMGpos[2], $IMGpos[3], 0)
	FFKeepColor(-1, 20, False)

	Local $aCoords = 0
	$aCoords = FFColorCount ( 0xd60000, 20, False, 0, 0, 0, 0, 0 )



Добавлено:
Сообщение автоматически объединено:

Так и не нашел решение. За бугром этой функцией почти не пользуются, все примеры - когда ей передаются координаты участка и она их сама скриншотит и считает. У меня скриншот сделан и картинка обработана через FFKeepColor, теперь нужно посчитать, сколько на ней пикселей (желательно еще их все сделать одного цвета, убрав градации). Но вот FFColorCount почему то выдает неверные значения. Может ей нужно скормить правильные размеры картинки?


Добавлено:
Сообщение автоматически объединено:

Эх, тишина... Применил FFNearestSpot и задачу решил. Но это не то немного. PixelSearch читает только с окна, а мне нужно сначала отсеять цвета на картинке и работать с находящимся в памяти фрагментом. FFColorCount как нельзя кстати подходит под эти задачи, но так и не понял причину глюка.
 
Верх