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

abnomegd

Активный
335
35
В диалоговом окне есть список, и там нужно что-то выбрать. я выбрал жму enter и должно появится другое точно такое же со списком диалоговое окно. или по краткому: как сделать диалоговое окно в диалоговом окне.
 

Pelmeska

Известный
931
232
В диалоговом окне есть список, и там нужно что-то выбрать. я выбрал жму enter и должно появится другое точно такое же со списком диалоговое окно. или по краткому: как сделать диалоговое окно в диалоговом окне.
тебе нужно чтоб диалог сервера закрывался и открывался фейковый диалог?
 

wulfandr

Известный
636
260
  • Нравится
Реакции: Biuti

chapo

чопа сребдс // @moujeek
Модератор
8,938
11,705
какой RPC отвечает за вход в режим редактирования объекта?
Через раклоггер не видно rpc
1630499115810.png
 

abnomegd

Активный
335
35
тебе нужно чтоб диалог сервера закрывался и открывался фейковый диалог?
нет. Смотри я написал скрипт (не полностью) вот нацеливаюсь на игрока нажимаю X открывается диалоговое окно(не серверное) На скрине можешь увидеть.
112888

И когда выбираю Показать документы и жму enter, нужно чтобы открылось точно такое же диалоговое окно (не серверное) с списком (чтобы я потом мог изменить названия каждой функции в списке).
Вот код
codedialogscript:
require "lib.moonloader" -- подключение библиотеки
local color_dialog = 0xDEB887

-- Для диалога с ID 12
local dialogArr = {"История ников", "Добавить в записную книгу", "Показать документы", "Действия", "Имущество"};
local dialogStr = ""

for _, str in ipairs(dialogArr) do
    dialogStr = dialogStr .. str .. "\n"
end

function main()
    if not isSampLoaded() or not isSampfuncsLoaded() then return end
    while not isSampAvailable() do wait(100) end
    sampRegisterChatCommand("dialog", cmd_dialog)
    while true do
        wait(0)
        -- Блок выполняющийся бесконечно (пока самп активен)
        local valid, ped = getCharPlayerIsTargeting(PLAYER_HANDLE)
        if valid and doesCharExist(ped) then
            local result, id = sampGetPlayerIdByCharHandle(ped)
            if result and isKeyJustPressed(VK_X) then
                playerid = id
                cmd_dialog(2)
            end
        end

        local result, button, list, input = sampHasDialogRespond(11) -- /dialog1 (InputBox)
        if result then -- если диалог открыт
            if button == 1 then -- если нажата первая кнопка (Выбрать)
    
            end
        end

        local result, button, list, input = sampHasDialogRespond(12) -- /dialog2 (ListBox)
        if result then -- если диалог открыт
            if button == 1 then -- если нажата первая кнопка (Выбрать)
                -- list - переменная содержащая порядковый ид нажатой в диалоге кнопки (listbox), счёт начинается с 0.
                if list == 0 then -- если нажато "История ников"
                    sampSendChat("/history "..sampGetPlayerNickname(tonumber(playerid)))
                elseif list == 1 then -- "Добавить в записную книгу"
                    sampSendChat("/add "..tostring(playerid))
                elseif list == 2 then -- "Показать документы"
                    sampShowDialog(20, "Показать документы", "Выбрать", "Закрыть", 3)
                elseif list == 3 then -- "Действия"
                elseif list == 4 then -- "Имущество"
                end
            end
        end
    end

local result, button, list, input = sampHasDialogRespond(20) -- /dialog3 (ListBox)

if result then -- если диалог открыт
    if button == 1 then -- если нажата первая кнопка (Выбрать)
        if list == 0 then
        elseif list == 1 then
        elseif list == 2 then
        elseif list == 3 then
        end
    else -- если нажата вторая кнопка (Закрыть)
    end
end
end


function cmd_dialog(arg)
    if tonumber(arg) == 1 then
        sampShowDialog(11, "Диалог с типом ID 1 (InputBox)", "Введите какую-либо строку", "Выбрать", "Закрыть", 1)
    elseif tonumber(arg) == 2 then
        sampShowDialog(12, "{00ff00}Меню взаимодействия с игроком", dialogStr, "Выбрать", "Закрыть", 2)
    elseif tonumber(arg) == 3 then
        sampShowDialog(20, "{00ff00}Показать документы", dialogTabStr, "Выбрать", "Закрыть", 3)
    end
end
 

chapo

чопа сребдс // @moujeek
Модератор
8,938
11,705
Пример использования
Lua:
local imgui = require('imgui')
local encoding = require 'encoding'
encoding.default = 'CP1251'
u8 = encoding.UTF8

local window = imgui.ImBool(false)

