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

chapo

🫡 В армии с 17.10.2023. В ЛС НЕ ОТВЕЧАЮ
Друг
8,776
11,236
Окей, как получить ширину и высоту текста?
Lua:
float height = renderGetFontDrawHeight(DxFont font)
float length = renderGetFontDrawTextLength(DxFont font, zstring text [, bool ignoreColorTags=false])

--например
local sizeX = renderGetFontDrawTextLength(твоя переменная с шрифтом, твой текст, false)
local sizeY = renderGetFontDrawHeight(твоя переменная с шрифтом)
 
  • Нравится
Реакции: qdIbp

Hund dev.

Участник
47
2
Lua:
float height = renderGetFontDrawHeight(DxFont font)
float length = renderGetFontDrawTextLength(DxFont font, zstring text [, bool ignoreColorTags=false])

--например
local sizeX = renderGetFontDrawTextLength(твоя переменная с шрифтом, твой текст, false)
local sizeY = renderGetFontDrawHeight(твоя переменная с шрифтом)
Спасибо

Lua:
float height = renderGetFontDrawHeight(DxFont font)
float length = renderGetFontDrawTextLength(DxFont font, zstring text [, bool ignoreColorTags=false])

--например
local sizeX = renderGetFontDrawTextLength(твоя переменная с шрифтом, твой текст, false)
local sizeY = renderGetFontDrawHeight(твоя переменная с шрифтом)
Произошел один ньюанс:
Lua:
local carLabel = string.format("%s[%d]\nHealth: %d\nX: %d | Y: %d | Z: %d\nDistance: %d", modelLabel, modelId, carHealth, carX, carY, carZ, distance)
Вроде бы все хорошо, но функция
Lua:
local carLabelWidth = renderGetFontDrawTextLength(smallFont, carLabel, false)
Получает длину строки с учетом (\n), а не делает каждую строку по центру.
Как можно реализовать центрирование, без прибегания к костылям по типу
Lua:
local carLabelWidth1 = renderGetFontDrawTextLength(smallFont, carLabel1, false)
local carLabelWidth2 = renderGetFontDrawTextLength(smallFont, carLabel2, false)
local carLabelWidth3 = renderGetFontDrawTextLength(smallFont, carLabel3, false)

if carLabelWidth1 > carLabelWidth2 then
...
end
?
 
Последнее редактирование:

l-m

Новичок
28
1
Буду очень благодарен в помощи. Прошу поставить ограничение на использование команды. Например при использовании трижды данной функции, на четвёртый раз устанавливается лимит сроком на 5 минут, по истечению этих 5 минут опять можно использовать трижды и снова ставится лимит на время(в чат будет сообщать что доступно будет по истечению время, ну с этим я думаю и сам справлюсь))))).
Так же не могу поставить антифлуд,(чтобы скрипт если начал работать то не видел последующих команд пока не закончит начатую).
1673646233203.png

Код:
function sampev.onServerMessage(color--[[Цвет]], text--[[Текст]]) -- Этот хук ловит сообщения в чате
    lua_thread.create(function() -- создаем поток -- позволяет использовать wait
        if text:find('[R].*: /driver') then -- если найден текст "test" то
            wait(100) -- отвечает за ожидание в размере секунды БЫЛО 1000 сек
            sampSendChat('/r Вызываю эвакуатор через 10 секунд')
            wait(5000)
            sampSendChat('/r (( /drive 5 sek ))')
            wait(4000)
            sampSendChat('/r Вызываю эвакуатор через 1 секунду, кто не успел тот опоздал')
            wait(1000)
            sampSendChat('/drive') -- если в чате засветится сообщение test, то хук поймает данное сообщение, дальше скрипт подождет 1 секунду и выведет "Не тест"
            wait(2000)
            sampCloseCurrentDialogWithButton(1) --закрывает окно с нажатием кнопки
        elseif text:find('[R].*: /cancel') then
            sampSendChat("/r (( drive disabled ))")
            wait(500)
            thisScript():reload()
        end
    end)-- закрываем поток
end

Прошу объяснить максимально подробно начинающему недоскриптеру)
Пробовал ставить через "while i <=3" и получался флуд трижды и функция останавливалась
 
Последнее редактирование:

Armando Guerra

Новичок
16
1
Код:
price = '100.000'
price = string.gsub(price,  '.',  '')

Удаляется вся строка, хотя хотелось бы удалить только точку, хелпаните пожалуйста
 

l-m

