Зачастую при разработке мода или в игре приходится выполнять различные действия - выдача инфопорций, спавн объектов, включение\отключение скриптового ПНВ, сброс рюкзака, съедание антирада, запуск скриптового меню и т.д. Можно назначать горячие кнопки своим скриптам в любой версии игры, при этом не используя главное меню, кейлоггер или правку движка. Во-первых, это кнопка, нажатие которой отображает на экране название активного квеста (по умолчанию - Tab). Пример можно посмотреть в моде OGSE 0692. В нем на кнопку подвешено съедание антирада и включение пулемета в БТР. Во-вторых, есть алгоритм, использующий другие кнопки. Рассмотрим его подробнее.
Идея довольно проста - использование консольной команды вида "bind_console demo_record 1 knumpad0". В данном примере при нажатии кнопки 0 на дополнительной клавиатуре будет выполнена команда "demo_record 1".
Таким образом для каждой кнопки можно задать выполнение своей консольной команды. Мы можем взять в качестве команды какую-нибудь неиспользуемую в сингле, например "mm_net_player_name", а в качестве параметра передавать идентификатор нажатой кнопки. Теперь, если на апдейте ловить значение параметра консольной команды, то будем знать, какая кнопка нажата, и выполнять соответствующую ей функцию.
Работает эта схема на любой версии игры, однако нельзя использовать уже забинденные клавиши, т.к. они будут перебиндены на другое действие. Следует помнить, что при открытом диалоговом окне оно перехватывает обработку клавиш и нажатия не отлавливаются.
Вариант 1:
|
local con = nil -- переменная для объекта консоли local con_command = "mm_net_player_name" -- консольная команда local def_value = "_" -- значение по умолчанию - символ подчеркивания function update() if not con then -- инициализируем схему con = get_console() -- кешируем консоль con:execute( con_command .." ".. def_value ) -- инициализируем дефотлным значением, т.к. кнопка не нажата for k,v in pairs(_G[script_name()]) do -- перебираем функции в текущем файле -- v это функция и её имя является кодом клавиши if type(v)=='function' and DIK_keys[string.upper(k)] then local key = "k"..string.gsub(k,"dik_","") -- формируем ключ и con:execute("bind_console "..con_command.." "..k.." "..key) -- биндим кнопку на него end end else -- получаем из консоли значение параметра для нашей команды local str = con:get_string(con_command) -- если оно не является значением по умолчанию -- и в этом файле есть функция с таким именем, то выполняем её if str~=def_value and this[str] then this[str]() con:execute(con_command.." "..def_value) -- записываем значение по умолчанию end end end function dik_numpad0() news_manager.send_tip(db.actor,"нажали кнопку numpad0") end function dik_numpad1() news_manager.send_tip(db.actor,"нажали кнопку numpad1") end function dik_numpad2() news_manager.send_tip(db.actor,"нажали кнопку numpad2") end
|
При нажатии клавиш 0,1 или 2 цифровой клавиатуры будет выведено соответствующее каждой кнопке сообщение.
Отслеживать можно не только нажатие, но и отпускание кнопки. Cделать это можно аналогично случаю с кнопкой Tab.
На наше счастье на одно действие можно забиндить вторую кнопку командой "bind_sec". Вариант кода с отлавливанием отпускания выглядит так:
Вариант 2:
|
local con = nil local con_command = "mm_net_player_name" local def_value = "_" local act_key = "" -- последняя нажатая клавиша function update() if not con then con = get_console() con:execute(con_command .." " .. def_value) for k,v in pairs(_G[script_name()]) do if type(v)=='function' and DIK_keys[string.upper(k)] then local key = "k"..string.gsub(k,"dik_","") con:execute("bind_console "..con_command.." "..k.." "..key) end end else local str = con:get_string(con_command) if str~=def_value and this[str] then this[str]() con:execute(con_command .." " .. def_value) --отлова отпускания -- биндим на показ статика активного квеста нажатую кнопку con:execute("bind_sec scores k"..string.gsub(str,"dik_","")) -- если статик ещё не показан, то показываем его -- он будет висеть пока не отпущена клавиша local cs = get_hud():GetCustomStatic("main_task") or get_hud():AddCustomStatic("main_task") -- задаем 100% прозрачность тексту, чтоб не светился без нужды cs:wnd():SetTextColor(0,240,217,182) act_key = str -- запоминаем нажатую кнопку news_manager.send_tip(db.actor,"нажали "..act_key) end end -- отлов отпускания local cs = get_hud():GetCustomStatic("main_task") if act_key~="" and not cs then -- была нажата клавиша, а статика нет con:execute("unbind_sec scores") news_manager.send_tip(db.actor,"отпустили "..act_key) act_key="" end end function dik_numpad0() end function dik_numpad1() end function dik_numpad2() end
|
При нажатии клавиши 0 на дополнительной клавиатуре будет выведено сообщение "нажали 0", а при отпускании "отпустили 0".Функцию update вызываем из апдейта биндера актора. Имена функций берутся из класса-перечисления DIK_keys, описание которого можно найти в lua_help.script.
Автор Charsi. Навел на идею Shadows.