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

S.Walston

Новичок
22
1
Что не так? Просто до конца не шарю
Код:
    while true do
        wait(0)
            if activate == true then
                lua_thread.create(function()
                    sampSendChat("/sprunk")
                end)
            end
            wait(300000)
    end
end
        local result, button, list, input = sampHasDialogRespond(1999)
        if result then
            if button == 1 then
            if list == 0 then
                 sampSendChat("/aad Helpers | Хочешь быть хелпером?", -1)
                wait(1000)
                sampSendChat("/aad Helpers | Тогда скорее отпишись мне в репорт!")
                wait(1000)
                sampSendChat("/aad Helpers | Ожидаем всех!", -1)
                wait(1000)
                sampAddChatMessage("{FF0000}Удачного вам поиска =)",0x01FAD2)
            end
            if list == 1 then
                sampSendChat("/a Helpers | Происходит поиск ЗГСов Helpers", -1)
                wait(1000)
                sampSendChat("/a Helpers | Все подробности можете узнать в ВК у меня!")
                wait(1000)
                sampSendChat("/a Helpers | Все подробности ->Закрыто", -1)
                wait(1000)
                sampAddChatMessage("{FF0000}Удачни найти ЗГСов!",0x01FAD2)
            end
            if list == 2 then
                sampSendChat("/a Helpers | Уважаемые коллеги, хелперы, обращаюсь к вам", -1)
                wait(1000)
                sampSendChat("/a Helpers | Что бы повысить свой уровень хелперки, вам нужно ответь на репорты!")
                wait(1000)
                sampSendChat("/a Helpers | Чем больше отвечаете - тем больше ваш ЛВЛ!", -1)
                wait(1000)
                sampAddChatMessage("{FF0000}Эти бездельники предурпждены!!",0x01FAD2)
            end
        end
end
         if main_window_state.v == false then
           imgui.Process = false
         end
    end
end

Пишет:<eof>' expected near 'end'
и скрипт сразу умирает
 

MrBidloKoder

Известный
423
249
Что не так? Просто до конца не шарю
Код:
    while true do
        wait(0)
            if activate == true then
                lua_thread.create(function()
                    sampSendChat("/sprunk")
                end)
            end
            wait(300000)
    end
end
        local result, button, list, input = sampHasDialogRespond(1999)
        if result then
            if button == 1 then
            if list == 0 then
                 sampSendChat("/aad Helpers | Хочешь быть хелпером?", -1)
                wait(1000)
                sampSendChat("/aad Helpers | Тогда скорее отпишись мне в репорт!")
                wait(1000)
                sampSendChat("/aad Helpers | Ожидаем всех!", -1)
                wait(1000)
                sampAddChatMessage("{FF0000}Удачного вам поиска =)",0x01FAD2)
            end
            if list == 1 then
                sampSendChat("/a Helpers | Происходит поиск ЗГСов Helpers", -1)
                wait(1000)
                sampSendChat("/a Helpers | Все подробности можете узнать в ВК у меня!")
                wait(1000)
                sampSendChat("/a Helpers | Все подробности ->Закрыто", -1)
                wait(1000)
                sampAddChatMessage("{FF0000}Удачни найти ЗГСов!",0x01FAD2)
            end
            if list == 2 then
                sampSendChat("/a Helpers | Уважаемые коллеги, хелперы, обращаюсь к вам", -1)
                wait(1000)
                sampSendChat("/a Helpers | Что бы повысить свой уровень хелперки, вам нужно ответь на репорты!")
                wait(1000)
                sampSendChat("/a Helpers | Чем больше отвечаете - тем больше ваш ЛВЛ!", -1)
                wait(1000)
                sampAddChatMessage("{FF0000}Эти бездельники предурпждены!!",0x01FAD2)
            end
        end
end
         if main_window_state.v == false then
           imgui.Process = false
         end
    end
end

Пишет:<eof>' expected near 'end'
и скрипт сразу умирает
Либо ты не так скопировал, либо тут беда с табуляций. Можешь юзать elseif где есть несколько условий. Ты не открыл lua_thread.create где задержка (пример 16 строка).
Посмотреть вложение 67355
Как сделать такой чекпоинт? Чтобы был низкий.

Я смог сделать только так:
Посмотреть вложение 67354
подниму и перефразирую:
Как изменить высоту чекпоинта? (координаты z не помогают)
 

S.Walston

Новичок
22
1
Либо ты не так скопировал, либо тут беда с табуляций. Можешь юзать elseif где есть несколько условий. Ты не открыл lua_thread.create где задержка (пример 16 строка).
Извини, не шарю, что сделать именно нужно с elseif? Как открыть lua_thread.create?
 

CaJlaT