function main()
    while not isSampAvailable() do wait(200) end
    imgui.Process = false
    window.v = true  --show window
    while true do
        wait(0)
        imgui.Process = window.v
    end
end

function imgui.OnDrawFrame()
    if window.v then
        imgui.SetNextWindowPos(imgui.ImVec2(350.0, 250.0), imgui.Cond.FirstUseEver)
        imgui.SetNextWindowSize(imgui.ImVec2(280.0, 70.0), imgui.Cond.FirstUseEver)
        imgui.Begin('Window Title', window)

        imgui.TextQuestion('Не навелся на на знак вопроса')

        imgui.End()
    end
end

function imgui.TextQuestion(text)
    imgui.SameLine()
    imgui.TextDisabled('?')
    if imgui.IsItemHovered() then
        imgui.BeginTooltip()
        imgui.PushTextWrapPos(450)
        imgui.TextUnformatted(text)
        imgui.PopTextWrapPos()
        imgui.EndTooltip()
    end
end
 
  • Нравится
Реакции: #SameLine

Dmitriy Makarov

25.05.2021
Проверенный
2,505
1,134
нет. Смотри я написал скрипт (не полностью) вот нацеливаюсь на игрока нажимаю X открывается диалоговое окно(не серверное) На скрине можешь увидеть.
112888

И когда выбираю Показать документы и жму enter, нужно чтобы открылось точно такое же диалоговое окно (не серверное) с списком (чтобы я потом мог изменить названия каждой функции в списке).
Вот код
codedialogscript:
require "lib.moonloader" -- подключение библиотеки
local color_dialog = 0xDEB887

-- Для диалога с ID 12
local dialogArr = {"История ников", "Добавить в записную книгу", "Показать документы", "Действия", "Имущество"};
local dialogStr = ""

for _, str in ipairs(dialogArr) do
    dialogStr = dialogStr .. str .. "\n"
end

function main()
    if not isSampLoaded() or not isSampfuncsLoaded() then return end
    while not isSampAvailable() do wait(100) end
    sampRegisterChatCommand("dialog", cmd_dialog)
    while true do
        wait(0)
        -- Блок выполняющийся бесконечно (пока самп активен)
        local valid, ped = getCharPlayerIsTargeting(PLAYER_HANDLE)
        if valid and doesCharExist(ped) then
            local result, id = sampGetPlayerIdByCharHandle(ped)
            if result and isKeyJustPressed(VK_X) then
                playerid = id
                cmd_dialog(2)
            end
        end

        local result, button, list, input = sampHasDialogRespond(11) -- /dialog1 (InputBox)
        if result then -- если диалог открыт
            if button == 1 then -- если нажата первая кнопка (Выбрать)
   
            end
        end

        local result, button, list, input = sampHasDialogRespond(12) -- /dialog2 (ListBox)
        if result then -- если диалог открыт
            if button == 1 then -- если нажата первая кнопка (Выбрать)
                -- list - переменная содержащая порядковый ид нажатой в диалоге кнопки (listbox), счёт начинается с 0.
                if list == 0 then -- если нажато "История ников"
                    sampSendChat("/history "..sampGetPlayerNickname(tonumber(playerid)))
                elseif list == 1 then -- "Добавить в записную книгу"
                    sampSendChat("/add "..tostring(playerid))
                elseif list == 2 then -- "Показать документы"
                    sampShowDialog(20, "Показать документы", "Выбрать", "Закрыть", 3)
                elseif list == 3 then -- "Действия"
                elseif list == 4 then -- "Имущество"
                end
            end
        end
    end

local result, button, list, input = sampHasDialogRespond(20) -- /dialog3 (ListBox)

if result then -- если диалог открыт
    if button == 1 then -- если нажата первая кнопка (Выбрать)
        if list == 0 then
        elseif list == 1 then
        elseif list == 2 then
        elseif list == 3 then
        end
    else -- если нажата вторая кнопка (Закрыть)
    end
end
end


function cmd_dialog(arg)
    if tonumber(arg) == 1 then
        sampShowDialog(11, "Диалог с типом ID 1 (InputBox)", "Введите какую-либо строку", "Выбрать", "Закрыть", 1)
    elseif tonumber(arg) == 2 then
        sampShowDialog(12, "{00ff00}Меню взаимодействия с игроком", dialogStr, "Выбрать", "Закрыть", 2)
    elseif tonumber(arg) == 3 then
        sampShowDialog(20, "{00ff00}Показать документы", dialogTabStr, "Выбрать", "Закрыть", 3)
    end
end
Так вызови его просто, не? Я так понял, что это у тебя диалог с ID 12, просто сделай, чтобы при нажатии на строку "Показать документы", вызывалась функция cmd_dialog(2) с аргументом 2, которая показывает этот диалог.
 
  • Нравится
Реакции: abnomegd