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

Qsany

Потрачен
464
147
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
Lua:
script_name('editTimeWeather_imgur')
script_author('imring')
script_moonloader(025)
script_version_number(3.0)

imgui                            = require 'imgui'
bitex                            = require 'bitex'
encoding                        = require 'encoding'
inicfg                            = require 'inicfg'
encoding.default                    = 'CP1251'
u8                            = encoding.UTF8
edit_menu_time_weather                = imgui.ImBool(false)
script_enable                        = imgui.ImBool(false)
loaded_parameter                    = imgui.ImBool(false)
save_parameter                    = imgui.ImBool(false)
autoload_enable                    = imgui.ImBool(false)
loaded_parameter_autoload                = imgui.ImBool(false)
delete_parameter                    = imgui.ImBool(false)
slider_int_time                    = imgui.ImInt(-1)
slider_int_weather                    = imgui.ImInt(-1)
name_parameter                    = imgui.ImBuffer('NameParameter', 256)

function apply_custom_style()
    local style = imgui.GetStyle()
    local colors = style.Colors
    local clr = imgui.Col
    local ImVec4 = imgui.ImVec4
    colors[clr.Button] = ImVec4(0.8, 0.8, 0.8, 0.40)
    colors[clr.ButtonHovered] = ImVec4(0.8, 0.8, 0.8, 0.5)
    colors[clr.ButtonActive] = ImVec4(0.8, 0.8, 0.8, 0.75)
    colors[clr.SliderGrabActive] = ImVec4(0.8, 0.8, 0.8, 0.75)
end

apply_custom_style()