Новичок
28
1
Как показать в коде что функция начала работу после ввода команды активации?
 

l-m

Новичок
28
1
выводи sampAddChatMessage

Lua:
function xz--[[твоя функция]]()
    sampAddChatMessage('хуя заработало',-1)
-- you code
end
Ты не понял) Мне нужно сделать невидимой для скрипта команду, если он уже выполняет её, потому что если дважды он увидит команду, будет дважды флудить одним и тем же.
 
  • Эм
Реакции: qdIbp

qdIbp

Автор темы
Проверенный
1,392
1,151
Ты не понял) Мне нужно сделать невидимой для скрипта команду, если он уже выполняет её, потому что если дважды он увидит команду, будет дважды флудить одним и тем же.
?
Lua:
local wast = 0

function main()
    while not sampIsLocalPlayerSpawned() do wait(100) end
    sampRegisterChatCommand('off',function()
        wast = 0
    end)
    while true do wait(0)
        for i = 1, wast do
            sampSendChat('/c xz')
            wait(123)
        end
    end
end

require('lib.samp.events').onSendCommand = function(cmd)
    if string.match(cmd,'^/test') then
        if wast == 0 then
            sampAddChatMessage('Ухх пошла жара',-1)
        end
        wast = wast + 1
    end
end
 

chapo

🫡 В армии с 17.10.2023. В ЛС НЕ ОТВЕЧАЮ
Друг
8,776
11,236
Спасибо


Произошел один ньюанс:
Lua:
local carLabel = string.format("%s[%d]\nHealth: %d\nX: %d | Y: %d | Z: %d\nDistance: %d", modelLabel, modelId, carHealth, carX, carY, carZ, distance)
Вроде бы все хорошо, но функция
Lua:
local carLabelWidth = renderGetFontDrawTextLength(smallFont, carLabel, false)
Получает длину строки с учетом (\n), а не делает каждую строку по центру.
Как можно реализовать центрирование, без прибегания к костылям по типу
Lua:
local carLabelWidth1 = renderGetFontDrawTextLength(smallFont, carLabel1, false)
local carLabelWidth2 = renderGetFontDrawTextLength(smallFont, carLabel2, false)
local carLabelWidth3 = renderGetFontDrawTextLength(smallFont, carLabel3, false)

if carLabelWidth1 > carLabelWidth2 then
...
end
?
Lua:
        local veh = хендл машины
            if isCarOnScreen(veh) then
                local x, y = convert3DCoordsToScreen(getCarCoordinates(veh))
                local lines = {
                    ('%s [%s]'):format(getNameOfVehicleModel(getCarModel(veh)) or 'UNKNOWN', getCarModel(veh)),
                    ('Health: %s'):format(getCarHealth(veh)),
                    ('XYZ: %s'):format(table.concat({getCarCoordinates(veh)}, ', '))
                }
                for i, text in ipairs(lines) do
                    renderFontDrawText(font, text, x - renderGetFontDrawTextLength(font, text) / 2, y, 0xFFffffff)
                    y = y + renderGetFontDrawHeight(font)
                end
            end
Lua:
local font = renderCreateFont('Trebuchet MS', 9, 5)

function main()
    while not isSampAvailable() do wait(0) end
    while true do
        wait(0)
        for _, veh in ipairs(getAllVehicles()) do
            if isCarOnScreen(veh) then
                local x, y = convert3DCoordsToScreen(getCarCoordinates(veh))
                local lines = {
                    ('%s [%s]'):format(getNameOfVehicleModel(getCarModel(veh)) or 'UNKNOWN', getCarModel(veh)),
                    ('Health: %s'):format(getCarHealth(veh)),
                    ('XYZ: %s'):format(table.concat({getCarCoordinates(veh)}, ', '))
                }
                for i, text in ipairs(lines) do
                    renderFontDrawText(font, text, x - renderGetFontDrawTextLength(font, text) / 2, y, 0xFFffffff)
                    y = y + renderGetFontDrawHeight(font)
                end
            end
        end
    end
end
1673693430746.png
 
  • Ха-ха
Реакции: qdIbp

l-m

Новичок
28
1
?
Lua:
local wast = 0

function main()
    while not sampIsLocalPlayerSpawned() do wait(100) end
    sampRegisterChatCommand('off',function()
        wast = 0
    end)
    while true do wait(0)
        for i = 1, wast do
            sampSendChat('/c xz')
            wait(123)
        end
    end
end

