Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

UoKit.com Форумы _ UO Pilot _ Последовательное выполнение скриптов

Автор: BlackBot 17.8.2021, 8:04

Доброго дня друзья.
Интересует вопрос следующего плана.
Имеется игра в котороой в неактивном окне не работает отправка left, send - что крайне необходимо для управления. Kleft работает нормально - активирует окно и кликает в заданные координаты.
Возникла мысль играя в 6 и более окон выполнять действия в всех запущенных клиентах игры.
Собственно вопрос. Возможно ли написав необходимый скрипт, и привязав каждый скрипт к одному клиенту, реализовать поочередное выполнение каждого скрипта с последующей активацией следующего скрипта, управляющего другим клиентом?
Действия будут одинаковые - на компе (сервере) лидер ставить группу в очередь на арену, на клиенте кликер ждет подтверждения сбора арены и жмет кнопку "битться на арене" - отдает управление следующему скрипту - тот делает тоже в своем окне и так далее. После чего скрипт ждет результатов арены и выходит с нее вставая в ожидание следующей.

Автор: kyja 17.8.2021, 10:44

Запуск скриптов
https://uopilot.tati.pro/index.php?title=Start_script_(Lua)
https://uopilot.uokit.com/wiki/index.php?title=Start_script

Автор: cirus 17.8.2021, 10:50

Если действия одинаковые для всех окон, то можно использовать один скрипт, в нём менять рабочее окно.

Автор: BlackBot 17.8.2021, 11:29

Start_script нашел. Но почему то напрямую

спойлер

Код

kleft 216 278
wait 1500
sendex {f3}
wait 1500
kleft 141 541
wait 2000
sendex {ESC}
wait 500
Start_script 1
end_script


Работает некорректно. Может в одном окне начать выполнять действия - которые должны выполнится уже в другом. Прикрутил проверку GetWindow через if Если GetWindow равен привязанному - идет выполнение действий.
Думал про выполнение в цикле - но окна расположенны в два слоя, первый ряд 3 окна сверху рабочего стола. Второй ряд 3 окна перекрыт на две-трети верхними.
Есть мысли как в цикле активировать часть окон через верхнюю треть видимого окна, а часть - через нижнюю треть?
Или как то можно активировать окна програмно?

Автор: cirus 17.8.2021, 13:30

Цитата
Или как то можно активировать окна програмно?

Код
set %handle findwindow ("Блокнот")      // найти окна с указанным именем

log clear
log mode compact

set #n size(%handle)   // количество окон

if #n = 0
    log Окна не найдены, скрипт остановлен
    end_script
end_if

log Всего найдено окон: #n

for #i 1 #n   // цикл для всех окон
    showwindow %handle[#i 1]     // показывать окно
    wait 2000     // пауза 2 секунды
    // тут нужные действия для окна
end_for
end_script

Автор: BlackBot 17.8.2021, 15:09

То что надо) Благодарю! Какие возможности прям открываются ) Пойду эксперементировать
А как при открытии окна перейти в Относительные координаты окна?
Разобрался с координатами