function imgui.OnDrawFrame()
    if edit_menu_time_weather.v then
        local x, y = getScreenResolution()
        local btn_size = imgui.ImVec2(-0.1, 0)
        imgui.SetNextWindowPos(imgui.ImVec2(x/2, y/2), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
        imgui.SetNextWindowSize(imgui.ImVec2(450, 225), imgui.Cond.FirstUseEver)
        imgui.Begin('Edit Time or Weather')
        if imgui.Checkbox('Script enable', script_enable) then script_enable.v = script_enable.v end
        if script_enable.v then
            local file = inicfg.load(nil, 'moonloader/editTimeWeather_config.ini')
            while not file do file = inicfg.load(nil, 'moonloader/editTimeWeather_config.ini') end
            autoload_enable.v = file.autoload.enable
            if slider_int_time.v == -1 then
                oldtime = readMemory(0xB70153, 1, 1)
                slider_int_time.v = readMemory(0xB70153, 1, 1)
            end
            imgui.SliderInt('Edit Time', slider_int_time, 0, 24)
            if slider_int_weather.v == -1 then
                slider_int_weather.v = readMemory(0xC81320, 1, 1)
                oldweather = readMemory(0xC81320, 1, 1)
            end
            imgui.SliderInt('Edit Weather', slider_int_weather, 0, 50)
            if imgui.Button('Select option', btn_size) then
                loaded_parameter.v = not loaded_parameter.v
            end
            if imgui.Button('Save option', btn_size) then
                save_parameter.v = not save_parameter.v
            end
            if imgui.Button('Delete option', btn_size) then
                delete_parameter.v = not delete_parameter.v
            end
            if imgui.Checkbox('Autoload', autoload_enable) then
                file.autoload.enable = autoload_enable.v
                inicfg.save(file, 'moonloader/editTimeWeather_config.ini')
            end
            if autoload_enable.v then
                if imgui.Button('Select option for autoload', btn_size) then
                    loaded_parameter_autoload.v = not loaded_parameter_autoload.v
                end
            end
        end
        imgui.End()
    end
    if loaded_parameter.v and script_enable.v then
        local x, y = getScreenResolution()
        local btn_size = imgui.ImVec2(-0.1, 0)
        imgui.SetNextWindowPos(imgui.ImVec2(x/2-350, y/2-100), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
        imgui.SetNextWindowSize(imgui.ImVec2(250, 80), imgui.Cond.FirstUseEver)
        imgui.Begin('Edit Time or Weather: Select option')
        local parameterFound = false
        file = inicfg.load(nil, 'moonloader/editTimeWeather_config.ini')
        while not file do file = inicfg.load(nil, 'moonloader/editTimeWeather_config.ini') end
        for i = 1, #file.name+1 do
            if file.name[i] then
                parameterFound = true
                if imgui.Button(file.name[i], btn_size) then
                    slider_int_weather.v = file.weather[i]
                    slider_int_time.v = file.time[i]
                    sampAddChatMessage('{524F91}EditTimeWeather{FFFFFF}: Parameter is loaded at name '..file.name[i]..'.', -1)
                    loaded_parameter.v = false
                end
            end
        end
        if not parameterFound then imgui.Text('Not found.') end
        imgui.End()
    end
    if save_parameter.v and script_enable.v then
        local x, y = getScreenResolution()
        local btn_size = imgui.ImVec2(-0.1, 0)
        imgui.SetNextWindowPos(imgui.ImVec2(x/2+350, y/2-100), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
        imgui.SetNextWindowSize(imgui.ImVec2(350, 80), imgui.Cond.FirstUseEver)
        imgui.Begin('Edit Time or Weather: Save option')
        imgui.InputText('Parameter name', name_parameter)
        if imgui.Button('Save', btn_size) then
            local namedublicate = false
            local file = inicfg.load(nil, 'moonloader/editTimeWeather_config.ini')
            while not file do file = inicfg.load(nil, 'moonloader/editTimeWeather_config.ini') end
            for i = 1, #file.name+1 do
                if file.name[i] == u8:decode(name_parameter.v) then namedublicate = true end
            end
            if not namedublicate then
                local index, boolindex = 0, false
                while not boolindex do
                    index = index + 1
                    send = true
                    if not file.name[index] then boolindex = true end
                end
                file.name[index] = u8:decode(name_parameter.v)
                file.weather[index] = tonumber(slider_int_weather.v)
                file.time[index] = tonumber(slider_int_time.v)
                inicfg.save(file, 'moonloader/editTimeWeather_config.ini')
                sampAddChatMessage('{524F91}EditTimeWeather{FFFFFF}: Parameter is saved at name '..u8:decode(name_parameter.v)..'.', -1)
                save_parameter.v = false
            end
        end
        imgui.End()
    end
    if loaded_parameter_autoload.v and script_enable.v then
        local x, y = getScreenResolution()
        local btn_size = imgui.ImVec2(-0.1, 0)
        imgui.SetNextWindowPos(imgui.ImVec2(x/2-350, y/2-100), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
        imgui.SetNextWindowSize(imgui.ImVec2(250, 80), imgui.Cond.FirstUseEver)
        imgui.Begin('Edit Time or Weather: Select option for autoload')
        local parameterFound = false
        file = inicfg.load(nil, 'moonloader/editTimeWeather_config.ini')
        while not file do file = inicfg.load(nil, 'moonloader/editTimeWeather_config.ini') end
        for i = 1, #file.name+1 do
            if file.name[i] then
                parameterFound = true
                if imgui.Button(file.name[i], btn_size) then
                    file.autoload.id = i
                    sampAddChatMessage('{524F91}EditTimeWeather{FFFFFF}: Parameter is loaded for autoload at name '..file.name[i]..'.', -1)
                    loaded_parameter_autoload.v = false
                    inicfg.save(file, 'moonloader/editTimeWeather_config.ini')
                end
            end
        end
        if not parameterFound then imgui.Text('Not found.') end
        imgui.End()
    end
    if delete_parameter.v then
        local x, y = getScreenResolution()
        local btn_size = imgui.ImVec2(-0.1, 0)
        imgui.SetNextWindowPos(imgui.ImVec2(x/2-350, y/2-100), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
        imgui.SetNextWindowSize(imgui.ImVec2(250, 80), imgui.Cond.FirstUseEver)
        imgui.Begin('Edit Time or Weather: Delete option')
        local parameterFound = false
        file = inicfg.load(nil, 'moonloader/editTimeWeather_config.ini')
        while not file do file = inicfg.load(nil, 'moonloader/editTimeWeather_config.ini') end
        for i = 1, #file.name+1 do
            if file.name[i] then
                parameterFound = true
                if imgui.Button(file.name[i], btn_size) then
                    file.weather[i] = nil
                    file.time[i] = nil
                    sampAddChatMessage('{524F91}EditTimeWeather{FFFFFF}: Parameter is removed at name '..file.name[i]..'.', -1)
                    file.name[i] = nil
                    delete_parameter.v = false
                    if file.autoload.id == i then
                        file.autoload.id = 0
                        file.autoload.enable = false
                        autoload_enable.v = false
                    end
                    inicfg.save(file, 'moonloader/editTimeWeather_config.ini')
                end
            end
        end
        if not parameterFound then imgui.Text('Not found.') end
        imgui.End()
    end
end

function main()
    while not isSampAvailable() do wait(0) end
    if not doesFileExist('moonloader/editTimeWeather_config.ini') then
        local f = io.open('moonloader/editTimeWeather_config.ini', 'a')
        f:write('[name]\n0=0\n[weather]\n0=0\n[time]\n0=0\n[autoload]\nenable=false\nid=0')
        f:flush()
        f:close()
    end
    local file = inicfg.load(nil, 'moonloader/editTimeWeather_config.ini')
    while not file do file = inicfg.load(nil, 'moonloader/editTimeWeather_config.ini') end
    if file.autoload.enable and file.autoload.id ~= 0 then
        slider_int_time.v = file.time[file.autoload.id]
        slider_int_weather.v = file.weather[file.autoload.id]
        script_enable.v = true
    end
    while true do wait(0)
        if script_enable.v then
            if slider_int_time.v ~= -1 then writeMemory(0xB70153, 1, tonumber(slider_int_time.v), 1) end
            if slider_int_weather.v ~= -1 then writeMemory(0xC81320, 1, tonumber(slider_int_weather.v), 1) end
        end
        if not script_enable.v and slider_int_time.v ~= -1 then writeMemory(0xB70153, 1, oldtime, 1) end
        if not script_enable.v and slider_int_weather.v ~= -1 then writeMemory(0xC81320, 1, oldweather, 1) end
        if not sampIsChatInputActive() and not sampIsDialogActive() and not sampIsScoreboardOpen() and not isSampfuncsConsoleActive() then
            if isKeyJustPressed(0x4B) then edit_menu_time_weather.v = not edit_menu_time_weather.v end
        end
        imgui.Process = edit_menu_time_weather.v
    end
end
В какой строчке у имринга написана кнопка K- как активация менюшки ? Xd
 

Hatiko

Известный
Проверенный
1,470
612
Есть ли способ выравнивать текст обычный в imGui? И ешё, не знаю как выразиться, нужно получить типо координат или привязку какую-то к окну ввода чата. Хочу сделать что-то подобное ChatHUD`а, в котором показывается ид, язык раскладки, капс лок и т.п.
 

applethecandy

Now it's PHP time
Проверенный
253
328
lua = load3dAudioStream("moonloader/resource/Police Scanner/radom_police_scanner_sound_2.mp3")
[ML] (script) SAMPFUNCS Integration: -1
lua = loadAudioStream("moonloader/resource/Police Scanner/radom_police_scanner_sound_2.mp3")
[ML] (script) SAMPFUNCS Integration: true 34

Внимание вопрос: Почему в первом случае не загрузилось, а во втором загрузилось? Если что, функции разные (мне нужна именно первая)
 

Bogach

Активный
558
27
Ребят, прошу помощи, дайте пример выполнения
цикл for проверяет содержимое файла на совпадение, а после, если такой ник найден, содержимое файла добавляется в таблицу, удаляется оттуда строчка с найденными ником и в текстовый файл перезаписывается содержимое таблицы.
Я раньше такое уже делал, но забыл как :wall::sorry:
 

trefa

Известный
Всефорумный модератор
2,097
1,231
Ребят, прошу помощи, дайте пример выполнения
цикл for проверяет содержимое файла на совпадение, а после, если такой ник найден, содержимое файла добавляется в таблицу, удаляется оттуда строчка с найденными ником и в текстовый файл перезаписывается содержимое таблицы.
Я раньше такое уже делал, но забыл как :wall::sorry:
Уже кто-то кидал готовый код для чекера на чс, поищи в этой теме
 

Bogach

Активный
558
27
Lua:
local result, button, _, input = sampHasDialogRespond(2031)
    if result then
         if button == 1 then
              local blNick = string.match(input,"(%a+_%a+)")
                if blNick ~= nil then
                     local bl = io.open("moonloader\\BlackList\\BlackList.txt","r")
                     local found = false
                     for line in bl:lines() do
                             if string.find(line,blNick) then
                                  found = true
                  break
                             end
                      end
                     io.close(bl)
                    if found then
                         local bl = io.open("moonloader\\BlackList\\BlackList.txt","r")
                         nickname = {}
                         repeat
                         local text = bl:read()
                         if string.find(text,blNick) then
                              table.insert(nickname, blNick)
                         end
                         until text == nil
                         io.close(bl)
                         local bl = io.open("moonloader\\BlackList\\BlackList.txt","w")
                         for key, val in ipairs(nickname) do
                               if val ~= nil then
                                    bl:write(val .. "\n")
                               end
                         end
                         io.close(bl)
                 end
             end
         end
    end
Lua:
[ML] (error) StoHelper // Diamond RP: D:\SAMP\moonloader\STO.lua:233: bad argument #1 to 'find' (string expected, got nil)
[ML] (error) StoHelper // Diamond RP: Script died due to error. (0872A45C)
Что не так?Файл не пуст.:(
 

f0Re3t

Poh production
Друг
876
808
при попытке узнать кватерионы объекта
Lua:
local qx, qy, qz, qw = getObjectQuaternion(obj)
мунлоадер выплевывает ошибку
Код:
[ML] (error) opcode '07C3' call caused an unhandled exception
[ML] (error) forbka objects.lua: cannot resume non-suspended coroutine
[ML] (error) forbka objects.lua: Script died due to error. (01A77414)
все это дело происходит в цикле
 

AnWu

Guardian of Order
Всефорумный модератор
4,690
5,202
при попытке узнать кватерионы объекта
Lua:
local qx, qy, qz, qw = getObjectQuaternion(obj)
мунлоадер выплевывает ошибку
Код:
[ML] (error) opcode '07C3' call caused an unhandled exception
[ML] (error) forbka objects.lua: cannot resume non-suspended coroutine
[ML] (error) forbka objects.lua: Script died due to error. (01A77414)
все это дело происходит в цикле
bool result = doesObjectExist(Object object)
Попробуй проверять существование объекта. Возможно проблема в получении хэндла объекта
 

_JeT_

Новичок
24
0
Есть ли функция в lua на проверку подключений игроков по нику? Грубо говоря, чтобы при подключении определённого ника на сервер об этом писалось в чат игроку.
 

AnWu

Guardian of Order
Всефорумный модератор
4,690
5,202
Есть ли функция в lua на проверку подключений игроков по нику? Грубо говоря, чтобы при подключении определённого ника на сервер об этом писалось в чат игроку.
Перехватывать onPlayerJoin(playerid, nick)
 

Bogach

Активный
558
27
Lua:
local result, button, _, input = sampHasDialogRespond(2031)
    if result then
         if button == 1 then
              local blNick = string.match(input,"(%a+_%a+)")
                if blNick ~= nil then
                     local bl = io.open("moonloader\\BlackList\\BlackList.txt","r")
                     local found = false
                     for line in bl:lines() do
                             if string.find(line,blNick) then
                                  found = true
                  break
                             end
                      end
                     io.close(bl)
                    if found then
                         local bl = io.open("moonloader\\BlackList\\BlackList.txt","r")
                         nickname = {}
                         repeat
                         local text = bl:read()
                         if string.find(text,blNick) then
                              table.insert(nickname, blNick)
                         end
                         until text == nil
                         io.close(bl)
                         local bl = io.open("moonloader\\BlackList\\BlackList.txt","w")
                         for key, val in ipairs(nickname) do
                               if val ~= nil then
                                    bl:write(val .. "\n")
                               end
                         end
                         io.close(bl)
                 end
             end
         end
    end
Lua:
[ML] (error) StoHelper // Diamond RP: D:\SAMP\moonloader\STO.lua:233: bad argument #1 to 'find' (string expected, got nil)
[ML] (error) StoHelper // Diamond RP: Script died due to error. (0872A45C)
Что не так?Файл не пуст.:(
Все ещё требуется помощь:(
 

FYP

Известный
Автор темы
Администратор
1,758
5,726
при попытке узнать кватерионы объекта
Lua:
local qx, qy, qz, qw = getObjectQuaternion(obj)
мунлоадер выплевывает ошибку
Код:
[ML] (error) opcode '07C3' call caused an unhandled exception
[ML] (error) forbka objects.lua: cannot resume non-suspended coroutine
[ML] (error) forbka objects.lua: Script died due to error. (01A77414)
все это дело происходит в цикле
тоже. похоже на баг опкода

Все ещё требуется помощь:(
if text and string.find(text,blNick) then
 

Bogach

Активный
558
27
тоже. похоже на баг опкода


if text and string.find(text,blNick) then
Суть в том, что мне нужно ник (который я укажу) удалить из списка,
т.е, это надо текст из файла записать в таблицу построчно и при совпадении удалить из таблицы нужный ник, а после оставшиеся данные из таблицы записать обратно в файл, я просто не знаю как это все реализовать, когда - то давно уже делал такое, но я уже забыл как
и при текущем коде, у меня из файла удаляется все, кроме ника который я указал :(

Хотя бы напишите пример, как можно текст из файла записать в таблицу построчно
в файле текст построчно, и в таблицу также
 
Последнее редактирование модератором: