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

kyrtion

Известный
1,324
486
Поправим немного алгоритм:
1. при нахождении строчки "[Ошибка] Пока ты в больнице, ты не можешь использовать укроп"
2. скрипт автоматически сохранял ее в json файлик
Установим 2 либ: samp.lua и carbjsonconfig. а теперь дальше:
Lua:
-- Task-list:
-- 1. при нахождении строчки "[Ошибка] Пока ты в больнице, ты не можешь использовать укроп"
-- 2. скрипт автоматически сохранял ее в json файлик

local cjc = require('carbjsonconfig')
local sampev = require('samp.events')

-- Воспользуем либ carbJsonConfig ❤ для обработки в JSON
-- типо наша таблица со значениями
local json = {
    -- пустая таблица в chats по умолчанию при первой загрузки скрипта
    chats = {}
}

-- для подгрузки значений из файла
cjc.load(getWorkingDirectory()..'\\config\\test_your_script.json', json)
json() -- для сохранения в файл, также если конфиг изменилось - его нужно сохранить
-- json('reset') -- для сброса таблицы и файла конфига, но желательно не трогать
-- как будто уронишь всех данные в бд и потеряешь без восстановления

local regex = {
    dillInHospital = '^%[Ошибка%] Пока ты в больнице, ты не можешь использовать укроп$'
}