Код
set workwindow %handle[#i 1]//переключаемся в координаты окна

p.s. showwindow MINIMIZE // свернуть текущее рабочее окно - Не работает нынче?

Код
 showwindow %handle[#i 1] minimize //сворачиваем отработанное окно

Странно - но с маленькими буквами работает сворачивание..

Автор: BlackBot 19.8.2021, 7:27

Еще вопросик. Переменные между скриптами передаются? Или в каждом скрипте необходимо объявлять свои? Если в одном скрипте хендл окна определить - в другом его можно использовать?

Автор: cirus 19.8.2021, 11:08

https://uopilot.uokit.com/wiki/index.php?title=Переменные_из_других_скриптов

Автор: BlackBot 21.8.2021, 19:30

Cirus, Уважаемый - подскажи следущее
- Есть окно игры в котором скажем открыт чат. Если в скрипте пишем

Код
sendex "сообщение пользователю"
допустим, а в винде в это время включена ENG раскладка - то получаем на ввыходе абракадабру нечитаемую.
Есть возможность проверки системного языка и переключения его в необходимую раскладку?

Код
// Пример 3
// печатаем одной строкой текста: Вася.Пупкин@gmail.com
set $var setlayout (0419)  // включили русскую раскладку
sendex Dfcz/Gegrby         // Вася.Пупкин (смотрим на клавиатуру)
set $var setlayout (0409)  // включили английскую раскладку
sendex ~2gmail.com         // @gmail.com
End_script


Не совсем понял данный пример
set $var setlayout (0419) // включили русскую раскладку - включит русскую раскладку в любом случае? Но писать все же надо на английских клавишах?

Автор: cirus 21.8.2021, 20:28

Код
wait 3000                         // пауза 3 секунды
set #h getwindow (0)              // получить хендл активного окна
set workwindow #h                 // сделать рабочим окном
set $var setlayout (0419)         // переключить на русскую раскладку
sendex "сообщение пользователю"   // написать текст
end_script

Автор: BlackBot 22.8.2021, 6:40

А если после необходимо на английском написать что либо?

Код

wait 3000                         // пауза 3 секунды
set #h getwindow (0)              // получить хендл активного окна
set workwindow #h                 // сделать рабочим окном
set $var setlayout (0419)         // переключить на русскую раскладку
set SendExDelay 100
sendex "сообщение пользователю"   // написать текст
wait 2000
set $var setlayout (0409)  // включили английскую раскладку
sendex hello cirus   // написать текст
end_script

Так получается?

Автор: cirus 22.8.2021, 10:47

Цитата
Так получается?

Да.

Автор: BlackBot 26.8.2021, 12:07

Вопросик еще возник.
Имеется окно браузера, в нем есть строка меню из 8 пунктов.
Можно ли в зависимости от ширины окна - вычислить координаты клика?
Умеет ли пилот производить математические действия?

Код
set #X1 %arr[#1 1] / 8*6

Строка меню - 8 пунктов, необходимо нажать на 6 пункт. Максимальное разрешение окна нужно поделить на 8 пунктов меню и умножить на 6. На выходе получаем необходимые координаты по Х, которые должны соответствовать 6 пункту меню...
Пните в направлении как это реализовать

Автор: cirus 26.8.2021, 12:23

Цитата
Максимальное разрешение окна нужно поделить на 8 пунктов меню и умножить на 6.

Код
log clear
log mode compact
get windowpos workwindow #X #Y #width #height
log Размеры окна: #width #height
log Позиция окна: #X #Y
set #posX #width / 8 * 6
log #posX
move #posX 100
end_script

Автор: BlackBot 8.9.2021, 14:00

Цитата(cirus @ 26.8.2021, 12:23) *




Загвоздочка возникла.. Есть игра нонтаргет - мышкой ведешь влево = персонаж поворачивается влево, вправо = вправо

Так вот если мышкой двигаю - все норм.
А на
Код
else
get mouse_pos #x #y
set #x #x + 5
mouse enable

move #x #y
kleft #x #y
end_if
end_while

нет реакции... На move_smooth также ноль внимания На kleft все как положено - стреляет. Куда копать?

Автор: cirus 8.9.2021, 14:33

Цитата
Куда копать?

Функциями пилота не сделать. Через ардуино можно.

Автор: BlackBot 8.9.2021, 18:15

Цитата(cirus @ 8.9.2021, 14:33) *

Функциями пилота не сделать. Через ардуино можно.


Порылся на задворках форума) Нашел вариант - Впринципе работает. Удалось повернуть героя и заставить бежать.
https://forum.uokit.com/index.php?s=&showtopic=69850&view=findpost&p=434892
code

Код
//...

//repeat 213  // полный оборот
repeat 107
call move 10 0      // сдвинуть курсор на 100 вправо и на 0 вверх
end_repeat

sendex_down w
wait 3000
sendex {Spacebar}
wait 3000
sendex_up w
//...
end_script



proc move #x #y $abs
set linedelay 0
set #flags 1
if $abs = abs
set #flags 32769
set #x 65536 * #x / screenwidth
set #y 65536 * #y / screenheight
end_if
exec winapiexec.exe u@mouse_event #flags #x #y 0 0
end_proc


Автор: BlackBot 9.9.2021, 16:10


Товарищи - подскажите как перемешать массив? А то боты все время в одноой и той же последовательности входят в игру)) Как то палевно...

