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

Dashok.

Участник
228
9
Как сделать что-бы скрипт нажимал по каждому пункту списка в луа?
GTA_SA_MP 06.04.2021 17_56_06.png
айди диалога 2390
 

Dmitriy Makarov

25.05.2021
Проверенный
2,481
1,113
Какой вариант не говнокод?
Lua:
-- 1
if imgui.Button("Кнопка №1", imgui.ImVec2(40, 40)) then
    print("Вы нажали на кнопку №1")
end
imgui.SameLine()
if imgui.Button("Кнопка №2", imgui.ImVec2(40, 40)) then
    print("Вы нажали на кнопку №2")
end
imgui.SameLine()
if imgui.Button("Кнопка №3", imgui.ImVec2(40, 40)) then
    print("Вы нажали на кнопку №3")
end

-- 2
for i = 1, 3 do
    if imgui.Button("Кнопка №"..i, imgui.ImVec2(40, 40)) then
        print("Вы нажали на кнопку №"..i)
    end
    imgui.SameLine()
end
 

Dashok.

Участник
228
9
Какой вариант не говнокод?
Lua:
-- 1
if imgui.Button("Кнопка №1", imgui.ImVec2(40, 40)) then
    print("Вы нажали на кнопку №1")
end
imgui.SameLine()
if imgui.Button("Кнопка №2", imgui.ImVec2(40, 40)) then
    print("Вы нажали на кнопку №2")
end
imgui.SameLine()
if imgui.Button("Кнопка №3", imgui.ImVec2(40, 40)) then
    print("Вы нажали на кнопку №3")
end

-- 2
for i = 1, 3 do
    if imgui.Button("Кнопка №"..i, imgui.ImVec2(40, 40)) then
        print("Вы нажали на кнопку №"..i)
    end
    imgui.SameLine()
end
2 варик
 

Adrian G.

Известный
Проверенный
521
454
Как сделать что-бы скрипт нажимал по каждому пункту списка в луа?
Посмотреть вложение 92240айди диалога 2390
Как-то так
Lua:
--это если диалог не закрывается после выбора пункта, в противном случае нужно каждый раз вызывать диалог снова
for i = 0, sampGetListboxItemsCount() do
sampSendDialogResponse(2390, 1, i, nil)
end
 

Nelit

Потрачен
252
38
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
У меня есть глобальная переменная balance = 300.300 сделал для того, что-бы затестить будет ли тратиться коины. У меня есть диалог, в нём выводится данный баланс. Реализовал снятия денег когда выбираешь пункт в диалоге, они снимаются, но бабки в диалоге продолжают показываться 300 даже после того, как все деньги уже кончились. миллион раз переоткрывал диалог, нихера. Вот код. Помогите

Lua:
script_name('Miner-Simulator')
script_author('Nelit')
script_properties('work-in-pause')
script_version('1.0 Beta')

require 'lib.moonloader'
require 'sampfuncs'

-- local inicfg = require 'inicfg'
-- local settings = 'Miner-Simualator'

local tag = '{666666}« {F9DF05}Miner{666666}-{F9DF05}Simulator {666666}» {FFFFFF}'
local author = unpack(thisScript().authors)
local version = thisScript().version
local main_color = '0xF9DF05'

----------------------------------------------
---------------For First Dialog---------------
----------------------------------------------

balance = 300

local titleMainDialog = '{FFFFFF}Главное меню {F9DF05}| {FFFFFF}Автор: {FF0000}'..author..' {F9DF05}| {FFFFFF}Версия: {FF0000}'..version..''
local firstButtonDialog = 'Выбрать'
local secondButtonDialog = 'Закрыть'

local mainMenuDialog = {
    'Магазин снаряжения',
    'Ваш баланс: {F9DF05}'..balance..' Коинов',
    'Рюкзак: {32CD32}(В РАЗРАБОТКЕ)',
    ' ',
    'Продажа руды',
    'Как играть?',
    '{FF0000}НАЧАТЬ ИГРУ СНАЧАЛА',
    ' ',
    'Идти домой {F9DF05}(ВЫ ТУТ)',
    '{32CD32}Идти в шахту'
}

local mainDialogText = ''

for _, str in ipairs(mainMenuDialog) do
    mainDialogText = mainDialogText .. str .. "\n"
end

---------------------------------------------------
---------------For HowPlaying Dialog---------------
---------------------------------------------------

