Solomon753 2 Опубликовано 3 Декабря 2014 (изменено) Уважаемые форумчане, помогите пожалуйста со скриптом. Привожу упрощенный пример гашения отдачи в шутере. Как сделать, чтобы при отпускании кнопки мыши цикл сразу прерывался? Сейчас дашь небольшую очередь, отпускаешь кнопку, а мышь дёргает пока цикл не закончится. delay = 54 --задержка между выстрелами x,y = 0,50 EnablePrimaryMouseButtonEvents(true); function OnEvent(event, arg) if (event == "MOUSE_BUTTON_PRESSED" and arg == 1) then Sleep(delay) MoveMouseRelative(x,y) Sleep(delay) MoveMouseRelative(x,y) Sleep(delay) MoveMouseRelative(x,y) Sleep(delay) MoveMouseRelative(x,y) Sleep(delay) MoveMouseRelative(x,y) Sleep(delay) MoveMouseRelative(x,y) end end Пробовал вариант: repeat -- Тело if not IsMouseButtonPressed(1) then break end и ему подобные, но либо выдаётся ошибка, либо остановки не происходит. В инете искал информацию, но везде примеры прерывания только с оператором for и введением переменной, как это применить здесь пока не разобрался, удивлён что нет простого решения для игровой мыши. Изменено 3 Декабря 2014 пользователем Solomon753 Поделиться этим сообщением Ссылка на сообщение
Solomon753 2 Опубликовано 3 Декабря 2014 (изменено) Solomon753, Всем будет гораздо проще, если вы опишете задачу которую пытаетесь решить. У меня ировая мышка Logitech G500, играю в онлайн-шутер, а именно Warface. У всего оружия есть отдача, эту отдачу хорошо убирают макросы для мышек X7 компании A4tech, там прилагается специальное ПО для этого дела, и макросы писать проще. У лоджитека только консоль на Lua, но тоже народ пишет, только в русскоязычном инете очень мало примеров именно для шутеров. Теперь к делу. Макрос нужен чтобы при стрельбе из автоматического оружия, после каждой выпущенной пули центр прицела(экрана) возвращался на исходную позицию, т.е. чтобы команды макроса синхронно с выстрелом тянули мышь в противоположное направление отдачи на расстояние увода прицела. Задержки и координаты подобрать опытным путём не сложно, макрос работает. Только проблема в том, что патронов 30 и если дал очередь из 5 и отжал кнопку макрос не останавливается, а дёргает мышь пока не истечёт время вылета всех 30. Итак задача, чтобы при отжатии левой кнопки мыши мгновенно останавливался цикл компенсации отдачи, а при повторном нажатии начинался сначала. У A4tech подобное прерывание цикла реализовано в ПО, а не в самом макросе, хотелось бы это же реализовать на Lua. На англоязычном форуме лоджитека нашел подобный вопрос, только решение предлагаемое там совершенно мне непонятно и делает цикл неудобным для быстрого редактирования, если оно вообще работоспособно. http://forums.logitech.com/t5/G-series-Gaming-Mice/Help-Regarding-Lua-Mouse-Script-in-LGS/m-p/1331203/highlight/true Вот ещё тщетная попытка остановить цикл с помощью оператора until not , тут он сперва тело завершает, потом по событию останавливается. http://stackoverflow.com/questions/24578998/game-lua-scripting-using-couroutine-or-polling Я так понимаю нужны операторы либо break, либо AbortMacro, как работать с последним не разобрался, мало примеров нашел. Хотелось бы такое решение, чтобы можно было быстро редактировать смещение мыши для каждой итерации. В крайнем случае хоть какое-то решение уже результат. Ещё появилась следующая идейка: создать переменную принимающую при нажатии кнопки значение A, а при отпускании B, как только она принимает значение B цикл прерывается, а по принятию А выполняется тело. Если такое возможно подскажите как это более грамотно прописать в скрипте. Изменено 3 Декабря 2014 пользователем Solomon753 Поделиться этим сообщением Ссылка на сообщение
Solomon753 2 Опубликовано 3 Декабря 2014 (изменено) Solomon753, скорее всего тут тебе не помогут, надо хоть немного знать документацию по твоему случаю. Да со смещением мыши я разобрался, там всё элементарно, меня только прерывание цикла интересует, всё остальное знаю как. На форумах нет ничего путного, ужасно реализована поддержка Lua лоджитеком, до всего самому докапываться надо. Инструкция API вот: http://www.scribd.com/doc/228594915/G-SeriesLuaAPIтолько там ни слова про прерывание. Один я тут цикл не вижу? И зачем несколько раз вызывается Sleep(delay) MoveMouseRelative(x,y) Да это в примере я кусок тестового макроса дал, х и у в каждом шаге разные, на каждом выстреле отдача кидает куда попало. Вот например другой аналогичный скрипт из инета EnablePrimaryMouseButtonEvents(true); local recoil = not true; function OnEvent(event, arg) if (event == "MOUSE_BUTTON_PRESSED" and arg == 5) then recoil = not recoil OutputLogMessage("AK47 No Recoil", 2014) end if IsMouseButtonPressed(3) and recoil then Sleep(1) if (event == "MOUSE_BUTTON_PRESSED" and arg == 1) then Sleep(98) MoveMouseRelative(0,8) Sleep(98) MoveMouseRelative(5,21) Sleep(98) MoveMouseRelative(-5,26) Sleep(98) MoveMouseRelative(0,23) Sleep(98) MoveMouseRelative(10,33) Sleep(98) MoveMouseRelative(12,20) Sleep(98) MoveMouseRelative(8,33) Sleep(98) MoveMouseRelative(-14,15) Sleep(98) MoveMouseRelative(-35,4) Sleep(98) MoveMouseRelative(-16,2) Sleep(98) MoveMouseRelative(5,3) Sleep(98) MoveMouseRelative(-12,2) Sleep(98) MoveMouseRelative(-18,2) Sleep(98) MoveMouseRelative(-10,2) Sleep(98) Sleep(98) end end end Там для прерывания цикла предлагают такое решение, только я в него пока что не въехал, 3 день только в Lua разобраться пытаюсь. sleep_duration = 98 recoil_coords = { { x = 0, y = 8 }, { x = 5, y = 21 }, { x = -5, y = 26 }, } function OnEvent(event, arg) if event == "PROFILE_ACTIVATED" then EnablePrimaryMouseButtonEvents(true); end if (event == "MOUSE_BUTTON_PRESSED" and arg == 5) then recoil = not recoil if recoil then ClearLCD() OutputLCDMessage("AK47 No Recoil - ON", 2014) else ClearLCD() OutputLCDMessage("AK47 No Recoil - OFF", 2014) end end if IsMouseButtonPressed(3) and recoil then if (event == "MOUSE_BUTTON_PRESSED" and arg == 1) then for i, v in ipairs(recoil_coords) do Sleep(sleep_duration) if not (IsMouseButtonPressed(1) and IsMouseButtonPressed(3)) then break end MoveMouseRelative( recoil_coords[i].x, recoil_coords[i].y ) end end end end EnablePrimaryMouseButtonEvents(true) -- видимо включение событий Это разрешение использовать левую кнопку для макрома, API требует. Оператор while разумное решение, уже думал на этим, только именно к циклу его нужно приделать. А MoveMouseRelative тоже API требует это писать. В предыдущем посте ссылка на API. Изменено 3 Декабря 2014 пользователем Solomon753 Поделиться этим сообщением Ссылка на сообщение
Solomon753 2 Опубликовано 3 Декабря 2014 (изменено) while это и есть цикл. Зачем его ещё куда-то приделывать? Код-то тестил, который я выше привел? Код принимает, только мышь ничего не делает при нажатии, подозреваю что из-за этого: local LEFT_BTN = 1 if event == "MOUSE_BUTTON_PRESSED" and arg == LEFT_BTN В API не упоминается что вместо номера кнопки можно переменную поставить Убрал переменную, сделал так, тоже ничего local delay = 54 -- задержка между выстрелами local x, y = 0, 50 EnablePrimaryMouseButtonEvents(true) -- видимо включение событий function OnEvent(event, arg) if (event == "MOUSE_BUTTON_PRESSED" and arg == 1) then while IsMouseButtonPressed(1) do Sleep(delay) MoveMouseRelative(x, y) end end end Для эксперимента поменял "MOUSE_BUTTON_PRESSED" на "MOUSE_BUTTON_RELEASED" , при отжатии цикл выполняется полностью(добавил еще несколько шагов), только как while разрешает это делать если кнопка не нажата. Изменено 3 Декабря 2014 пользователем Solomon753 Поделиться этим сообщением Ссылка на сообщение
Solomon753 2 Опубликовано 4 Декабря 2014 (изменено) Выводи в лог на экран что-нибудь (вроде там функция была), проверь вообще идет ли выполнение кода внутри цикла. Как видишь While не выполняется. Но что странно, консоль приняла код на загрузку в мышь, про ошибки молчит. Изменено 4 Декабря 2014 пользователем Dennis_Chikin Поделиться этим сообщением Ссылка на сообщение
Solomon753 2 Опубликовано 4 Декабря 2014 (изменено) Подскажи пожалуйста ссылку на API http://www.scribd.com/doc/228594915/G-SeriesLuaAPI Пробуй так. Попробовал, мышь тянет вниз как бешеную, никакие нажатия не останавливают, до того как успел нажать alt-f4 консоль вместе с драйвером аварийно завершила работу. Изменено 4 Декабря 2014 пользователем Solomon753 Поделиться этим сообщением Ссылка на сообщение
Solomon753 2 Опубликовано 4 Декабря 2014 Сделал чтобы действие каждой операции выводилось на дебаггер, вот что получилось: Как видим на 4 операции циклу благополучно передаётся управление, а отжатие кнопки не определятся вообще. Поделиться этим сообщением Ссылка на сообщение
Solomon753 2 Опубликовано 5 Декабря 2014 (изменено) Скрипт, который ты тестировал (как мы уже выяснили) не годится. Попробуй мой вариант чуть выше. И поиграйся со временем задержки в Sleep(30) -- тут нужно подобрать оптимальное время задержки При всех задержках тело цикла выполняется полностью, повторяется пока зажата кнопка, как если бы использовались операторы repeat и until not, эффект точно такой же. Ставил задержку даже 1000, драйвер точно бы успел перехватить отжатие. Сюда бы Break как-то запихнуть, он в цикле While должен делать полное прерывание тела. В скриптах в инете много вижу такое сочетание как пример прерывания. Только там другие задачи решаются. Надо бы что-то вроде: if not IsMouseButtonPressed(1) then break end только и здесь тело не прерывается, хотя по логике обязано. Эврика!!! Получилось... Вот решение : local delay = 54 -- задержка между выстрелами local x, y = 0, 50 function OnEvent(event, arg) if (event == "MOUSE_BUTTON_PRESSED" and arg == 1) then Sleep(7) -- БЕЗ ЭТОЙ ЗАДЕРЖКИ СКРИПТ НЕ РАБОТАЕТ, СПАСИБО Nazgool ЗА ИДЕЮ while IsMouseButtonPressed(1) do Sleep(delay) MoveMouseRelative(x, y) if not IsMouseButtonPressed(1) then break end Sleep(delay) MoveMouseRelative(x,y) if not IsMouseButtonPressed(1) then break end Sleep(delay) MoveMouseRelative(x,y) if not IsMouseButtonPressed(1) then break end end end end Конечно увидев это профессиональный программист упадёт со смеху, но оно работает. Идея Nazgool с задержкой тоже оказалась верна, поставил 7мс, при 5 слегка подлагивает при очень быстрых нажатиях(может исполнение проигнорировать), а на 3 уже не работает. Теперь хотелось бы найти более грамотное решение задачи, как одной строкой объяснить циклу что после каждой итерации нужно проверять состояние кнопки. Но конечно предпочтительнее параллельное отслеживание состояния как в предыдущих скриптах, видимо дело именно в отсутствии задежки в них, надо будет поэкспериментировать. Изменено 5 Декабря 2014 пользователем Solomon753 Поделиться этим сообщением Ссылка на сообщение
Solomon753 2 Опубликовано 5 Декабря 2014 (изменено) Solomon753 сказал(а) тело цикла выполняется полностью, повторяется пока зажата кнопка А разве не это требовалось? Мне прерывание выполнения именно тела нужно по отжатию, т.е остановка после любой итерации, без завершения выполнения тела. while IsMouseButtonPressed(1) do как раз и проверяет на каждом новом круге "нажата ли кнопка?" Ну если хочется с break-ом, то можно переписать так : А тут вот именно что "на каждом новом круге", т.е всё тело выполняется полностью в любом случае, не рубится по событию, я этот код давно пробовал, он работает так же как цикл "repeat - until not", об этом выше упоминал уже. В таком варианте не происходит проверки после каждой итерации состояния кнопки, пока всё тело не выполнится. Кстати сегодня задержку между "if (event == "MOUSE_BUTTON_PRESSED" and arg == 1) then" и "while IsMouseButtonPressed(1) do" пришлось до 15 увеличить, видимо от загрузки процессора и приоритетности зависит как быстро драйвер о состоянии кнопки узнает. Меня ещё вот что интересует, можно ли в этом коде задать повышение приоритета процесса? Изменено 5 Декабря 2014 пользователем Solomon753 Поделиться этим сообщением Ссылка на сообщение
Solomon753 2 Опубликовано 5 Декабря 2014 (изменено) @Solomon753, Ты видимо не понимаешь как работает цикл while. Да именно так я и понимаю происходящее, может изъяснился запутанно, только 5 день в язык вникаю. И по логике тоже сразу считал что if not IsMouseButtonPressed(1) then проверяет состояние кнопки на каждом шаге цикла, но вот именно что с API мыши это не работает, состояние кнопки становится известно только после последнего шага и принимается решение повторить ли цикл. Но при этом если прописывать "if not IsMouseButtonPressed(1) then break end" после каждого шага цикла, то драйвер прекрасно успевает понять в каком состоянии кнопка и принять решение делать ли следующий шаг. И так и так должно работать, но работает почему-то только во втором случае, видимо у лоджитека так реализована работа драйвера, что не все операторы работают как должны. У меня в реальном коде шагов "MoveMouseRelative(x, y)" будет 30(в абойме 30 патронов), точнее 30-1, отклонения начинаются после первого выстрела, и на каждом шаге x,y разные, поэтому придётся прописывать после каждого шага проверку состояния кнопки, если API упорно отказывается понимать другие способы. Возможно лоджитек намеренно ограничила возможности оператора, может быть при очень быстрых нажатиях будет надёжнее проверять состояние кнопки по отдельной команде на каждом шаге цикла. Изменено 5 Декабря 2014 пользователем Solomon753 Поделиться этим сообщением Ссылка на сообщение
Solomon753 2 Опубликовано 26 Декабря 2014 (изменено) Подскажите пожалуйста в Lua есть возможность определения цвета пикселя по заданным координатам? То есть мне нужно чтобы условие выполнялось только в том случе, если определённые места на экране имеют определённый цвет. Скачал книгу Programming in Lua, Third Edition by Roberto Ierusalimschy, но там про это ничего нет, только как цвета на эране менять, хотя по логике вещей, если на этом языке игры пишут, то должно быть что-то подобное. И ещё вопрос про coroutines, это полностью параллельное вычисление происходящее в реальном времени с основным кодом? И если это так, то когда корутинов несколько они могут все одновременно выполняются или один уступает ресурсы процессора дугому? Изменено 26 Декабря 2014 пользователем Solomon753 Поделиться этим сообщением Ссылка на сообщение
Solomon753 2 Опубликовано 27 Декабря 2014 (изменено) Жаль что нет параллельных потоков, при работе с мышью есть проблемы, если слишком часто опрашивать состояние кнопки, а именно каждые 100мс, то на 7-8 опросе состояние не всегда определяется правильно, а дальше так вообще перестаёт, тоже самое и с операцией MoveMouseRelative, чем дальше, тем чаще несрабатывание и полный отказ. Думал с помощью опроса состояния в параллельном потоке это попробовать решить, если это не проблемы контроллера мыши конечно. Видимо тут ничего не поделаешь, не продумал грамотно производитель мыши реализацию Lua в их устройствах. Про os.execute почитал, интересный оператор, но если через него использовать стороннюю программу для определения цвета, то слишком большие задержки наверняка получатся, да и умеет ли он возвращать данные от программы в код Lua пока что не понял. Библиотек умеющих работать с пикселями тоже пока что не заметил, даже близких упомянаний про подобное нигде нет. Вообще добавление в язык подобного штатного оператора существенно усилило бы возможности взаимодействия со сторонними приложениями, особенно с полноэкранными играми. В любом случае спасибо за помощь. Я вот третье издание Роберто Иерузалимского на русском языке с трудом нашел, кто-то отсканировал страницы, качество конечно так себе, но читать можно. Там pdf файл был запаролен для редактирования, программкой снял пароль, может у кого будет желание улучшить качество, там бы контрастность увеличить, текст бледный, можно через фотошоп групповой обработкой файлов, только через акробат сперва страницы в jpeg файлы сконвертировать нужно, потом обратно в pdf запихнуть. Конечно перевести всё это в текстовый формат вряд ли у кого найдётся время и желание. Хорошая книжка, хотелось бы чтобы в хорошем качестве на русском была. На хостинг залил, думаю многим пригодится http://myfolder.ru/files/42637218 Изменено 27 Декабря 2014 пользователем Solomon753 1 Поделиться этим сообщением Ссылка на сообщение
Solomon753 2 Опубликовано 30 Декабря 2014 Здесь английская версия книги, можно скрипты копировать, проще будет. Programming in Lua, 3rd Edition Roberto Ierusalimschy http://myfolder.ru/files/42658339 1 Поделиться этим сообщением Ссылка на сообщение