Код

set %mult [1] mult1                          // имя мульта
set %mult [2] mult2                          // имя второго мульта
set %mult [3] mult3                          // третьего
set %mult [4] mult4                          // имя четвертого
set #size size(%mult)                            // всего мультов

Автор: cirus 10.9.2021, 1:41

Цитата
подскажите как перемешать массив?

Код
set %mult [1] mult1                          // имя мульта
set %mult [2] mult2                          // имя второго мульта
set %mult [3] mult3                          // третьего
set %mult [4] mult4                          // имя четвертого
set #size size(%mult)                            // всего мультов

log clear
log mode compact
// перемешивание
for #i 1 #size
    set #rand 1 + random(#size)
    set $tmp %mult [#i]
    set %mult [#i] %mult [#rand]
    set %mult [#rand] $tmp
end_for
// вывод массива
for #i 1 #size
    log %mult [#i]
end_for
end_script

Автор: BlackBot 10.9.2021, 5:48

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

Автор: DarkMaster 11.9.2021, 12:07

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

Всмысле? Дублироваться значения которые не дублировались ранее - не будет, никакие значения которые присутствовали в массиве не пропадут. Массив именно перемешивается.

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

Автор: DarkMaster 11.9.2021, 12:20

Цитата
set #rand 1 + random(#size)

Вот это разве что можно чуть изменить. Вроде как более правильное распеределение получается при:
set #dynamicpart #size - #i
set #rand #i + random(#dynamicpart)
читать можно про метод Дуршенфельда

Автор: BlackBot 11.9.2021, 14:40

Извиняюсь - не разобралсо )
А кто-нибудь заморачиввался попыткой управления в 3д шутере?


Автор: DarkMaster 11.9.2021, 19:35

Было дело. Смысла мало - динамика слишком велика для графического анализа. Если прям хочется, то тупо читать память, искать там координаты врагов, свои, считать вектора. Правда пилот тут уже становится постольку поскольку.

Автор: DarkMaster 12.9.2021, 6:56

Вобщем не поленился я... Потестил нормальное распределение. Разница существенная, при статичном свапе от 1 до #arr отклонения от ожидаемого до 20%. math.random(i, #arr) однозначно лучше - отклонения в пределах статистической погрешности.

код для теста
Код
-- 1 - обмен позиций 1-10
-- 2 - обмен позиций i-10
local method = 2

math.randomseed(os.clock())

local n = 1000000

-- инициализируем счетчик
local counter = {}
for i = 1, 10 do
    counter[i] = {}
    for j = 1, 10 do
        counter[i][j] = 0
    end
end

for z = 1, n do
    local a = {1,2,3,4,5,6,7,8,9,10}
    for i = 1, #a do
        local tmp = a[i]
        local r
        if method == 1 then
            r = math.random(1,10)
        else
            r = math.random(i,10)
        end
        a[i] = a[r]
        a[r] = tmp
    end
    for i = 1, #a do
        counter[a[i]][i] = counter[a[i]][i] + 1
    end
end

local p = {}
for i = 1, 10 do
    p[i] = {}
    for j = 1, 10 do
        p[i][j] = math.abs(10 - counter[i][j] / (n / 100)) * 10
    end
end

for i = 1, 10 do
    log("% отклонения перемещения "..i.." от ожидаемого в позицию:")
    for j = 1, 10 do
        local s = string.format("%f",p[i][j])
        if p[i][j] < 10 then
            s = "0"..s
        end
        if j < 10 then
            log(" "..j..": "..s)
        else
            log(j..": "..s)
        end
    end
end

lua перемешать массив. готовая функция
Код
local shuffle = function(a)
    math.randomseed(os.clock())
    for i = 1, #a do
        local tmp = a[i]
        local r = math.random(i, #a)
        a[i] = a[r]
        a[r] = tmp
    end
    return a
end

Автор: BlackBot 12.9.2021, 7:04

Цитата(DarkMaster @ 12.9.2021, 6:56) *

Вобщем не поленился я... Потестил нормальное распределение. Разница существенная, отклонения от жидаемого до 20%. math.random(i, #arr) однозначно лучше.



Это конечно хорошо - вещь иногда полезная весьма. Но тогда весь код надо на ЛУА переносить)
А с ориентацией в 3d играх, беда ( Затратный код получается - игру переписать можно) Слишком много входных данных для анализа нужно - цвет не вариант, изображения меняются взависимости от углаобзора, анализ растояния до припятствия невыполним, или слишком затратен.
Пока остается только - тригер -> время бега-> поиск очередного тригера -> опять бег

Автор: DarkMaster 12.9.2021, 7:28

Цитата
Но тогда весь код надо на ЛУА переносить

Я выше приводил код для фикса в старом синтаксисе. Там всего лишь добавляется одна переменная.

Цитата
set #dynamicpart #size - #i
set #rand #i + random(#dynamicpart)



Цитата
А с ориентацией в 3d играх, беда

Ориентация как раз зачастую более-менее решаемая, а вот динамическое определение окружающих мобов/игроков уже намного сложнее.

Автор: BlackBot 12.9.2021, 8:21

В игре - мобы и игроки разным цветом горят - это я вижу более менее решаемым. Сканировать экран на поиск цвета - при совпадении поворачивать игрока и центрировать на совпадение цвета.
Но тут встает вопрос - если игрок дальнобойный, то хорошо. А вот если ближнего боя - встает вопрос о дистанции. Как ее определить?

Автор: DarkMaster 12.9.2021, 8:27

Цитата
Но тут встает вопрос - если игрок дальнобойный, то хорошо. А вот если ближнего боя - встает вопрос о дистанции. Как ее определить?

Размер цели, цвет скилов, миникарта. Все сильно зависит от приложения.

Автор: BlackBot 12.9.2021, 8:43

скилы всегда активны - они не привязаны к дистанции. Можно просто стоять и лупить со всех стволов в пустоту)) На миникарте кроме твоего расположения тоже нет информации..
А вот с размером цели - надо подумать. Мониторить массив совпадений цвета?

Автор: DarkMaster 12.9.2021, 10:45

Цитата
Мониторить массив совпадений цвета?

Самый простой вариант.

Автор: BlackBot 12.9.2021, 16:38

затык очередной - почему скрипт так себя ведет?

kod+log

Код

    set $X findimage (20 70 300 200 (Scripts\Blade\img\arena_box.bmp) %arrt 2) // ищем панель управления аренами
    if $X >0 //
log найдена панель управления аренами
            set #X1 %arrt[#1 1]
            set #Y1 %arrt[#1 2]
            kleft #X1,#Y1     //
log тут #X1,#Y1
wait 2000

в логе получаем
21:34:22 2 (test.txt, 21): Открывваем управление аренами
21:34:25 2 (test.txt, 28): найдена панель управления аренами
21:34:26 2 (test.txt, 32): тут 0,0



область указывваю одну - получаю координаты левые ) Причем если картинка действительно на экране - все работает корректно

Вот где тут косяк? Час потратил отлавливая этот баг smile.gif
code

Код

set $X findimage (10 70 300 1400 (Scripts\Blade\img\arena_box1.bmp) %arr 2) // Так все работает норм
if $X > 0
    log lose
    set $T FindImage (20 70 300 200 (Scripts\Blade\img\arena_box1.bmp) %ar 2) // так находит картинку даже если ее на экране нет
     if $T >0 //
                log найдена панель управления аренами вне цикла
            set #X1 %ar[#1 1]
            set #Y1 %ar[#1 2]
                kleft #X1,#Y1     //
                log тут #X1,#Y1   ar
     else
     log вне цикла нет панели арен
     end_if
end_if



Вопросик такой - находясь в процедуре можно вызывать другую процедуру?
Ответ - можно

Автор: BlackBot 17.9.2021, 15:18

Цитата(DarkMaster @ 12.9.2021, 6:56) *

Вобщем не поленился я... Потестил нормальное распределение. Разница существенная, при статичном свапе от 1 до #arr отклонения от ожидаемого до 20%. math.random(i, #arr) однозначно лучше - отклонения в пределах статистической погрешности.


С многомерными массивами версия для пилота - не фурыкает. Склеивает значения в одномерный массив.
Это так для справки - если кто будет мучаться )