local titleHowPlayingDialog = 'Как играть?'

local howPlayingText = [[
    {FFFFFF}Приветствуем тебя в игре {666666}« {F9DF05}Miner{666666}-{F9DF05}Simulator {666666}»{FFFFFF}

    Это простая убивалка времени. В ней тебе предстоит копать руду в {F9DF05}шахте, {FFFFFF}затем продавать её.
    За полученные {32CD32}деньги {FFFFFF}ты можешь покупать новое снаряжение, чинить свои кирки и так далее.

    Копать в {FF0000}шахте {FFFFFF}всё время тоже не выйдет, у тебя есть запас {F9DF05}энергии, {FFFFFF}по его окончанию ты не сможешь копать.
    Для его {32CD32}восстановления {FFFFFF}тебе придётся поспать у себя {F9DF05}дома.

    {FFFFFF}Надеюсь ты справишься, {F9DF05}удачи!
]]

---------------------------------------------
---------------For Shop Dialog---------------
---------------------------------------------

local titleShopDialog = '{FFFFFF}Магазин снаряжения {F9DF05}| {FFFFFF}Баланс: {F9DF05}'..balance..' Коинов'
local firstButtonShopDialog = 'Купить'
local secondButtonShopDialog = 'Закрыть'

local shopDialog = {
    'Деревянная кирка \t{32CD32}(Есть)',
    'Каменная кирка \t{F9DF05}(15 Коинов)',
    'Железная кирка \t{F9DF05}(25 Коинов)',
    'Золотая кирка \t{F9DF05}(39 Коинов)',
    'Титановая кирка \t{F9DF05}(47 Коинов)',
    'Алмазная кирка \t{F9DF05}(100 Коинов)'
}

local ShopDialogText = ''

for _, str in ipairs(shopDialog) do
    ShopDialogText = ShopDialogText .. str .. "\n"
end

-------------------------------------------
---------------Main Function---------------
-------------------------------------------

function main()
    if not isSampLoaded() or not isSampfuncsLoaded() then return end
    while not isSampAvailable() do wait(100) end

    -- wait(7000)

    sampAddChatMessage(tag .. 'Скрипт {32CD32}успешно {FFFFFF}загружен! Автор: {FF0000}' .. author, main_color)
    sampAddChatMessage(tag .. 'Главное меню скрипта {666666}- {F9DF05}/ms', main_color)
    sampAddChatMessage(tag .. 'Вы используете версию: {FF0000}' .. version, main_color)

    sampRegisterChatCommand('ms', cmd_ms)

    sampRegisterChatCommand('reload', function()
        thisScript():reload()
    end)

    while true do
        wait(0)

        -----------------------------------------
        ---------------Main Dialog---------------
        -----------------------------------------

        local result, button, list = sampHasDialogRespond(10000)
       
        if result then
            if button == 1 then
                if list == 0 then
                    sampShowDialog(10002, titleShopDialog, string.format(ShopDialogText), firstButtonShopDialog, secondButtonShopDialog, 4)
                elseif list == 1 then
                    sampAddChatMessage(tag .. 'Ваш баланс: {F9DF05}'..balance..' Коинов', main_color)
                    sampShowDialog(10000, titleMainDialog, string.format(mainDialogText), firstButtonDialog, secondButtonDialog, 2)
                elseif list == 2 then
                    sampAddChatMessage(tag .. 'В {32CD32}разработке!', main_color)
                    sampShowDialog(10000, titleMainDialog, string.format(mainDialogText), firstButtonDialog, secondButtonDialog, 2)
                elseif list == 4 then
                    sampAddChatMessage(tag .. 'Продажа руды', main_color)
                    sampShowDialog(10000, titleMainDialog, string.format(mainDialogText), firstButtonDialog, secondButtonDialog, 2)
                elseif list == 5 then
                    sampShowDialog(10001, titleHowPlayingDialog, string.format(howPlayingText), firstButtonDialog, secondButtonDialog, 0)
                elseif list == 6 then
                    sampAddChatMessage(tag .. 'Начать игру сначала', main_color)
                    sampShowDialog(10000, titleMainDialog, string.format(mainDialogText), firstButtonDialog, secondButtonDialog, 2)
                elseif list == 8 then
                    sampAddChatMessage(tag .. 'Вы уже тут!', main_color)
                    sampShowDialog(10000, titleMainDialog, string.format(mainDialogText), firstButtonDialog, secondButtonDialog, 2)
                elseif list == 9 then
                    sampAddChatMessage(tag .. 'Вы идёте в шахту.', main_color)
                    sampShowDialog(10000, titleMainDialog, string.format(mainDialogText), firstButtonDialog, secondButtonDialog, 2)
                end
            end
        end

        -----------------------------------------
        ---------------Shop Dialog---------------
        -----------------------------------------

        local result, button, list = sampHasDialogRespond(10002)
       
        if result then
            if button == 1 then
                if list == 0 then
                    sampAddChatMessage(tag .. 'У Вас уже {32CD32}есть {FFFFFF}этот предмет!', main_color)
                    sampShowDialog(10002, titleShopDialog, string.format(ShopDialogText), firstButtonShopDialog, secondButtonShopDialog, 4)
                elseif list == 1 then
                    if balance >= 15 then
                        balance = balance-15
                        sampAddChatMessage(tag .. 'Вы купили новый предмет - '.. shopDialog[2], main_color)
                        -- sampShowDialog(10002, titleShopDialog, string.format(ShopDialogText), firstButtonShopDialog, secondButtonShopDialog, 4)
                    else
                        sampAddChatMessage('У Вас недостаточно коинов!', main_color)
                    end
                elseif list == 2 then
                    sampAddChatMessage(tag .. 'В {32CD32}разработке!', main_color)
                    sampShowDialog(10000, titleMainDialog, string.format(mainDialogText), firstButtonDialog, secondButtonDialog, 2)
                elseif list == 4 then
                    sampAddChatMessage(tag .. 'Продажа руды', main_color)
                    sampShowDialog(10000, titleMainDialog, string.format(mainDialogText), firstButtonDialog, secondButtonDialog, 2)
                elseif list == 5 then
                    sampShowDialog(10001, titleHowPlayingDialog, string.format(howPlayingText), firstButtonDialog, secondButtonDialog, 0)
                end
            end
        end

    end
