Перейти к контенту

Язык Lua. Общие вопросы программирования


Malandrinus

Рекомендуемые сообщения

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

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 и введением переменной, как это применить здесь пока не разобрался, удивлён что нет простого решения для игровой мыши.

Изменено пользователем Solomon753

Поделиться этим сообщением


Ссылка на сообщение

 

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 цикл прерывается, а по принятию А выполняется тело. Если такое возможно подскажите как это более грамотно прописать в скрипте.

Изменено пользователем Solomon753

Поделиться этим сообщением


Ссылка на сообщение

 

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.

Изменено пользователем Solomon753

Поделиться этим сообщением


Ссылка на сообщение
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 разрешает это делать если кнопка не нажата.

Изменено пользователем Solomon753

Поделиться этим сообщением


Ссылка на сообщение

Выводи в лог на экран что-нибудь (вроде там функция была), проверь вообще идет ли выполнение кода внутри цикла.

dddee8b9ae182488a4af950a4ef31f95.png

 

Как видишь While не выполняется. Но что странно, консоль приняла код на загрузку в мышь, про ошибки молчит.

Изменено пользователем Dennis_Chikin

Поделиться этим сообщением


Ссылка на сообщение
Подскажи пожалуйста ссылку на API

 

http://www.scribd.com/doc/228594915/G-SeriesLuaAPI

 

 

Пробуй так.

 

Попробовал, мышь тянет вниз как бешеную, никакие нажатия не останавливают, до того как успел нажать alt-f4 консоль вместе с драйвером аварийно завершила работу. :)

Изменено пользователем Solomon753

Поделиться этим сообщением


Ссылка на сообщение

Сделал чтобы действие каждой операции выводилось на дебаггер, вот что получилось:

 

0f7e0fe730422986d5ac49d9158a3f51.png

 

 

fe780ec267edfacbc8abdd365056dd4d.png

 

 

 

Как видим на 4 операции циклу благополучно передаётся управление, а отжатие кнопки не определятся вообще.

Поделиться этим сообщением


Ссылка на сообщение
Скрипт, который ты тестировал (как мы уже выяснили) не годится. Попробуй мой вариант чуть выше. И поиграйся со временем задержки в Sleep(30) -- тут нужно подобрать оптимальное время задержки

При всех задержках тело цикла выполняется полностью, повторяется пока зажата кнопка, как если бы использовались операторы repeat и until not, эффект точно такой же. Ставил задержку даже 1000, драйвер точно бы успел перехватить отжатие.

 

 

Сюда бы Break как-то запихнуть, он в цикле While должен делать полное прерывание тела. В скриптах в инете много вижу такое сочетание как пример прерывания. Только там другие задачи решаются. Надо бы что-то вроде:

if not IsMouseButtonPressed(1) then break
end

только и здесь тело не прерывается, хотя по логике обязано.

Эврика!!! Получилось... :beach:

Вот решение :) :

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 уже не работает. Теперь хотелось бы найти более грамотное решение задачи, как одной строкой объяснить циклу что после каждой итерации нужно проверять состояние кнопки. Но конечно предпочтительнее параллельное отслеживание состояния как в предыдущих скриптах, видимо дело именно в отсутствии задежки в них, надо будет поэкспериментировать.

Изменено пользователем Solomon753

Поделиться этим сообщением


Ссылка на сообщение
Solomon753 сказал(а) тело цикла выполняется полностью, повторяется пока зажата кнопка А разве не это требовалось?

Мне прерывание выполнения именно тела нужно по отжатию, т.е остановка после любой итерации, без завершения выполнения тела.

 

 

 

while IsMouseButtonPressed(1) do как раз и проверяет на каждом новом круге "нажата ли кнопка?" Ну если хочется с break-ом, то можно переписать так :

А тут вот именно что "на каждом новом круге", т.е всё тело выполняется полностью в любом случае, не рубится по событию, я этот код давно пробовал, он работает так же как цикл  "repeat - until not", об этом выше упоминал уже. В таком варианте не происходит проверки после каждой итерации состояния кнопки, пока всё тело не выполнится.

 

Кстати сегодня задержку между "if (event == "MOUSE_BUTTON_PRESSED" and arg == 1) then" и "while IsMouseButtonPressed(1) do" пришлось до 15 увеличить, видимо от загрузки процессора и приоритетности зависит как быстро драйвер о состоянии кнопки узнает.

 

Меня ещё вот что интересует, можно ли в этом коде задать повышение приоритета процесса?

Изменено пользователем Solomon753

Поделиться этим сообщением


Ссылка на сообщение

@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 упорно отказывается понимать другие способы. Возможно лоджитек намеренно ограничила возможности оператора, может быть при очень быстрых нажатиях будет надёжнее проверять состояние кнопки по отдельной команде на каждом шаге цикла.

Изменено пользователем Solomon753

Поделиться этим сообщением


Ссылка на сообщение

Подскажите пожалуйста в Lua есть возможность определения цвета пикселя по заданным координатам? То есть мне нужно чтобы условие выполнялось только в том случе, если определённые места на экране имеют определённый цвет. Скачал книгу Programming in Lua, Third Edition by Roberto Ierusalimschy, но там про это ничего нет, только как цвета на эране менять,  хотя по логике вещей, если на этом языке игры пишут, то должно быть что-то подобное.

И ещё вопрос про coroutines, это полностью параллельное вычисление происходящее в реальном времени с основным кодом? И если это так, то когда корутинов несколько они могут все одновременно выполняются или один уступает ресурсы процессора дугому?

Изменено пользователем Solomon753

Поделиться этим сообщением


Ссылка на сообщение

Жаль что нет параллельных потоков, при работе с мышью есть проблемы, если слишком часто опрашивать состояние кнопки, а именно каждые 100мс, то на 7-8 опросе состояние не всегда определяется правильно, а дальше так вообще перестаёт, тоже самое и с операцией MoveMouseRelative, чем дальше, тем чаще несрабатывание и полный отказ. Думал с помощью опроса состояния в параллельном потоке это попробовать решить, если это не проблемы контроллера мыши конечно. Видимо тут ничего не поделаешь, не продумал грамотно производитель мыши реализацию Lua в их устройствах.

 

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

 

Я вот третье издание Роберто Иерузалимского на русском языке с трудом нашел, кто-то отсканировал страницы, качество конечно так себе, но читать можно. Там pdf файл был запаролен для редактирования, программкой снял пароль, может у кого будет желание улучшить качество, там бы контрастность увеличить, текст бледный, можно через фотошоп групповой обработкой файлов, только через акробат сперва страницы в jpeg файлы сконвертировать нужно, потом обратно в pdf запихнуть. Конечно перевести всё это в текстовый формат вряд ли у кого найдётся время и желание.  Хорошая книжка, хотелось бы чтобы в хорошем качестве на русском была.

На хостинг залил, думаю многим пригодится http://myfolder.ru/files/42637218

Изменено пользователем Solomon753
  • Полезно 1

Поделиться этим сообщением


Ссылка на сообщение
  • Недавно просматривали   0 пользователей

    • Ни один зарегистрированный пользователь не просматривает эту страницу.
×
×
  • Создать...