Автор: DarkMaster 18.9.2021, 4:54

Цитата
С многомерными массивами версия для пилота - не фурыкает.

В смысле на старом синтаксисе? Вообще старый синтаксис очень условно "многомерный". Он двумерный. Дальше только лютыми костылями. Для двумерного массива не вижу особой проблемы поэлементно скопировать значения. Ну и мой код принципиально не отличается от кода Cirus'a - все проблемы будут те же самые. Это так на всякий случай для потомков) А то прозвучало с цитатой двусмысленно.

Автор: Sergei1234 18.9.2021, 17:21

Народ через какую функцию в с++ осущесвлекн клик мышью по хендлеру, поскажите, я перепробовал sendmessage, postmessage,SendInput не идет чего то

Автор: cirus 18.9.2021, 18:08

Цитата
Народ через какую функцию в с++ осущесвлекн клик мышью по хендлеру

SendMessage, WM_LBUTTONDOWN и WM_LBUTTONUP.

Автор: Sergei1234 18.9.2021, 18:43

проблема решена

Автор: Cockney 18.9.2021, 18:50

Цитата(Sergei1234 @ 18.9.2021, 18:43) *

это си шарп, но не столь важно



не думаю что это совсем верное утверждение, хотя бы из того, что подобный код на с++ не зависнет, а на шарпе повис.

