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

Dmitriy Makarov

25.05.2021
Проверенный
2,505
1,134
How do I make it so it types "/givelicense ID flying"?
and if you put the ID in there and press a button (with the script so it types on chat "/sx PlayerName (ID) at me)
Lua:
sampSendChat(string.format("/givelicense %s", ffi.string(buf))
-- /givelicense 123
sampSendChat(string.format("/sx %s %s", sampGetPlayerNickname(ffi.string(buf), ffi.string(buf))
-- /sx Nick_Name 123
 

Dmitriy Makarov

25.05.2021
Проверенный
2,505
1,134
sampSendChat(string.format("/sx L-a acceptat cineva pe %s (%s) ?", sampGetPlayerNickname(ffi.string(buf), ffi.string(buf))
Lua:
sampSendChat(string.format("/sx L-a acceptat cineva pe %s (%s) ?", sampGetPlayerNickname(ffi.string(buf)), ffi.string(buf)))

Another thing, if you can help me. I can't figure out what it can come from. In other mods, the commands work properly, they don't show the message "Eroare: Comanda neconuscuta." which means in english "Error: Unknown command" recognized by the server.
Here is a video so you can understand:
Your command is sent to the server, because of this the server tells you that this is an unknown command:
function sampev.onSendCommand(text) if text:lower() == '/recf'--[[text:lower():find('/blm') or text:lower():find('/george_floyd')]] then active[0] = not active[0] end end
Try this.
Lua:
-- in main()
sampRegisterChatCommand("recf", function()
    active[0] = not active[0]
end)
 
Последнее редактирование:

[SA ARZ]

Известный
392
8
189034

Пытаюсь вытащить по методу /members, но увы - мб кто знает как? и мне желательно в imgui все ники вывести.
 

chapo

чопа сребдс // @moujeek
Модератор
8,996
11,813
Lua:
sampSendChat(string.format("/sx L-a acceptat cineva pe %s (%s) ?", sampGetPlayerNickname(ffi.string(buf)), ffi.string(buf)))
1. можно же вместо string.format('text', var) писать сразу ('text'):format(var)
2. sampGetPlayerNickname вроде бы крашнется если передать в него строку
3. если игрока с идом нет в сети, но при этом ты юзнешь sampGetPlayerNickname, то скрипт вроде бы тоже крашнется
 
  • Нравится
Реакции: Dmitriy Makarov

Dmitriy Makarov

25.05.2021
Проверенный
2,505
1,134
1. можно же вместо string.format('text', var) писать сразу ('text'):format(var)
1. Да, можно и так. Мне просто первый вариант нравится слегка.
2. Не подумал об этом. Но, вроде как, у него всё:
Worked, all of them. Thanks
Надеюсь и остальное тоже.
3. И это тоже. Я ему как небольшой пример дал код. С доп. проверками, надеюсь, разберётся..


One more thing, how can I use this style configuration to edit the imGui colors? (in my code)
style config:
Lua:
-- in imgui.OnInitialize
apply_custom_style()
I think it's for ImGui. Look here (https://www.blast.hk/threads/25442/) for styles for mimgui.
function sampev.onSendCommand(text) sampRegisterChatCommand("sfsi", function() active[0] = not active[0] end) end
The command registration should be in main, not here. Delete it and move it:
Lua:
sampRegisterChatCommand("sfsi", function() active[0] = not active[0] end)
to main()
 
  • Влюблен
Реакции: sssilvian

Less_Go

Новичок
12
1
Хай. Можете помочь сделать скрипт, который будет отправлять команды после того, когда в чате найдет текст "объявление". У работает, если я сам пишу "объявление" в чат. А если просто в чате, ничего не происходит. Вот код

Код:
local sampev = require 'lib.samp.events'
local activation = false


function main()
    while not isSampAvailable() do wait(0) end
    sampRegisterChatCommand("adlvnews", cmd)
end
function sampev.onServerMessage(color, text)
    if activation then
        if text:find("Объявление") then
            lua_thread.create(function()
                sampSendChat("/flood 2")
                wait(1000)
                sampSendChat("/ad LVn - Свободная строка объявлений - 103.3 FM")
                wait(2000)
                sampSendChat("/flood /adsend 0")
            end)
        end
    end
end
function sampev.onShowDialog(id, style, title, button1, button2, text)
    if activation then
        if title:find("Подтверждение") then
            sampSendDialogResponse(id, 1, 0, _)
            return false
        end
    end
end
function cmd()
    if activation then
        activation = false
        printStringNow("AdLvNews - OFF", 3000)
    else
        activation = true
        printStringNow("AdLvNews - ON", 3000)
    end
end
 

BaiYun

Участник
43
3
Всем общий, ребят помогите с ошибкой, пожалуйста)
После сохранение скрипта вылезает данная ошибка - attempt to index upvalue 'imgui' (a function value)

Lua:
require "lib.moonloader"
local encoding = require "encoding"
local sampev = require 'lib.samp.events'
local imgui = require 'imgui'
encoding.default = 'CP1251'
u8 = encoding.UTF8
function main()
    if not isSampLoaded() or not isSampfuncsLoaded() then return end
    while not isSampAvailable() do wait(100) end
        while true do
            wait(0)

        sampRegisterChatCommand("imgui", imgui)
        imgui.Process = true
        function imgui(arg)
            main_window_state.v = not main_window_state.v
            imgui.Process = main_window_state.v
         end
         function imgui.OnDrawFrame()
             imgui.Begin("Start menu")
             imgui.text("123123")
             imgui.End()
         end   
    end
end
 

Dmitriy Makarov

25.05.2021
Проверенный
2,505
1,134
Всем общий, ребят помогите с ошибкой, пожалуйста)
После сохранение скрипта вылезает данная ошибка - attempt to index upvalue 'imgui' (a function value)

Lua:
require "lib.moonloader"
local encoding = require "encoding"
local sampev = require 'lib.samp.events'
local imgui = require 'imgui'
encoding.default = 'CP1251'
u8 = encoding.UTF8
function main()
    if not isSampLoaded() or not isSampfuncsLoaded() then return end
    while not isSampAvailable() do wait(100) end
        while true do
            wait(0)

        sampRegisterChatCommand("imgui", imgui)
        imgui.Process = true
        function imgui(arg)
            main_window_state.v = not main_window_state.v
            imgui.Process = main_window_state.v
         end
         function imgui.OnDrawFrame()
             imgui.Begin("Start menu")
             imgui.text("123123")
             imgui.End()
         end  
    end
end
Lua:
require "lib.moonloader"
local encoding = require "encoding"
local sampev = require 'lib.samp.events'
local imgui = require 'imgui'
encoding.default = 'CP1251'
u8 = encoding.UTF8

function main()
    while not isSampAvailable() do wait(100) end
    sampRegisterChatCommand("imgui", function()
        main_window_state.v = not main_window_state.v
    end)
    while true do wait(0)
        imgui.Process = main_window_state.v
    end
end

function imgui.OnDrawFrame()
    if main_window_state.v then
        imgui.Begin("Start menu")
        imgui.Text("123123")
        imgui.End()
    end
end

Хай. Можете помочь сделать скрипт, который будет отправлять команды после того, когда в чате найдет текст "объявление". У работает, если я сам пишу "объявление" в чат. А если просто в чате, ничего не происходит. Вот код

Код:
local sampev = require 'lib.samp.events'
local activation = false


function main()
    while not isSampAvailable() do wait(0) end
    sampRegisterChatCommand("adlvnews", cmd)
end
function sampev.onServerMessage(color, text)
    if activation then
        if text:find("Объявление") then
            lua_thread.create(function()
                sampSendChat("/flood 2")
                wait(1000)
                sampSendChat("/ad LVn - Свободная строка объявлений - 103.3 FM")
                wait(2000)
                sampSendChat("/flood /adsend 0")
            end)
        end
    end
end
function sampev.onShowDialog(id, style, title, button1, button2, text)
    if activation then
        if title:find("Подтверждение") then
            sampSendDialogResponse(id, 1, 0, _)
            return false
        end
    end
end
function cmd()
    if activation then
        activation = false
        printStringNow("AdLvNews - OFF", 3000)
    else
        activation = true
        printStringNow("AdLvNews - ON", 3000)
    end
end
Возможно, строка имеет цвет или же нужно увеличить количество слов для поиска. Скинь строку с нужным тебе текстом из чатлога.
И ещё, что за команда "/flood"? Она серверная или же в другом скрипте? Если в другом скрипте, то sampSendChat не будет её отправлять. Используй для таких целей sampProcessChatInput. Рядом со строками пример добавил.
Lua:
local sampev = require 'lib.samp.events'
local activation = false


function main()
    while not isSampAvailable() do wait(0) end
    sampRegisterChatCommand("adlvnews", function()
        activation = not activation
        printStringNow("AdLvNews - "..(activation and "ON" or "OFF"), 3000)
    end)
    wait(-1)
end

function sampev.onServerMessage(color, text)
    if activation then
        if text:find("Объявление") then
            lua_thread.create(function()
                sampSendChat("/flood 2") -- sampProcessChatInput("/flood 2")
                wait(1000)
                sampSendChat("/ad LVn - Свободная строка объявлений - 103.3 FM")
                wait(2000)
                sampSendChat("/flood /adsend 0") -- sampProcessChatInput("/flood /adsend 0")
            end)
        end
    end
end

function sampev.onShowDialog(id, style, title, button1, button2, text)
    if activation then
        if title:find("Подтверждение") then
            sampSendDialogResponse(id, 1, 0, nil)
            return false
        end
    end
end

I want to use this in my ImGui code, how do I do it?
This is C++ code. You need to first translate it into Lua and then add it to your script.
 
Последнее редактирование:
  • Нравится
Реакции: MLycoris

BaiYun

Участник
43
3
Lua:
require "lib.moonloader"
local encoding = require "encoding"
local sampev = require 'lib.samp.events'
local imgui = require 'imgui'
encoding.default = 'CP1251'
u8 = encoding.UTF8

function main()
    while not isSampAvailable() do wait(100) end
    sampRegisterChatCommand("imgui", function()
        main_window_state.v = not main_window_state.v
    end)
    while true do wait(0)
        imgui.Process = main_window_state.v
    end
end

function imgui.OnDrawFrame()
    if main_window_state.v then
        imgui.Begin("Start menu")
        imgui.Text("123123")
        imgui.End()
    end
end


Возможно, строка имеет цвет или же нужно увеличить количество слов для поиска. Скинь строку с нужным тебе текстом из чатлога.
И ещё, что за команда "/flood"? Она серверная или же в другом скрипте? Если в другом скрипте, то sampSendChat не будет её отправлять. Используй для таких целей sampProcessChatInput. Рядом со строками пример добавил.
Lua:
local sampev = require 'lib.samp.events'
local activation = false


function main()
    while not isSampAvailable() do wait(0) end
    sampRegisterChatCommand("adlvnews", function()
        activation = not activation
        printStringNow("AdLvNews - "..(activation and "ON" or "OFF"), 3000)
    end)
    wait(-1)
end

function sampev.onServerMessage(color, text)
    if activation then
        if text:find("Объявление") then
            lua_thread.create(function()
                sampSendChat("/flood 2") -- sampProcessChatInput("/flood 2")
                wait(1000)
                sampSendChat("/ad LVn - Свободная строка объявлений - 103.3 FM")
                wait(2000)
                sampSendChat("/flood /adsend 0") -- sampProcessChatInput("/flood /adsend 0")
            end)
        end
    end
end

function sampev.onShowDialog(id, style, title, button1, button2, text)
    if activation then
        if title:find("Подтверждение") then
            sampSendDialogResponse(id, 1, 0, nil)
            return false
        end
    end
end


This is C++ code. You need to first translate it into Lua and then add it to your script.
теперь такая ошибка вылезла - attempt to index global 'main_window_state' (a nil value)
 

Dmitriy Makarov

25.05.2021
Проверенный
2,505
1,134
теперь такая ошибка вылезла - attempt to index global 'main_window_state' (a nil value)
Точно.
Lua:
require "lib.moonloader"
local encoding = require "encoding"
local sampev = require 'lib.samp.events'
local imgui = require 'imgui'
encoding.default = 'CP1251'
u8 = encoding.UTF8

local main_window_state = imgui.ImBool(false)

function main()
    while not isSampAvailable() do wait(100) end
    sampRegisterChatCommand("imgui", function()
        main_window_state.v = not main_window_state.v
    end)
    while true do wait(0)
        imgui.Process = main_window_state.v
    end
end

function imgui.OnDrawFrame()
    if main_window_state.v then
        imgui.Begin("Start menu")
        imgui.Text("123123")
        imgui.End()
    end
end
 

Less_Go

Новичок
12
1
Lua:
require "lib.moonloader"
local encoding = require "encoding"
local sampev = require 'lib.samp.events'
local imgui = require 'imgui'
encoding.default = 'CP1251'
u8 = encoding.UTF8

function main()
    while not isSampAvailable() do wait(100) end
    sampRegisterChatCommand("imgui", function()
        main_window_state.v = not main_window_state.v
    end)
    while true do wait(0)
        imgui.Process = main_window_state.v
    end
end

function imgui.OnDrawFrame()
    if main_window_state.v then
        imgui.Begin("Start menu")
        imgui.Text("123123")
        imgui.End()
    end
end


Возможно, строка имеет цвет или же нужно увеличить количество слов для поиска. Скинь строку с нужным тебе текстом из чатлога.
И ещё, что за команда "/flood"? Она серверная или же в другом скрипте? Если в другом скрипте, то sampSendChat не будет её отправлять. Используй для таких целей sampProcessChatInput. Рядом со строками пример добавил.
Lua:
local sampev = require 'lib.samp.events'
local activation = false


function main()
    while not isSampAvailable() do wait(0) end
    sampRegisterChatCommand("adlvnews", function()
        activation = not activation
        printStringNow("AdLvNews - "..(activation and "ON" or "OFF"), 3000)
    end)
    wait(-1)
end

function sampev.onServerMessage(color, text)
    if activation then
        if text:find("Объявление") then
            lua_thread.create(function()
                sampSendChat("/flood 2") -- sampProcessChatInput("/flood 2")
                wait(1000)
                sampSendChat("/ad LVn - Свободная строка объявлений - 103.3 FM")
                wait(2000)
                sampSendChat("/flood /adsend 0") -- sampProcessChatInput("/flood /adsend 0")
            end)
        end
    end
end

function sampev.onShowDialog(id, style, title, button1, button2, text)
    if activation then
        if title:find("Подтверждение") then
            sampSendDialogResponse(id, 1, 0, nil)
            return false
        end
    end
end


This is C++ code. You need to first translate it into Lua and then add it to your script.
Спасибо. Решил проблему немного другим способом. А за sampProcessChatInput отдельное спасибо. Проебался немного
 

BaiYun

Участник
43
3
Точно.
Lua:
require "lib.moonloader"
local encoding = require "encoding"
local sampev = require 'lib.samp.events'
local imgui = require 'imgui'
encoding.default = 'CP1251'
u8 = encoding.UTF8

local main_window_state = imgui.ImBool(false)

function main()
    while not isSampAvailable() do wait(100) end
    sampRegisterChatCommand("imgui", function()
        main_window_state.v = not main_window_state.v
    end)
    while true do wait(0)
        imgui.Process = main_window_state.v
    end
end

function imgui.OnDrawFrame()
    if main_window_state.v then
        imgui.Begin("Start menu")
        imgui.Text("123123")
        imgui.End()
    end
end
Спасибо, я уже нашёл проблему в коде
 

BaiYun

Участник
43
3
Не выводится в чат значение из конфига. Что делать?

code:
require "lib.moonloader"
local encoding = require "encoding"
local sampev = require 'lib.samp.events'
local imgui = require 'imgui'
local main_window_state = imgui.ImBool(false)
local text_buffer = imgui.ImBuffer(256)
local inicfg = require 'inicfg'
local directini = "moonloader\\config.ini"
local mainini = inicfg.load(nil, directini)
local stateini = inicfg.save(mainini, directini)
encoding.default = 'CP1251'
u8 = encoding.UTF8

function main()
    while not isSampAvailable() do wait(100) end
    while true do wait(0)
    end
    sampRegisterChatCommand("getinfo", getinfo)
    sampRegisterChatCommand("setinfo", setinfo)
    _, id = sampGetPlayerIdByCharHandle(PLAYER_PED)
    nick = sampGetPlayerNickname(id)
end
function getinfo(arg)
    sampAddChatMessage(mainini.config.name, -1)
end

function setinfo(arg)
    -- body
end
 

YarikVL

Известный
Проверенный
4,746
1,813
Не выводится в чат значение из конфига. Что делать?

code:
require "lib.moonloader"
local encoding = require "encoding"
local sampev = require 'lib.samp.events'
local imgui = require 'imgui'
local main_window_state = imgui.ImBool(false)
local text_buffer = imgui.ImBuffer(256)
local inicfg = require 'inicfg'
local directini = "moonloader\\config.ini"
local mainini = inicfg.load(nil, directini)
local stateini = inicfg.save(mainini, directini)
encoding.default = 'CP1251'
u8 = encoding.UTF8

function main()
    while not isSampAvailable() do wait(100) end
    while true do wait(0)
    end
    sampRegisterChatCommand("getinfo", getinfo)
    sampRegisterChatCommand("setinfo", setinfo)
    _, id = sampGetPlayerIdByCharHandle(PLAYER_PED)
    nick = sampGetPlayerNickname(id)
end
function getinfo(arg)
    sampAddChatMessage(mainini.config.name, -1)
end

function setinfo(arg)
    -- body
end
Перенести это надо:
CB8B58E3-71F6-46E6-9ADE-1257024E4759.jpeg
И у тебя в конфиге ключ config есть?
Если не ошибаюсь, при открытии твоего файла ini должно быть так:
[config]
name = "Значение твое"