-- отдельная функция для обработки в onServerMessage
local function checkDillInHospital(color, text)
    text = text:gsub('{%x%x%x%x%x%x}', '') -- убираем цветной hex в виде: {FFFFFF}
    if text:find(regex.dillInHospital) then
        table.insert(json.chats, text) -- засунем строка в json.chats
        -- или: json.chats[#json.chats + 1] = text
        json() -- сохраняем
    end
end

-- событие на появление строка в чате
function sampev.onServerMessage(color, text)
    checkDillInHospital(color, text)
    -- вызывает функция. Вернется nil, то там неуказано return для возвращение значение
    -- но функция выполняется 100%
end
 

varkon

Известный
180
16
Поправим немного алгоритм:

Установим 2 либ: samp.lua и carbjsonconfig. а теперь дальше:
Lua:
-- Task-list:
-- 1. при нахождении строчки "[Ошибка] Пока ты в больнице, ты не можешь использовать укроп"
-- 2. скрипт автоматически сохранял ее в json файлик

local cjc = require('carbjsonconfig')
local sampev = require('samp.events')

-- Воспользуем либ carbJsonConfig ❤ для обработки в JSON
-- типо наша таблица со значениями
local json = {
    -- пустая таблица в chats по умолчанию при первой загрузки скрипта
    chats = {}
}

-- для подгрузки значений из файла
cjc.load(getWorkingDirectory()..'\\config\\test_your_script.json', json)
json() -- для сохранения в файл, также если конфиг изменилось - его нужно сохранить
-- json('reset') -- для сброса таблицы и файла конфига, но желательно не трогать
-- как будто уронишь всех данные в бд и потеряешь без восстановления

local regex = {
    dillInHospital = '^%[Ошибка%] Пока ты в больнице, ты не можешь использовать укроп$'
}

-- отдельная функция для обработки в onServerMessage
local function checkDillInHospital(color, text)
    text = text:gsub('{%x%x%x%x%x%x}', '') -- убираем цветной hex в виде: {FFFFFF}
    if text:find(regex.dillInHospital) then
        table.insert(json.chats, text) -- засунем строка в json.chats
        -- или: json.chats[#json.chats + 1] = text
        json() -- сохраняем
    end
end

-- событие на появление строка в чате
function sampev.onServerMessage(color, text)
    checkDillInHospital(color, text)
    -- вызывает функция. Вернется nil, то там неуказано return для возвращение значение
    -- но функция выполняется 100%
end
На 27ой строке просто %x+ разве нельзя?
Вместо повторения одно и того же
 

kyrtion

Известный
1,324
486
На 27ой строке просто %x+ разве нельзя?
Вместо повторения одно и того же
закрашивание в чате строго 6 hex в формате {...}. поэтому нужно как бы ограничить
если бы не было ограничение в hex, хоть 10, 12, 14, и тд. то я позволил бы
 

Орк

Известный
399
344
1734083476503.png

как отловить пустые сообщения от сервера? ни через hooks, ни через самп евентс не получается
 

chapo

tg/inst: @moujeek
Всефорумный модератор
9,202
12,520
Как адекватно подружить ImGuiListClipper и ImGuiTextFilter? Из-за того что фильтрация находится в клиппере элементы отображаются криво
Lua:
                             local clipper = imgui.ImGuiListClipper(5);
                            clipper:Begin(#Items.list / 5, 120);
                            while (clipper:Step()) do
                                for index = clipper.DisplayStart + 1, clipper.DisplayEnd do
                                    -- print('DisplayEnd', clipper.DisplayEnd)
                                    for row = 1, 5 do
                                        local itemIndex = (index - 1) * 5+row;;
                                        if (itemIndex < #Items.list) then
                                            local item = Items.list[itemIndex];
                                            if (item) then
                                                if (ui.searchFilter:PassFilter(('%s %d %d'):format(item.name, item.model or 0, item.UID or 0))) then
                                                    drawItem(item, itemIndex, alpha);
                                                end
                                            end
                                        end
                                    end
                                end
                            end
 

Орк

Известный
399
344
regex lua: ^%s*$
%s содержит как и \n, \t и прочее
там вроде даже пробела нет

Как адекватно подружить ImGuiListClipper и ImGuiTextFilter? Из-за того что фильтрация находится в клиппере элементы отображаются криво
клиппер это кривая хуйня, разве у тебя таблица на 1000 и больше элементов, чтобы его использовать? Зачем тебе этот клиппер
 

kyrtion

Известный
1,324
486
Проверю, но имел в виду в сообщении пробел даже не возвращает.
я указал в виде регулярное выражение %s*, определяет даже если нет пробела и может быть с пробелом, а также перенос строка, табуляция
включая начиная (^) и конец ($) что гарантирует правильной работе
 
  • Нравится
Реакции: Орк

chapo

tg/inst: @moujeek
Всефорумный модератор
9,202
12,520
Вряд ли кто-то подскажет, попробуй тут поискать https://github.com/search?q=repo:ocornut/imgui+ImGuiListClipper&type=issues
я уже забил хуй и написал свой "аналог". Но падение фпс около 30%
Lua:
local itemIndex = 1;
                            local filterPassedItemsCount = 0;
                            for _, item in ipairs(Items.list) do
                                local isFilterPassed = ui.searchFilter:PassFilter(('%s %d %d'):format(u8(Utils.toLowerCase(u8:decode(item.name))), item.modelId or 0, item.UID or 0));
                                local c = imgui.GetCursorScreenPos();
                                if (isFilterPassed) then
                                    filterPassedItemsCount = filterPassedItemsCount + 1
                                    if (imgui.IsRectVisibleVec2(c, c + imgui.ImVec2(120, 120))) then
                                        if (isFilterPassed) then
                                            drawItem(item, itemIndex, alpha);
                                        end
                                    else
                                        imgui.Dummy(imgui.ImVec2(120, 120));
                                    end
                                    if (itemIndex %5 == 0) then
                                        imgui.SetCursorPos(imgui.ImVec2(15, imgui.GetCursorPosY() + 5));
                                    else
                                        imgui.SameLine(nil, 15);
                                    end
                                    itemIndex = itemIndex + 1;
                                end
                            end

                            imgui.SetCursorPosY(imgui.GetCursorPosY() + 120 + 15);
                            imgui.PushFont(ui.font.bold[20]);
                            imgui.CenterText(filterPassedItemsCount == 0 and u8'Кажется, по вашему запросу ничего не найдено :(' or (ui.searchFilter:IsActive() and u8'Найдено предметов: ' .. filterPassedItemsCount or u8'Всего предметов: ' .. #Items.list));
                            imgui.PopFont();
 
  • Нравится
Реакции: Орк

KyRDa

Активный
116
70
Буду рад, если кто-то расскажет мне возможные причины появления этой ошибки:
error:
C++ exception
stack traceback:
stack traceback:
[C]: in function 'create'