end

function cmd_ms()
    sampShowDialog(10000, titleMainDialog, string.format(mainDialogText), firstButtonDialog, secondButtonDialog, 2)
end
 
  • Нравится
Реакции: Gorskin

Vintik

Мечтатель
Проверенный
1,487
952
Какой вариант не говнокод?
Lua:
-- 1
if imgui.Button("Кнопка №1", imgui.ImVec2(40, 40)) then
    print("Вы нажали на кнопку №1")
end
imgui.SameLine()
if imgui.Button("Кнопка №2", imgui.ImVec2(40, 40)) then
    print("Вы нажали на кнопку №2")
end
imgui.SameLine()
if imgui.Button("Кнопка №3", imgui.ImVec2(40, 40)) then
    print("Вы нажали на кнопку №3")
end

-- 2
for i = 1, 3 do
    if imgui.Button("Кнопка №"..i, imgui.ImVec2(40, 40)) then
        print("Вы нажали на кнопку №"..i)
    end
    imgui.SameLine()
end
Очевидно, второй. Если текст кастомный, то лучше запихунть в массив:
Lua:
text = { 'Кнопка 1', 'Текст кнопки 2', 'Последняя кнопка' } -- сколько хочешь добавляешь
for i, str in ipairs(text) do
  if imgui.Button(str, imgui.ImVec2(40, 40)) then
    print('Вы нажали на кнопку №' .. i)
  end
  imgui.SameLine()
end
 
  • Нравится
Реакции: Dmitriy Makarov

Corrygan

Новичок
26
1
Как сделать чтобы текст из InputText сохранялся в ini? Пытался так: mainIni.flooder.proflood = text_buffer, но не работало
 

Nelit

Потрачен
252
38
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
Как сделать чтобы текст из InputText сохранялся в ini? Пытался так: mainIni.flooder.proflood = text_buffer, но не работало
Lua:
local config_ini = 'folder\\settings.ini'

function iniReset()
    inicfg.save({
        config = {
            proflood = ''
        }
    }, config_ini)
    print('[ Создание конфигурационных файлов... ]')
end

function iniLoad()
    print('[ Проверка конфигурационных файлов... ]')
    mainIni = inicfg.load(nil, config_ini)
    if mainIni == nil then
        iniReset()
    else
        print('[ Загрузка конфигурационных файлов... ]')
    end
