Вопросы по 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
 
Последнее редактирование:

trefa

Известный
Всефорумный модератор
2,097
1,231
Lua:
function search(param)
local id = tonumber(param)
    if id == nil then sampAddChatMessage("[xxx] {FFFFFF} Не ввели необходимые значения.{9d00bd} /search [id].", 0x4b58ebFF) else
        if mainIni.settings.search == 1 then
            sampSendChat("Встаньте лицом к стене, руки за голову.")
        lua_thread.create(function() wait(1000)
            sampSendChat("/n /anim 33")
            sampSendChat("/me достал резиновые перчатки.")
            wait(1000)
            sampSendChat(" /me одел резиновые перчатки.")
            wait(1000)
            sampSendChat("/me обыскал ноги.")
            wait(1000)
            sampSendChat("/anim 14")
            wait(1000)
            sampSendChat("/me обыскал тело.")
            wait(1000)
            sampSendChat("/anim 16")
            wait(1000)
            sampSendChat(" /search "..id)
            wait(1000)
            ten_menu.v = not ten_menu.v
        end)
            else
            sampSendChat(" /search "..id)
            ten_menu.v = not ten_menu.v
        end
    end
end
Не выводит окно.
Пишу в func. main imgui.Process = ten_menu.v, выводит, но окно main_menu.v не выводит
Lua:
--- func. main

imgui.Process = main_menu.v
imgui.Process = ten_menu.v
Lua:
imgui.Process = main_menu.v or ten_menu.v
 
  • Нравится
Реакции: Даня1213221

Shell :3

Активный
159
32
@T1cK Вот, чет не пашет...
upload_2018-7-22_20-28-33.png
 

checkdasound

Известный
Проверенный
963
406
Lua:
local sf = require "sampfuncs"
require "lib.moonloader"

local my_dialog = {
    {
        title = '{FF99CC}Должностные обязанности врача скорой помощи',
        onclick = function()
            sampSendChat("Здравствуйте уважаемые сотрудники. Минуточку внимания.")
            wait(3000)
            sampSendChat("Должностные обязанности врача скорой помощи:")
            wait(3000)
            sampSendChat("Получает необходимую информацию о заболевании, отравлении или травме от пациента.")
            wait(3000)
            sampSendChat("Оценивает остроту и тяжесть состояния больного или пострадавшего.")
            wait(3000)
            sampSendChat("Оказывает необходимую скорую медицинскую помощь в соответствии с отраслевыми нормами...")
            wait(3000)
            sampSendChat("правилами и стандартами для врачей по оказанию скорой медицинской помощи.")
            wait(3000)
            sampSendChat("Определяет необходимость применения специальных методов исследования.")
            wait(3000)
            sampSendChat("Обосновывает поставленный диагноз, план и тактику ведения больного, показания к госпитализации.")
            wait(3000)
            sampSendChat("Обеспечивает щадящую транспортировку с одновременным проведением интенсивной терапии.")
            wait(3000)
            sampSendChat("Спасибо за внимание!")
        end
    },
    {
        title = '{FF99CC}Лекция об уколах',
        onclick = function()
            sampSendChat("Здравствуйте уважаемые сотрудники. Сейчас я проведу вам лекцию об уколах.")
            wait(3000)
            sampSendChat("Обязательным условием при введении препаратов является соблюдение гигиены.")
            wait(3000)
            sampSendChat("Перед уколом следует тщательно вымыть руки.")
            wait(3000)
            sampSendChat("Необходимо подготовить препарат, стерильный шприц, лезвие, которым вскрываются ампулы..")
            wait(3000)
            sampSendChat("..а также вату и спиртовые салфетки.")
            wait(3000)
            sampSendChat("Если вы делаете укол другому человеку, лучше всего, чтобы он лежал.")
            wait(3000)
            sampSendChat("Игла вводится строго в крайнюю верхнюю четверть ягодичной мышцы.")
            wait(3000)
            sampSendChat("Инъекции, как правило, вводятся не единооразово, а рассчитаны на определенный курс.")
            wait(3000)
            sampSendChat("В области укола можно делать йодную сетку, которая..")
            wait(3000)
            sampSendChat(".. ускоряет процесс рассасывания препарата.")
            wait(3000)
            sampSendChat("Спасибо за внимание!")
        end
    }
}