require('lib.samp.events').onSendCommand = function(cmd)
    if string.match(cmd,'^/test') then
        if wast == 0 then
            sampAddChatMessage('Ухх пошла жара',-1)
        end
        wast = wast + 1
    end
end
Флуд 'Ухх пошла жара' и кикает с сервера. Возможно ошибка в коде, возможно я не правильно объяснил. Я ввожу команду, и начинается производится текст который я забиндил с задержкой. Если к примеру трижды прописать команду, то одновременно в 3 строки будет производится текст. Так вот, я хочу сделать блокировку команды. Если я первый раз ввёл команду, начинает работать биндер с текстом, но, если этот биндер не дошёл до конца, то ввод команды будет не возможен.
1673722154604.png

Если ввести быстро несколько раз команду, то начинается флуд и кикает из сервера
 

CaJlaT

Овощ
Модератор
2,807
2,614
Флуд 'Ухх пошла жара' и кикает с сервера. Возможно ошибка в коде, возможно я не правильно объяснил. Я ввожу команду, и начинается производится текст который я забиндил с задержкой. Если к примеру трижды прописать команду, то одновременно в 3 строки будет производится текст. Так вот, я хочу сделать блокировку команды. Если я первый раз ввёл команду, начинает работать биндер с текстом, но, если этот биндер не дошёл до конца, то ввод команды будет не возможен.
Посмотреть вложение 185993
Если ввести быстро несколько раз команду, то начинается флуд и кикает из сервера
создавай поток, при повторном вводе команды удаляй его....
Lua:
function main()
    sampRegisterChatCommand('aboba', function()
        if thread then
            thread:terminate()
            thread = nil
            sampAddChatMessage('Флудер остановлен', -1)
            return
        end
        sampAddChatMessage('Флудер запущен', -1)
        thread = lua_thread.create(function()
            while true do
                sampAddChatMessage('ABOBA', -1)
                wait(100)
            end
        end)
    end)
    wait(-1)
end
1673722949727.png
 
  • Нравится
Реакции: qdIbp

l-m

Новичок
28
1
создавай поток, при повторном вводе команды удаляй его....
Lua:
function main()
    sampRegisterChatCommand('aboba', function()
        if thread then
            thread:terminate()
            thread = nil
            sampAddChatMessage('Флудер остановлен', -1)
            return
        end
        sampAddChatMessage('Флудер запущен', -1)
        thread = lua_thread.create(function()
            while true do
                sampAddChatMessage('ABOBA', -1)
                wait(100)
            end
        end)
    end)
    wait(-1)
end
Посмотреть вложение 185995
Не через main получится? Чтобы вот в этот код))))
Lua:
function sampev.onServerMessage(color--[[Цвет]], text--[[Текст]]) -- Этот хук ловит сообщения в чате
    lua_thread.create(function() -- создаем поток -- позволяет использовать wait
        if status then
            if text:find('[R].*: /driver') then -- если найден текст "test" то
                wait(100) -- отвечает за ожидание в размере секунды БЫЛО 1000 сек
                sampSendChat('/r Вызываю эвакуатор через 10 секунд')
                wait(5000)
                sampSendChat('/r (( /drive 5 sek ))')
                wait(4000)
                sampSendChat('/r Вызываю эвакуатор через 1 секунду, кто не успел тот опоздал')
                wait(1000)
                sampSendChat('/drive') -- если в чате засветится сообщение test, то хук поймает данное сообщение, дальше скрипт подождет 1 секунду и выведет "Не тест"
                wait(2000)
                sampCloseCurrentDialogWithButton(1) --закрывает окно с нажатием кнопки
            elseif text:find('[R].*: /cancel') then
                sampSendChat("/r (( drive disabled ))")
                wait(500)
                thisScript():reload() 
            end    
        end    
    end)-- закрываем поток
end
 

Arseniy_Verteich

Новичок
1
0
Ребят, помогите пожалуйста, в медхелпере при вводе команды /hl (id) отыгрывается рп, и после должно хилить игрока, но после обновлений нужно писать цену хила, изза этого выдает ошибку, в самой аризоне, мол введите цену за лечение , в хелпере есть политика цен, но она не работает. Как сделать так, что бы хелпер работал по команде /hl (id) (цена) и в после выдавал /heal (id) (цена) А не просто /heal (id). Да знаю, это сделать вроде-бы просто, но я новичок, и не разбираюсь в этом.
Нужно сделать перепенную, но как?