Не видно что за FindWindow, там мб выхода из цикла нет

Автор: cirus 18.9.2021, 18:51

Неверно заданы значения констант WM_LBUTTONDOWN и WM_LBUTTONUP.
Через пилот так:

Код
--lua
local ffi = require("ffi")
local WM_LBUTTONDOWN = 0x0201
local WM_LBUTTONUP = 0x0202
ffi.cdef[[
int SendMessageA(int hWnd, int Msg, int wParam, int lParam);
int PostMessageA(int hWnd, int Msg, int wParam, int lParam);
]]

local wndHandle = workwindow()   -- привязаться к окну Ctrl+A
local x = 200
local y = 100

ffi.C.SendMessageA(wndHandle, WM_LBUTTONDOWN, 0, y * 65536 + x)
wait (100)
ffi.C.SendMessageA(wndHandle, WM_LBUTTONUP, 0, y * 65536 + x)

Если не работает SendMessage, то можно попробовать PostMessage.

Автор: Sergei1234 18.9.2021, 19:07

Цитата(cirus @ 18.9.2021, 18:51) *

Неверно заданы значения констант WM_LBUTTONDOWN и WM_LBUTTONUP.
Через пилот так:
Код
--lua
local ffi = require("ffi")
local WM_LBUTTONDOWN = 0x0201
local WM_LBUTTONUP = 0x0202
ffi.cdef[[
int SendMessageA(int hWnd, int Msg, int wParam, int lParam);
int PostMessageA(int hWnd, int Msg, int wParam, int lParam);
]]

local wndHandle = workwindow()   -- привязаться к окну Ctrl+A
local x = 200
local y = 100

ffi.C.SendMessageA(wndHandle, WM_LBUTTONDOWN, 0, y * 65536 + x)
wait (100)
ffi.C.SendMessageA(wndHandle, WM_LBUTTONUP, 0, y * 65536 + x)

Если не работает SendMessage, то можно попробовать PostMessage.


спасибо проблема решена я лохопед неверный код WM_LBUTTONDOWN сделал

Автор: Sergei1234 18.9.2021, 20:12

еще такой вопрос перекрытое окно скриншот можно в с++ сделать? как?
клик мышью вот так венрнее не знаю что у вас