function submenus_show(menu, caption, select_button, close_button, back_button)
    select_button, close_button, back_button = select_button or 'Select', close_button or 'Close', back_button or 'Back'
    prev_menus = {}
    function display(menu, id, caption)
        local string_list = {}
        for i, v in ipairs(menu) do
            table.insert(string_list, type(v.submenu) == 'table' and v.title .. '  >>' or v.title)
        end
        sampShowDialog(id, caption, table.concat(string_list, '\n'), select_button, (#prev_menus > 0) and back_button or close_button, sf.DIALOG_STYLE_LIST)
        repeat
            wait(0)
            local result, button, list = sampHasDialogRespond(id)
            if result then
                if button == 1 and list ~= -1 then
                    local item = menu[list + 1]
                    if type(item.submenu) == 'table' then -- submenu
                        table.insert(prev_menus, {menu = menu, caption = caption})
                        if type(item.onclick) == 'function' then
                            item.onclick(menu, list + 1, item.submenu)
                        end
                        return display(item.submenu, id + 1, item.submenu.title and item.submenu.title or item.title)
                    elseif type(item.onclick) == 'function' then
                        local result = item.onclick(menu, list + 1)
                        if not result then return result end
                        return display(menu, id, caption)
                    end
                else -- if button == 0
                    if #prev_menus > 0 then
                        local prev_menu = prev_menus[#prev_menus]
                        prev_menus[#prev_menus] = nil
                        return display(prev_menu.menu, id - 1, prev_menu.caption)
                    end
                    return false
                end
            end
        until result
    end
    return display(menu, 31337, caption or menu.title)
end

function main()
sampRegisterChatCommand("ddd", func)
wait(-1)
end

function func()
submenus_show(my_dialog, "меню")
end
Почему не работает? Когда использую через кнопку всё работает
Вот ошибка
ML] (error) money.lua: I:\GTA San Andreas\moonloader\money.lua:67: attempt to yield across C-call boundary
stack traceback:
[C]: in function 'wait'
I:\GTA San Andreas\moonloader\money.lua:67: in function 'submenus_show'
I:\GTA San Andreas\moonloader\money.lua:103: in function <I:\GTA San Andreas\moonloader\money.lua:102>
[ML] (error) money.lua: Script died due to error. (19B7CAB4)
потому что ты используешь wait. Создавай поток и в нем уже используй.
 

atiZZZ

Новичок
249
47
Lua:
local sf = require "sampfuncs"
require "lib.moonloader"

local my_dialog = {
    {
        title = '{FF99CC}Должностные обязанности врача скорой помощи',
        onclick = function()
            sampSendChat("Здравствуйте уважаемые сотрудники. Минуточку внимания.")
            wait(3000)
            sampSendChat("Должностные обязанности врача скорой помощи:")
            wait(3000)
            sampSendChat("Получает необходимую информацию о заболевании, отравлении или травме от пациента.")
            wait(3000)
            sampSendChat("Оценивает остроту и тяжесть состояния больного или пострадавшего.")
            wait(3000)
            sampSendChat("Оказывает необходимую скорую медицинскую помощь в соответствии с отраслевыми нормами...")
            wait(3000)
            sampSendChat("правилами и стандартами для врачей по оказанию скорой медицинской помощи.")
            wait(3000)
            sampSendChat("Определяет необходимость применения специальных методов исследования.")
            wait(3000)
            sampSendChat("Обосновывает поставленный диагноз, план и тактику ведения больного, показания к госпитализации.")
            wait(3000)
            sampSendChat("Обеспечивает щадящую транспортировку с одновременным проведением интенсивной терапии.")
            wait(3000)
            sampSendChat("Спасибо за внимание!")
        end
    },
    {
        title = '{FF99CC}Лекция об уколах',
        onclick = function()
            sampSendChat("Здравствуйте уважаемые сотрудники. Сейчас я проведу вам лекцию об уколах.")
            wait(3000)
            sampSendChat("Обязательным условием при введении препаратов является соблюдение гигиены.")
            wait(3000)
            sampSendChat("Перед уколом следует тщательно вымыть руки.")
            wait(3000)
            sampSendChat("Необходимо подготовить препарат, стерильный шприц, лезвие, которым вскрываются ампулы..")
            wait(3000)
            sampSendChat("..а также вату и спиртовые салфетки.")
            wait(3000)
            sampSendChat("Если вы делаете укол другому человеку, лучше всего, чтобы он лежал.")
            wait(3000)
            sampSendChat("Игла вводится строго в крайнюю верхнюю четверть ягодичной мышцы.")
            wait(3000)
            sampSendChat("Инъекции, как правило, вводятся не единооразово, а рассчитаны на определенный курс.")
            wait(3000)
            sampSendChat("В области укола можно делать йодную сетку, которая..")
            wait(3000)
            sampSendChat(".. ускоряет процесс рассасывания препарата.")
            wait(3000)
            sampSendChat("Спасибо за внимание!")
        end
    }
}

function submenus_show(menu, caption, select_button, close_button, back_button)
    select_button, close_button, back_button = select_button or 'Select', close_button or 'Close', back_button or 'Back'
    prev_menus = {}
    function display(menu, id, caption)
        local string_list = {}
        for i, v in ipairs(menu) do
            table.insert(string_list, type(v.submenu) == 'table' and v.title .. '  >>' or v.title)
        end
        sampShowDialog(id, caption, table.concat(string_list, '\n'), select_button, (#prev_menus > 0) and back_button or close_button, sf.DIALOG_STYLE_LIST)
        repeat
            wait(0)
            local result, button, list = sampHasDialogRespond(id)
            if result then
                if button == 1 and list ~= -1 then
                    local item = menu[list + 1]
                    if type(item.submenu) == 'table' then -- submenu
                        table.insert(prev_menus, {menu = menu, caption = caption})
                        if type(item.onclick) == 'function' then
                            item.onclick(menu, list + 1, item.submenu)
                        end
                        return display(item.submenu, id + 1, item.submenu.title and item.submenu.title or item.title)
                    elseif type(item.onclick) == 'function' then
                        local result = item.onclick(menu, list + 1)
                        if not result then return result end
                        return display(menu, id, caption)
                    end
                else -- if button == 0
                    if #prev_menus > 0 then
                        local prev_menu = prev_menus[#prev_menus]
                        prev_menus[#prev_menus] = nil
                        return display(prev_menu.menu, id - 1, prev_menu.caption)
                    end
                    return false
                end
            end
        until result
    end
    return display(menu, 31337, caption or menu.title)
end

function main()
sampRegisterChatCommand("ddd", func)
wait(-1)
end

function func()
submenus_show(my_dialog, "меню")
end
Почему не работает? Когда использую через кнопку всё работает
Вот ошибка
ML] (error) money.lua: I:\GTA San Andreas\moonloader\money.lua:67: attempt to yield across C-call boundary
stack traceback:
[C]: in function 'wait'
I:\GTA San Andreas\moonloader\money.lua:67: in function 'submenus_show'
I:\GTA San Andreas\moonloader\money.lua:103: in function <I:\GTA San Andreas\moonloader\money.lua:102>
[ML] (error) money.lua: Script died due to error. (19B7CAB4)
wait 0 вроде не ставят, -1 или 1
 

#JD

Известный
40
1
Крч, есть команда (пусть будет - /command [ну с парамтерами естесна], как сделать чтобы при простом вводе команда выскакивала подсказка
тип я просто ввожу /command (без параметров) и в чате мол "Подсказка: /command [кол-во]"
Хелп, заранее спасибко <3
 

#Northn

Police Helper «Reborn» — уже ШЕСТЬ лет!
Всефорумный модератор
2,634
2,482
Крч, есть команда (пусть будет - /command [ну с парамтерами естесна], как сделать чтобы при простом вводе команда выскакивала подсказка
тип я просто ввожу /command (без параметров) и в чате мол "Подсказка: /command [кол-во]"
Хелп, заранее спасибко <3
Lua:
if tostring(param) ~= nil then else sampAddChatMessage('nea', -1) end
 

Fuexie

Известный
108
30
Можно ли как-нибудь разделить значения переменных. Т.е. допустим в переменной значение - 'Kek,Lol,Arbidol', а потом их как-нибудь разделить? Надеюсь ясно выразился