Вопросы по Lua скриптингу

Общая тема для вопросов по разработке скриптов на языке программирования Lua, в частности под MoonLoader.
  • Задавая вопрос, убедитесь, что его нет в списке частых вопросов и что на него ещё не отвечали (воспользуйтесь поиском).
  • Поищите ответ в теме посвященной разработке Lua скриптов в MoonLoader
  • Отвечая, убедитесь, что ваш ответ корректен.
  • Старайтесь как можно точнее выразить мысль, а если проблема связана с кодом, то обязательно прикрепите его к сообщению, используя блок [code=lua]здесь мог бы быть ваш код[/code].
  • Если вопрос связан с MoonLoader-ом первым делом желательно поискать решение на wiki.

Частые вопросы

Как научиться писать скрипты? С чего начать?
Информация - Гайд - Всё о Lua скриптинге для MoonLoader(https://blast.hk/threads/22707/)
Как вывести текст на русском? Вместо русского текста у меня какие-то каракули.
Изменить кодировку файла скрипта на Windows-1251. В Atom: комбинация клавиш Ctrl+Shift+U, в Notepad++: меню Кодировки -> Кодировки -> Кириллица -> Windows-1251.
Как получить транспорт, в котором сидит игрок?
Lua:
local veh = storeCarCharIsInNoSave(PLAYER_PED)
Как получить свой id или id другого игрока?
Lua:
local _, id = sampGetPlayerIdByCharHandle(PLAYER_PED) -- получить свой ид
local _, id = sampGetPlayerIdByCharHandle(ped) -- получить ид другого игрока. ped - это хендл персонажа
Как проверить, что строка содержит какой-то текст?
Lua:
if string.find(str, 'текст', 1, true) then
-- строка str содержит "текст"
end
Как эмулировать нажатие игровой клавиши?
Lua:
local game_keys = require 'game.keys' -- где-нибудь в начале скрипта вне функции main

setGameKeyState(game_keys.player.FIREWEAPON, -1) -- будет сэмулировано нажатие клавиши атаки
Все иды клавиш находятся в файле moonloader/lib/game/keys.lua.
Подробнее о функции setGameKeyState здесь: lua - setgamekeystate | BlastHack — DEV_WIKI(https://www.blast.hk/wiki/lua:setgamekeystate)
Как получить id другого игрока, в которого целюсь я?
Lua:
local valid, ped = getCharPlayerIsTargeting(PLAYER_HANDLE) -- получить хендл персонажа, в которого целится игрок
if valid and doesCharExist(ped) then -- если цель есть и персонаж существует
  local result, id = sampGetPlayerIdByCharHandle(ped) -- получить samp-ид игрока по хендлу персонажа
  if result then -- проверить, прошло ли получение ида успешно
    -- здесь любые действия с полученным идом игрока
  end
end
Как зарегистрировать команду чата SAMP?
Lua:
-- До бесконечного цикла/задержки
sampRegisterChatCommand("mycommand", function (param)
     -- param будет содержать весь текст введенный после команды, чтобы разделить его на аргументы используйте string.match()
    sampAddChatMessage("MyCMD", -1)
end)
Крашит игру при вызове sampSendChat. Как это исправить?
Это происходит из-за бага в SAMPFUNCS, когда производится попытка отправки пакета определенными функциями изнутри события исходящих RPC и пакетов. Исправления для этого бага нет, но есть способ не провоцировать его. Вызов sampSendChat изнутри обработчика исходящих RPC/пакетов нужно обернуть в скриптовый поток с нулевой задержкой:
Lua:
function onSendRpc(id)
  -- крашит:
  -- sampSendChat('Send RPC: ' .. id)

  -- норм:
  lua_thread.create(function()
    wait(0)
    sampSendChat('Send RPC: ' .. id)
  end)
end
 
Последнее редактирование:

moreveal

Известный
969
702
Если ты имеешь ввиду нажатие клавиш когда открыт диалог или чат то можно добавить проверку if not sampIsCursorActive() then и никаких проблем не будет, но возможно я тебя не правильно понял на счёт этого
я знаю, но зачем юзать костыли, когда есть решение не хуже, плюс будет нажиматься в свернутом режиме
 
  • Нравится
Реакции: YarikVL

YarikVL

Известный
Проверенный
4,721
1,807
я знаю, но зачем юзать костыли, когда есть решение не хуже, плюс будет нажиматься в свернутом режиме
Да, но в твоей функе вроде не все клавиши клавиатуры есть, поэтому в таких случаях юзают setVirtualKeyDown и проверку на курсор
 

moreveal

Известный
969
702
Да, но в твоей функе вроде не все клавиши клавиатуры есть, поэтому в таких случаях юзают setVirtualKeyDown и проверку на курсор
а смысла во всех клавишах нет, сервер же их не видит) поэтому и необходимости в их нажатии не должно возникать; скорее в виде исключения может понадобиться, но эт точно не тот случай
 
  • Нравится
Реакции: YarikVL

sadik~

Известный
150
60
Используй setGameKeyState(key, state) - так клавиша будет отправляться GTA, а не ОС, что не повлечет за собой нажатие клавиш вне игры, а также возможный конфликт при вводе сообщений в чат, открытого диалога, консоли sampfuncs и т.д. и т.п.
Учитывай, что названия клавиш разные, в зависимости от того, где находится игрок - в транспорте, или пешком.

key можно посмотреть в moonloader/lib/game/keys.lua
Lua:
local keys_onfoot = {
    GOLEFT_GORIGHT = 0,
    GOFORWARD_GOBACK = 1,
    ANSWERPHONE_FIREWEAPONALT = 4,
    CYCLEWEAPONLEFT_SNIPERZOOMIN = 5,
    LOCKTARGET = 6,
    CYCLEWEAPONRIGHT_SNIPERZOOMOUT = 7,
    GROUPCONTROLFWD = 8,
    GROUPCONTROLBWD = 9,
    CONVERSATIONNO = 10,
    CONVERSATIONYES = 11,
    CHANGECAMERAVIEW = 13,
    JUMP = 14,
    ENTERVEHICLE = 15,
    SPRINT = 16,
    FIREWEAPON = 17,
    CROUCH = 18,
    LOOKBEHIND = 19,
    WALK = 21
}

local keys_incar = {
    GOLEFT_GORIGHT = 0,
    STEERUP_STEERDOWN = 1,
    TURRETLEFT_TURRETRIGHT = 2,
    TURRETUP_TURRETDOWN = 3,
    FIREWEAPONALT = 4,
    LOOKLEFT = 5,
    HANDBRAKE = 6,
    LOOKBEHIND_LOOKRIGHT = 7,
    RADIOSTATIONUP = 8,
    RADIOSTATIONDOWN = 9,
    CONVERSATIONNO = 10,
    CONVERSATIONYES = 11,
    CHANGECAMERAVIEW = 13,
    BRAKE = 14,
    EXITVEHICLE = 15,
    ACCELERATE = 16,
    FIREWEAPON = 17,
    HORN = 18,
    TOGGLESUBMISSION = 19
}

в state ставишь любое значение, не меньше -32768, и не больше 32767;
если в названии клавиши есть нижнее подчеркивание, значит у нее два действия
пример: GOLEFT_GORIGHT
при положительном значении state, игрок будет идти вправо; при отрицательном - влево

понять, что за кнопка тебе нужна, по ее названию в game/keys.lua можно на этом сайте (там написаны дефолтные значения для каждого из названий)


Пример использования:
if text:find("Y") then
    -- нажмет Y вне зависимости от положения (в авто/пешком), т.к. id у обоих случаев совпадают
    setGameKeyState(11, 128)
end
А как сделать чтобы не один раз нажимало?
Допустим выдало мне: Y N N N Y Y N Y N Y Y N N (Рандомно каждый раз выдаёт)
И чтобы они поочерёдно нажались.
DisplayGameText Y - ~w~PRESS: ~g~Y
DisplayGameText N ~w~PRESS: ~g~N
 

YarikVL

Известный
Проверенный
4,721
1,807
А как сделать чтобы не один раз нажимало?
Допустим выдало мне: Y N N N Y Y N Y N Y Y N N (Рандомно каждый раз выдаёт)
И чтобы они поочерёдно нажались.
DisplayGameText Y - ~w~PRESS: ~g~Y
DisplayGameText N ~w~PRESS: ~g~N
Этот хук будет срабатывать при появлении геймтекста, соответсвенно блок в хуке тоже будет срабатывать каждый раз
 

sadik~

Известный
150
60
Этот хук будет срабатывать при появлении геймтекста, соответсвенно блок в хуке тоже будет срабатывать каждый раз
А можно на setGameKeyState поставить задержку?
Показался мне DisplayGameText и только через 2 секунды нажмет на нужную кнопку?
 

linmsqn

Известный
331
10
как сделать определенное действие при виде 3д с определенным текстом?
 

YarikVL

Известный
Проверенный
4,721
1,807
  • Нравится
  • Влюблен
Реакции: linmsqn и qdIbp

Insanity

Известный
247
20
Lua:
function events.onDisplayGameText(style, text)
    if text:find('~w~PRESS:') then
        key = text:match('PRESS:%s+(.+)')
        if key:find('Y') then
            sampAddChatMessage("Y", -1)
        elseif key:find('N') then
            sampAddChatMessage("N", -1)
        end
    end
end


строчка с действием /me будет подаваться с каждым нахождением в чате сообщения "купил лицензию", даже если эту лицензию продал не ты. чтобы такого не было, нужно указывать строчку с твоим ником, либо делать дополнительные проверки
на аризоне работает система антифлуда, ты можешь отправить строку примерно раз в 400-500ms
А как это сделать ? Где почитать может?
 

sadik~

Известный
150
60
Lua:
local events = require 'lib.samp.events'

function main()
    wait(-1)
end

function events.onDisplayGameText(style, time, text)
    lua_thread.create(function()    
        if text:find('~w~PRESS:') then
            key = text:match('PRESS:%s+(.+)')
            if key:find('~g~Y') then
                setGameKeyState(11, 1)
                wait(500)
            elseif key:find('~g~N') then
                setGameKeyState(10, 2)
                wait(500)
            end
        end
    end)
end

Решил сделать бота который автоматически нажимает Y и N (Смотря что покажет). Но часто не нажимается почему-то (Текст показывает, скрипт видит его, но почему-то не нажимается). Думаю что сервер не успевает обработать из за большого пинга.
Вопрос: Как поставить задержку перед нажатием?

UPD: Задержку поставил, но все равно иногда просто не нажимается кнопка.
 
Последнее редактирование:

YarikVL

Известный
Проверенный
4,721
1,807
Вопрос: Как поставить задержку перед нажатием?
В начале хука создаёшь поток lua_thread.create(function() tvoy code end)
И потом ставишь в коде задержки: wait(и тут число в миллисекундах, сколько тебе надо ждать)
 

sadik~

Известный
150
60
Lua:
local events = require 'lib.samp.events'

function main()
    wait(-1)
end

function events.onDisplayGameText(style, time, text)
    lua_thread.create(function()   
        if text:find('~w~PRESS:') then
            key = text:match('PRESS:%s+(.+)')
            if key:find('~g~Y') then
                setGameKeyState(11, 1)
                wait(500)
            elseif key:find('~g~N') then
                setGameKeyState(10, 2)
                wait(500)
            end
        end
    end)
end

Решил сделать бота который автоматически нажимает Y и N (Смотря что покажет). Но часто не нажимается почему-то (Текст показывает, скрипт видит его, но почему-то не нажимается). Думаю что сервер не успевает обработать из за большого пинга.
Вопрос: Как поставить задержку перед нажатием?

UPD: Задержку поставил, но все равно иногда просто не нажимается кнопка.
Разобрался :3 Спасибо за помощь всем.

Lua:
function events.onServerMessage(color, text)
    if text:match("[Успешно]") then
        sampSetChatInputText("/go")
   end
end

Снова помощь нужна ) Если в чате выдает надпись [Успешно], то должно прописывать команду /go, но почему-то не прописывает. Если вместо sampSetChatInputText поставить print, то в консоли все хорошо, команду пишет.
Как сделать чтобы в игре прописывало команду?
 

YarikVL

Известный
Проверенный
4,721
1,807
Разобрался :3 Спасибо за помощь всем.

Lua:
function events.onServerMessage(color, text)
    if text:match("[Успешно]") then
        sampSetChatInputText("/go")
   end
end

Снова помощь нужна ) Если в чате выдает надпись [Успешно], то должно прописывать команду /go, но почему-то не прописывает. Если вместо sampSetChatInputText поставить print, то в консоли все хорошо, команду пишет.
Как сделать чтобы в игре прописывало команду?
Оно устанавливает чат-инпуту текст, чтобы отправить используй sampSendChat и для не серверных команд: sampProcessChatInput
 

linmsqn

Известный
331
10
как сделать чтобы в тг отправлялся скрин из сампа? мне нужно саму функцию вот этого скрина и отправки, не знаю как реализовать
 

IT clown

Участник
45
2
Как написать луа скрипт для ракбота с активацией по команде?
стандартное sampRegisterChatCommand("command", fun)
не работает