SendMessage(wndHandle, WM_MOUSEMOVE, 0, coord);
SendMessage(wndHandle, WM_LBUTTONDOWN, 0, coord);
Thread.Sleep(100);
SendMessage(wndHandle, WM_LBUTTONUP, 0, coord);
далее принтскрин неактивного окна, вернее перекрытого, с# код, я думаю кому надо разберется полезно для бота, который работает по поиску в картинке, а не с памятью, что бы не забанили
это если есть манипуляции с масштабом

public class Scale
{

[DllImport("gdi32.dll")]
static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
public enum DeviceCap
{
VERTRES = 10,
DESKTOPVERTRES = 117,

// http://pinvoke.net/default.aspx/gdi32/GetDeviceCaps.html
}


public float getScalingFactor()
{
Graphics g = Graphics.FromHwnd(IntPtr.Zero);
IntPtr desktop = g.GetHdc();
int LogicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.VERTRES);
int PhysicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.DESKTOPVERTRES);

float ScreenScalingFactor = (float)PhysicalScreenHeight / (float)LogicalScreenHeight;

return ScreenScalingFactor; // 1.25 = 125%
}

}

[DllImport("User32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool PrintWindow(IntPtr hwnd, IntPtr hDC, uint nFlags);

[DllImport("user32.dll")]
static extern bool GetWindowRect(IntPtr handle, ref Rectangle rect);


private static double SCALEoFsCREEN = new Scale().getScalingFactor();
public void CaptureWindow(IntPtr handle)
{
// Get the size of the window to capture
Rectangle rect = new Rectangle();
GetWindowRect(handle, ref rect);

// GetWindowRect returns Top/Left and Bottom/Right, so fix it
rect.Width = rect.Width - rect.X;
rect.Height = rect.Height - rect.Y;

// Create a bitmap to draw the capture into
using (Bitmap bitmap = new Bitmap((int)(rect.Width * SCALEoFsCREEN), (int)(rect.Height* SCALEoFsCREEN)))
{
// Use PrintWindow to draw the window into our bitmap
using (Graphics g = Graphics.FromImage(bitmap))
{
IntPtr hdc = g.GetHdc();
if (!PrintWindow(handle, hdc, 0))
{
int error = Marshal.GetLastWin32Error();
var exception = new System.ComponentModel.Win32Exception(error);
Debug.WriteLine("ERROR: " + error + ": " + exception.Message);
// TODO: Throw the exception?
}
g.ReleaseHdc(hdc);
}

// Save it as a .png just to demo this
bitmap.Save("Example.png");
}
}

Автор: Sergei1234 24.9.2021, 10:54

а вот еще вопрос про сендмесседж, у меня несколько мониторов и клик мышью происходит только в том случае, если курсор мыши находится в испольнительном мониторе, как с этим бороться?: переставлять каждый раз курсор? на это 100 мс требуется а как без них?

Автор: BlackBot 24.9.2021, 18:08

Убери внизу окна программы задержку. Вместо 100 - выставить 0

Автор: DarkMaster 24.9.2021, 20:39

Цитата
Убери внизу окна программы задержку. Вместо 100 - выставить 0

Для луа эта задержка игнорируется.

Автор: Sergei1234 25.9.2021, 10:28

нее проверено если мышь нахолддится в другом мониторе sendmessage не пашет, movecursor тоже. может что то еще есть?

Автор: BlackBot 25.9.2021, 12:57

Привязка окна и активация его при необходимости действий? Работа с координатами активного привязанного окна? Тогда вроде пофиг где мышь находится...

Автор: Madeus 25.9.2021, 13:41

2 моника, проблем нет.

Автор: Sergei1234 12.2.2022, 18:49

народ а взгляните скрипт Ctrl+ space как катится в уо пилот*? заранее благодарен

Автор: Sergei1234 14.2.2022, 12:01

Цитата(Sergei1234 @ 12.2.2022, 18:49) *

народ а взгляните скрипт Ctrl+ space как катится в уо пилот*? заранее благодарен
я имю ввиду как ьзаслать в перекрытое окно нажатие двух клавиш, через sendmessage or postmessage


Русская версия Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)