07.11.2024 14:55
Модератор
2,836
2,674
Извини, не шарю, что сделать именно нужно с elseif? Как открыть lua_thread.create?
Lua:
function main()
    while true do
        wait(0)
        --[[if activate == true then
            sampSendChat("/sprunk")
        end
        ]]--В таком случае лучше это делать не в основном цикле, а создавать поток с другим циклом при активации
        local result, button, list, input = sampHasDialogRespond(1999)
        if result then
            if button == 1 then
                if list == 0 then
                     sampSendChat("/aad Helpers | Хочешь быть хелпером?", -1)
                    wait(1000)
                    sampSendChat("/aad Helpers | Тогда скорее отпишись мне в репорт!")
                    wait(1000)
                    sampSendChat("/aad Helpers | Ожидаем всех!", -1)
                    wait(1000)
                    sampAddChatMessage("{FF0000}Удачного вам поиска =)",0x01FAD2)
                elseif list == 1 then
                    sampSendChat("/a Helpers | Происходит поиск ЗГСов Helpers", -1)
                    wait(1000)
                    sampSendChat("/a Helpers | Все подробности можете узнать в ВК у меня!")
                    wait(1000)
                    sampSendChat("/a Helpers | Все подробности ->Закрыто", -1)
                    wait(1000)
                    sampAddChatMessage("{FF0000}Удачни найти ЗГСов!",0x01FAD2)
                elseif list == 2 then
                    sampSendChat("/a Helpers | Уважаемые коллеги, хелперы, обращаюсь к вам", -1)
                    wait(1000)
                    sampSendChat("/a Helpers | Что бы повысить свой уровень хелперки, вам нужно ответь на репорты!")
                    wait(1000)
                    sampSendChat("/a Helpers | Чем больше отвечаете - тем больше ваш ЛВЛ!", -1)
                    wait(1000)
                    sampAddChatMessage("{FF0000}Эти бездельники предурпждены!!",0x01FAD2)
                end
            end
        end
        if not main_window_state.v then -- эти 3 строчки можно сократить в 1 строчку, ниже пример...
           imgui.Process = false
        end
        --imgui.Process = main_window_state.v
    end
end
 

S.Walston

Новичок
22
1
Lua:
function main()
    while true do
        wait(0)
        --[[if activate == true then
            sampSendChat("/sprunk")
        end
        ]]--В таком случае лучше это делать не в основном цикле, а создавать поток с другим циклом при активации
        local result, button, list, input = sampHasDialogRespond(1999)
        if result then
            if button == 1 then
                if list == 0 then
                     sampSendChat("/aad Helpers | Хочешь быть хелпером?", -1)
                    wait(1000)
                    sampSendChat("/aad Helpers | Тогда скорее отпишись мне в репорт!")
                    wait(1000)
                    sampSendChat("/aad Helpers | Ожидаем всех!", -1)
                    wait(1000)
                    sampAddChatMessage("{FF0000}Удачного вам поиска =)",0x01FAD2)
                elseif list == 1 then
                    sampSendChat("/a Helpers | Происходит поиск ЗГСов Helpers", -1)
                    wait(1000)
                    sampSendChat("/a Helpers | Все подробности можете узнать в ВК у меня!")
                    wait(1000)
                    sampSendChat("/a Helpers | Все подробности ->Закрыто", -1)
                    wait(1000)
                    sampAddChatMessage("{FF0000}Удачни найти ЗГСов!",0x01FAD2)
                elseif list == 2 then
                    sampSendChat("/a Helpers | Уважаемые коллеги, хелперы, обращаюсь к вам", -1)
                    wait(1000)
                    sampSendChat("/a Helpers | Что бы повысить свой уровень хелперки, вам нужно ответь на репорты!")
                    wait(1000)
                    sampSendChat("/a Helpers | Чем больше отвечаете - тем больше ваш ЛВЛ!", -1)
                    wait(1000)
                    sampAddChatMessage("{FF0000}Эти бездельники предурпждены!!",0x01FAD2)
                end
            end
        end
        if not main_window_state.v then -- эти 3 строчки можно сократить в 1 строчку, ниже пример...
           imgui.Process = false
        end
        --imgui.Process = main_window_state.v
    end
end
Благодарю, не подскажете ли, как сделать поток с другим циклом? и что бы флудило раз в минуту
 

MrBidloKoder

Известный
423
249
Благодарю, не подскажете ли, как сделать поток с другим циклом? и что бы флудило раз в минуту
Создаёшь функцию любую, открываешь поток, и просто делаешь цикл с помощью:
while true do
(тут пробел поставь) wait(10000) -- каждые 10 секунд
end
 

S.Walston

Новичок
22
1
Создаёшь функцию любую, открываешь поток, и просто делаешь цикл с помощью:
while true do
(тут пробел поставь) wait(10000) -- каждые 10 секунд
end
Это примерно так?
function flooder()
if not isSampLoaded() or not isSampfuncsLoaded() then return end
while not isSampAvailable() do wait(100) end
 

MrBidloKoder

Известный
423
249
Открываешь функцию, открываешь там цикл, пишешь код, закрываешь цикл, закрываешь функцию. Функцию нужно запустить в потоке. Щас с телефона и пример не смогу кинуть, но попытайся что-то сделать сам. Поток открываешь в main если что. Если тебе нужно будет закрыть цикл - юзай break.

Оставлю в виде списка что нужно погуглить:
1) Циклы.
2) lua_thread.create
 

S.Walston