end

function iniSave()
    inicfg.save({
        config = {
            text_buffer == mainIni.flooder.proflood
        }
    }, config_ini)
    print('[ Сохранение настроек... ]')
end

-- onDrawFrame
if button('Test') then
    iniSave()
    sampAddChatMessage('Настройки сохранены', -1)
end
 

kizn

О КУ)))
Всефорумный модератор
2,405
2,060
Lua:
local config_ini = 'folder\\settings.ini'

function iniReset()
    inicfg.save({
        config = {
            proflood = ''
        }
    }, config_ini)
    print('[ Создание конфигурационных файлов... ]')
end

function iniLoad()
    print('[ Проверка конфигурационных файлов... ]')
    mainIni = inicfg.load(nil, config_ini)
    if mainIni == nil then
        iniReset()
    else
        print('[ Загрузка конфигурационных файлов... ]')
    end
end

function iniSave()
    inicfg.save({
        config = {
            text_buffer == mainIni.flooder.proflood
        }
    }, config_ini)
    print('[ Сохранение настроек... ]')
end

-- onDrawFrame
if button('Test') then
    iniSave()
    sampAddChatMessage('Настройки сохранены', -1)
end
text_buffer.v (в mimgui: text_buffer[0])
 

ID_Heaven

Известный
810
284
подключил хотгеев с цфг, как белый человек, а оно выплёвывает это при нажатии
moonloader\lib\rkeys.lua:106: attempt to call field 'callback' (a nil value)
как фиксить? Что я не таак сделал?
 

morti.

Участник
63
3
Начал писать скрипты на луа, и по какой-то причине когда я пытаюсь вывести русский текст через sampAddChatMessage, в игре пишутся какие-то иероглифы, что делать, чтобы этого не было?
 

goshan

Новичок
22
1
Как можно реализовать систему активного курсора по команде? Сейчас нужно, тк текстдравы смотрю.
 

PanSeek

t.me/dailypanseek
Всефорумный модератор
899
1,746
Начал писать скрипты на луа, и по какой-то причине когда я пытаюсь вывести русский текст через sampAddChatMessage, в игре пишутся какие-то иероглифы, что делать, чтобы этого не было?
Перевести скрипт в кодировку Windows 1251 вместо UTF-8.
Если VS Code, то справа снизу есть надпись "UTF-8", нажимаете и сверху первую кнопку нажимаете, в поле поиска вводите "Windows 1251" и применяете. Если текста много, лучше скопируйте, чтоб потом вставить ибо после смены иероглифы появятся.
Если не VS Code, то примерно также думаю.
 

PanSeek

t.me/dailypanseek
Всефорумный модератор
899
1,746
Как можно реализовать систему активного курсора по команде? Сейчас нужно, тк текстдравы смотрю.
Появление курсора:
Lua:
local cursor = false

-- регистрация команды
sampRegisterChatCommand('cursor', function() cursor = not cursor end)

-- while true do
showCursor(cursor, false)
Весь код, именно курсор по команде:
Lua:
local cursor = false
function main()
    sampRegisterChatCommand('cursor', function() cursor = not cursor end)
    while true do
        wait(0)
        showCursor(cursor, false)
    end
end
 
  • Bug
  • Нравится
Реакции: Vintik и goshan

Corrygаn

Участник
225
6
Lua:
local config_ini = 'folder\\settings.ini'

function iniReset()
    inicfg.save({
        config = {
            proflood = ''
        }
    }, config_ini)
    print('[ Создание конфигурационных файлов... ]')
end

function iniLoad()
    print('[ Проверка конфигурационных файлов... ]')
    mainIni = inicfg.load(nil, config_ini)
    if mainIni == nil then
        iniReset()
    else
        print('[ Загрузка конфигурационных файлов... ]')
    end
end

function iniSave()
    inicfg.save({
        config = {
            text_buffer == mainIni.flooder.proflood
        }
    }, config_ini)
    print('[ Сохранение настроек... ]')
end

-- onDrawFrame
if button('Test') then
    iniSave()
    sampAddChatMessage('Настройки сохранены', -1)
end
Screenshot_48.png
Screenshot_47.png

Внёс минимальнейшие изменения, т.к у меня 3 строки для флуда, а не одна. Но оно что щас, что раньше не рпаботает