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

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

Участник
46
4
Всем общий, ребят помогите с ошибкой, пожалуйста)
После сохранение скрипта вылезает данная ошибка - 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,515
1,142
Всем общий, ребят помогите с ошибкой, пожалуйста)
После сохранение скрипта вылезает данная ошибка - 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

Участник
46
4
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,515
1,142
теперь такая ошибка вылезла - 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

Участник
46
4
Точно.
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

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

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,721
1,805
Не выводится в чат значение из конфига. Что делать?

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 = "Значение твое"
 

Smeruxa

smeruxa.ru
Проверенный
1,430
789
Не выводится в чат значение из конфига. Что делать?

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
очень много мусора лишнего
Lua:
require "lib.moonloader"
local inicfg = require 'inicfg'

local HLcfg = inicfg.load({
    config = {
        name = ""  
    }
}, "test.ini")
inicfg.save(HLcfg, "test.ini")

function save()
    inicfg.save(HLcfg, "test.ini")
end

function main()
    while not isSampAvailable() do wait(100) end
    sampRegisterChatCommand("getinfo", function()
        print(HLcfg.config.name)
    end)
    sampRegisterChatCommand("setinfo", function(arg)
        HLcfg.config.name = arg
        save()
        print("arg name have new value -> "..arg)
    end)
    wait(-1)
end
 
  • Нравится
Реакции: YarikVL

BaiYun

Участник
46
4
очень много мусора лишнего
Lua:
require "lib.moonloader"
local inicfg = require 'inicfg'

local HLcfg = inicfg.load({
    config = {
        name = "" 
    }
}, "test.ini")
inicfg.save(HLcfg, "test.ini")

function save()
    inicfg.save(HLcfg, "test.ini")
end

function main()
    while not isSampAvailable() do wait(100) end
    sampRegisterChatCommand("getinfo", function()
        print(HLcfg.config.name)
    end)
    sampRegisterChatCommand("setinfo", function(arg)
        HLcfg.config.name = arg
        save()
        print("arg name have new value -> "..arg)
    end)
    wait(-1)
end
Я знаю, я луа изучаю сижу поэтому и мусора много

Перенести это надо:
Посмотреть вложение 193921
И у тебя в конфиге ключ config есть?
Если не ошибаюсь, при открытии твоего файла ini должно быть так:
[config]
name = "Значение твое"
ini файл такой и есть у меня
 

YarikVL

Известный
Проверенный
4,721
1,805
Я знаю, я луа изучаю сижу поэтому и мусора много
Советую:

ini файл такой и есть у меня
У тебя скорее всего вообще не регистрируются такие команды, потому что бесконечный цикл запускается и не дает выполняться коду дальше ( если я не ошибаюсь то оно так работает )
И у тебя в конфиге ключ config есть?
Ключ это не название файла, а так сказать таблица, к которой твой lua файл обращается. Ну в роликах по ссылке выше - автор рассказывает про эти ключи.
при открытии твоего файла ini должно быть так:
[config] name = "Значение твое"
 

BaiYun

Участник
46
4
Советую:



У тебя скорее всего вообще не регистрируются такие команды, потому что бесконечный цикл запускается и не дает выполняться коду дальше ( если я не ошибаюсь то оно так работает )

Ключ это не название файла, а так сказать таблица, к которой твой lua файл обращается. Ну в роликах по ссылке выше - автор рассказывает про эти ключи.
1) По этим видосам я и учусь
2)Кмд реагается и все норм
3)
Screenshot_174.png
 

Strand

Участник
48
28
Есть проблема со скриптом. Пытаюсь прочитать файл, но игру крашит, либо она намертво зависает. Как решить проблему? Первый файл вести 3КБ, второй 79КБ
Lua:
require 'lib.moonloader'
local sampev = require 'samp.events'

local snailMaticDir = os.getenv('USERPROFILE') .. '\\Documents\\GTA San Andreas User Files\\SAMP\\SnailMatic\\'
local settingsSnailMatic, currentProfileName, profileJson

function main()

    if not isSampLoaded() or not isSampfuncsLoaded() then return end
    while not isSampAvailable() do wait(100) end
    
    sampRegisterChatCommand('updateprofile', function()
        updateProfileInfo()
    end)
    
    sampRegisterChatCommand('checkprofile', function()
        if profileJson == nil then sampAddChatMessage('You need to load profile first!',-1) return end
        for _, folder in pairs(profileJson) do
            for _, bind in pairs(folder.binds) do
                print(bind.name)
            end
        end
    end)
    
    function updateProfileInfo()

        sampAddChatMessage('Started checking settings!',-1)
        settingsSnailMatic = io.open(snailMaticDir..'snailmatic.json', 'r')
        currentProfileName = string.match(io.read(), '"profile":"([%w%s%pА-Яа-яЁё]+)"')
        io.close(settingsSnailMatic)
        
        sampAddChatMessage('Opening profile file!',-1)
        profileJson = io.open(snailMaticDir..'profiles\\'..currentProfileName..'.json', 'r')
        local buffer = json.decode(io.read())
        io.close(profileJson)
        
        profileJson = table.copy(buffer)
        
        sampAddChatMessage('Profile info updated!',-1)

    end
    
end