Новичок
22
1
Открываешь функцию, открываешь там цикл, пишешь код, закрываешь цикл, закрываешь функцию. Функцию нужно запустить в потоке. Щас с телефона и пример не смогу кинуть, но попытайся что-то сделать сам. Поток открываешь в main если что. Если тебе нужно будет закрыть цикл - юзай break.

Оставлю в виде списка что нужно погуглить:
1) Циклы.
2) lua_thread.create
Почитал статьи, попытался сделать, не получается, можно как-то сделать? Не сейчас конечно, просто легче будет учиться, когда рассматривать примеры.
 

looney_

Участник
48
10
Почитал статьи, попытался сделать, не получается, можно как-то сделать? Не сейчас конечно, просто легче будет учиться, когда рассматривать примеры.
чё?
Lua:
function main()

repeat wait(0) until isSampLoaded()

-- repeat until - повторять какое либо действие, пока не случится until. В нашем же случае ожидание, пока не запустится самп

lua_thread.create(checkfunc) -- Создаешь поток на функцию, которая будет проверять и производить твои функции

end
Теперь у тебя будут работать две функции, если бы мы не создали поток, тогда бы скрипт просто не видел бы эту функцию, так же в функции, которую мы создали через поток, можно использовать wait()
Флудер ещё легче написать. Так же создаёшь поток в main, типа
Lua:
function main()
lua_thread.create(flooder)
end

function flooder()

while true do

wait(0)

-- while true do wait(0) обозначает что все функции ниже, будут повторяться постоянно

print('1')

end
-- всю работу скрипта, у тебя будет флудится в сампфункс лог "1"
 
Последнее редактирование:

enyag

Известный
345
12
как сделать сохранение значения переменной после перезахода в игру?
 

shizzard

Участник
150
7
Дополните или напишите, как менять команду прямо в игре, изначально пишет /ig , а в самом скрипте в инпуттекст при внесении новой команды чтобы оно заменяло /ig
Lua:
require "lib.moonloader"
local themes = import 'lib/imgui_themes.lua'
local tag = '{3498DB}[Игнорщик]: '
local color =  0x3498DB--0xFF69B4
local red_color = 0xff0040
ftext = function(text)
    sampAddChatMessage('[Игнорщик]: {ffffff}'..text,0x3498DB)
end
local encoding = require 'encoding'
encoding.default = 'CP1251'
u8 = encoding.UTF8
local sampev = require 'lib.samp.events'
local imgui = require 'imgui'
local buffer = imgui.ImBuffer(32)
local cbuffer = imgui.ImBuffer(32)
local mainmenu = imgui.ImBool(false)
local sw, sh = getScreenResolution()
local inicfg = require 'inicfg'
local directIni = "moonloader\\config\\ignore.ini"
local mainIni = inicfg.load({
    imessage = {
        itext = ' ',
        command = (cbuffer.v),
    }
})
function main()
    if not isSampfuncsLoaded() or not isSampLoaded() then return end
    while not isSampAvailable() do wait(100) end
        if not doesFileExist('ignore.ini') then inicfg.save(mainIni,'ignore.ini') end
        local _, myid = sampGetPlayerIdByCharHandle(PLAYER_PED)
        local nick = sampGetPlayerNickname(select(2, sampGetPlayerIdByCharHandle(1))):gsub('_', ' ')
        ftext('Добро пожаловать ' .. nick .. '!')
        ftext('Автор скрипта: Steven Eaton.')
        ftext('Активация : /ig' .. mainIni.imessage.itext)
        sampRegisterChatCommand('ig', mainmenuf)
        imgui.Process = False
        imgui.SwitchContext()
        themes.SwitchColorTheme()
    while true do
            imgui.Process = mainmenu.v
    wait(0)

    end
end
function mainmenuf(args)
    mainmenu.v = not mainmenu.v
    imgui.Process = mainmenu.v
end
function imgui.OnDrawFrame()
        imgui.SetNextWindowPos(imgui.ImVec2(sw / 2, sh / 2), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5)) imgui.SetNextWindowSize(imgui.ImVec2(725, 340), imgui.Cond.FirstUseEver)
        if mainmenu.v then
                imgui.Begin(u8"Игнорщик v24".. ' ' ..os.date("%d.%m.%Y"), mainmenu, imgui.WindowFlags.NoResize)
                imgui.PushItemWidth(150)
                imgui.InputText(u8'Вводите текст или часть текста которую хотите игнорировать',buffer)
                imgui.InputText(u8'Сменить команду активации', cbuffer)
            imgui.SameLine()
            if imgui.Button(u8'Сохранить команду') then
                mainIni.imessage.command = cbuffer.v
                inicfg.save(mainIni, directIni)
            end
            imgui.SameLine()
        if  not mainIni.imessage.command == '' or ' ' then
                imgui.Text(mainIni.imessage.command)
            else
                imgui.Text('/ig')
            end
--[[if mainIni.imessage.command == ' ' or '' then
    imgui.Text(u8'(Сейчас: /ig)')
elseif
    imgui.Text('Сейчас: /' .. u8(mainIni.imessage.command))
end]]
                imgui.End()
            end
end
как сделать сохранение значения переменной после перезахода в игру?
в cfg сохранять.