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

artie

Участник
70
20
как можно тут флуд убрать? чтобы при каждом появлении текстдрава не флудило /id?
Lua:
function sampev.onShowTextDraw(id, data)
    if data.text:find('^.+ %- .+ .+ %(.+%)~n~$') and data.modelId == 0 and data.letterColor == -5397778 then
        local nick, gun, damage = data.text:match('^(.+) %- (.+) (.+) %(.+%)~n~$')
        sampSendChat('/id '..nick..'')
    end
end
 

ARMOR

Модератор по раксампу
Модератор
4,936
6,732
как можно тут флуд убрать? чтобы при каждом появлении текстдрава не флудило /id?
Lua:
function sampev.onShowTextDraw(id, data)
    if data.text:find('^.+ %- .+ .+ %(.+%)~n~$') and data.modelId == 0 and data.letterColor == -5397778 then
        local nick, gun, damage = data.text:match('^(.+) %- (.+) (.+) %(.+%)~n~$')
                  sampSendChat('/id '..nick..'')
    end
end
Lua:
function sampev.onShowTextDraw(id, data)
    if data.text:find('^.+ %- .+ .+ %(.+%)~n~$') and data.modelId == 0 and data.letterColor == -5397778 then
    local nick, gun, damage = data.text:match('^(.+) %- (.+) (.+) %(.+%)~n~$')
end
 

artie

Участник
70
20
Lua:
function sampev.onShowTextDraw(id, data)
    if data.text:find('^.+ %- .+ .+ %(.+%)~n~$') and data.modelId == 0 and data.letterColor == -5397778 then
    local nick, gun, damage = data.text:match('^(.+) %- (.+) (.+) %(.+%)~n~$')
end
не, я имею в виду, что надо чтобы отправлялось серверу /id, но этот текстдрав - дамаг информер будет появляеся при каждом попадании в персонажа, и, соответственно, будет флуд /id, а надо чтобы допустим после одного попадания и появления текстдрава просто один раз /id отправляло и потом секунд 10-20 хоть сколько раз там этот текстдрав ни появлялся - ничего не отправлялось, сорри что в начале коряво объяснил
 

ARMOR

Модератор по раксампу
Модератор
4,936
6,732
не, я имею в виду, что надо чтобы отправлялось серверу /id, но этот текстдрав - дамаг информер будет появляеся при каждом попадании в персонажа, и, соответственно, будет флуд /id, а надо чтобы допустим после одного попадания и появления текстдрава просто один раз /id отправляло и потом секунд 10-20 хоть сколько раз там этот текстдрав ни появлялся - ничего не отправлялось, сорри что в начале коряво объяснил
Не знаю насколько мой код будет правильным( Как минимум у него будет минус из-за потока. Мб кто-то потом напишет код получше )
Lua:
local enable = true

function sampev.onShowTextDraw(id, data)
    if data.text:find('^.+ %- .+ .+ %(.+%)~n~$') and data.modelId == 0 and data.letterColor == -5397778 and enable then
        local nick, gun, damage = data.text:match('^(.+) %- (.+) (.+) %(.+%)~n~$')
        enable = false
        sampSendChat('/id '..nick..'')
        Time()
    end
end

function Time()
    lua_thread.create(function()
        wait(20000) -- 20000 мс = 20 секунд
        enable = true
    end)
end
 
  • Влюблен
Реакции: artie

artie

Участник
70
20
помогите пожалуйста с регуляркой, чтобы захватывало ник и кол-во урона (вместе с плюсом)
наподобие такого: "Darik_Banan нанес +11.32 урона!"
kmi6ubj(1)(1).png


QgATOLj(1)(1).png


Lua:
function sampev.onShowTextDraw(id, data)
    if data.text:find('') and data.modelId == 0 and data.letterColor == 2155905152 then
        local nick, damage = data.text:match('')
        sampAddChatMessage(''..nick..' нанес '..damage..' урона!')
        return false
    end
end
 

ARMOR

Модератор по раксампу
Модератор
4,936
6,732
помогите пожалуйста с регуляркой, чтобы захватывало ник и кол-во урона (вместе с плюсом)
наподобие такого: "Darik_Banan нанес +11.32 урона"
Посмотреть вложение 168550

Посмотреть вложение 168553

Lua:
function sampev.onShowTextDraw(id, data)
    if data.text:find('') and data.modelId == 0 and data.letterColor == 2155905152 then
        local nick, damage = data.text:match('')
        -- code
        return false
    end
end
Lua:
(.+) нанес %+(%d+%.%d+) урона
 
  • Влюблен
Реакции: artie

moreveal

Известный
Проверенный
920
617
сделал проверку с тестовым выводом текста в чат лог, но не работает проверка, как быть друзья мои?
ggg:
function onCreatePickup(pickupId)
            local data = getPickup(pickupId)
            if data.position.x == -2276.0407714844 and data.position.y == 535.40997314453 and data.position.z == 35.109798431396 then
                printLog("Пошёл нахуй")
            end
end
 

copypaste_scripter

Известный
1,261
235
Lua:
require('lib.moonloader')
local sampev = require('lib.samp.events')
local var1 = 0

function main()
    if not isSampLoaded() or not isSampfuncsLoaded() then return end
    while not isSampAvailable() do wait(100) end
   
    sampAddChatMessage("aaaaaaaaaaaa", -1)
   
    sampRegisterChatCommand('wello', var1)
end

function sampev.onShowDialog(id, s, t, btn1, btn2, text)
    lua_thread.create(function()
        if id == 228 then
            wait(100)
            stroka = sampGetListboxItemByText(tostring(var1))
            sampSendDialogResponse(id, 1, stroka, nil)
        end
    end)
end

function sampGetListboxItemByText(text, plain)
    if not sampIsDialogActive() then return -1 end
        plain = not (plain == false)
    for i = 0, sampGetListboxItemsCount() - 1 do
        if sampGetListboxItemText(i):find(text, 1, plain) then
            return i
        end
    end
    return -1
end
когда ввожу в игре команду /wello x1 выдает ошибку

[ML] (error) myscript.lua: attempt to call a number value
stack traceback:
[ML] (error) myscript.lua: Script died due to an error. (281F89A4)

edit: скрипт должен найти текст и нажать на нем в диалоге (текст ввожу я с помощью команды)
 

chapo

чопа сребдс // @moujeek
Модератор
8,861
11,548
Lua:
require('lib.moonloader')
local sampev = require('lib.samp.events')
local var1 = 0

function main()
    if not isSampLoaded() or not isSampfuncsLoaded() then return end
    while not isSampAvailable() do wait(100) end
  
    sampAddChatMessage("aaaaaaaaaaaa", -1)
  
    sampRegisterChatCommand('wello', var1)
end

function sampev.onShowDialog(id, s, t, btn1, btn2, text)
    lua_thread.create(function()
        if id == 228 then
            wait(100)
            stroka = sampGetListboxItemByText(tostring(var1))
            sampSendDialogResponse(id, 1, stroka, nil)
        end
    end)
end

function sampGetListboxItemByText(text, plain)
    if not sampIsDialogActive() then return -1 end
        plain = not (plain == false)
    for i = 0, sampGetListboxItemsCount() - 1 do
        if sampGetListboxItemText(i):find(text, 1, plain) then
            return i
        end
    end
    return -1
end
когда ввожу в игре команду /wello x1 выдает ошибку

[ML] (error) myscript.lua: attempt to call a number value
stack traceback:
[ML] (error) myscript.lua: Script died due to an error. (281F89A4)

edit: скрипт должен найти текст и нажать на нем в диалоге (текст ввожу я с помощью команды)
ты пытаешься вызвать функцию, хотя тип переменной не функция, а число
 
  • Нравится
Реакции: copypaste_scripter

copypaste_scripter

Известный
1,261
235
Lua:
require('lib.moonloader')
local sampev = require('lib.samp.events')
local var1 = nil

function main()
    if not isSampLoaded() or not isSampfuncsLoaded() then return end
    while not isSampAvailable() do wait(100) end
   
    sampAddChatMessage("aaaaaaaaaaaa", -1)
   
    sampRegisterChatCommand('wello', function(var1)
        var1 = tostring(var1)
    end)
end

function sampev.onShowDialog(id, s, t, btn1, btn2, text)
    lua_thread.create(function()
        if id == 185 then
            wait(100)
            stroka = sampGetListboxItemByText(tostring(var1))
            sampSendDialogResponse(id, 1, stroka, nil)
        end
    end)
end

function sampGetListboxItemByText(text, plain)
    if not sampIsDialogActive() then return -1 end
        plain = not (plain == false)
    for i = 0, sampGetListboxItemsCount() - 1 do
        if sampGetListboxItemText(i):find(text, 1, plain) then
            return i
        end
    end
    return -1
end

пишу /wello Бургер ((строка из автомата еды)), подхожу к автомату и открывается диалог, не выбирает ничего, ошибки нет, что делать?
edit: вот диалог
1663159320980.png
 
Последнее редактирование:

Ononimus

Потрачен
60
0
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
Ребят дайте код что бы если открыть чат и заать alt + t то в строке откправки сообщения вылезит допутим привет
 

Fomikus

Известный
Проверенный
475
345
Lua:
require('lib.moonloader')
local sampev = require('lib.samp.events')
local var1 = nil

function main()
    if not isSampLoaded() or not isSampfuncsLoaded() then return end
    while not isSampAvailable() do wait(100) end
  
    sampAddChatMessage("aaaaaaaaaaaa", -1)
  
    sampRegisterChatCommand('wello', function(var1)
        var1 = tostring(var1)
    end)
end

function sampev.onShowDialog(id, s, t, btn1, btn2, text)
    lua_thread.create(function()
        if id == 185 then
            wait(100)
            stroka = sampGetListboxItemByText(tostring(var1))
            sampSendDialogResponse(id, 1, stroka, nil)
        end
    end)
end

function sampGetListboxItemByText(text, plain)
    if not sampIsDialogActive() then return -1 end
        plain = not (plain == false)
    for i = 0, sampGetListboxItemsCount() - 1 do
        if sampGetListboxItemText(i):find(text, 1, plain) then
            return i
        end
    end
    return -1
end

пишу /wello Бургер ((строка из автомата еды)), подхожу к автомату и открывается диалог, не выбирает ничего, ошибки нет, что делать?
edit: вот диалог
Посмотреть вложение 168589
sampGetListboxItemText вроде как сломан и берёт текст из 1 колонки (Попробуй вывести), еще как вариант - кодировка из получения текста и переменной не совпадает, проверяется тоже принтом.
На замену sampGetListboxItemText можно юзать итерацию через gmatch
 
  • Нравится
Реакции: copypaste_scripter

linmsqn

Участник
337
9
вообщем, при выводе значение из бд в чат - получается ошибка, почему, не знаю
Lua:
function test_mysql()
    mysql = mysql_drv.mysql()
    mysqlconn = mysql:connect("логин", "бд", "пасс", "хост")

    testsql = mysqlconn:execute('SELECT ip FROM attempts LIMIT 2')
    sampAddChatMessage('id'..testsql, -1) -- 108 строка
end

ошибка 108: attempt to concatenate global 'testsql' (a userdata value)
 

Fomikus

Известный
Проверенный
475
345
вообщем, при выводе значение из бд в чат - получается ошибка, почему, не знаю
Lua:
function test_mysql()
    mysql = mysql_drv.mysql()
    mysqlconn = mysql:connect("логин", "бд", "пасс", "хост")

    testsql = mysqlconn:execute('SELECT ip FROM attempts LIMIT 2')
    sampAddChatMessage('id'..testsql, -1) -- 108 строка
end

ошибка 108: attempt to concatenate global 'testsql' (a userdata value)
execute возвращает курсор и нужно получать результат вызовом fetch
Гайд | Перевод гайда
 

linmsqn

Участник
337
9
execute возвращает курсор и нужно получать результат вызовом fetch
Гайд | Перевод гайда
Lua:
if not mysqlconn ~= nil then
    mysql_querry = string.format("SELECT ip FROM attempts LIMIT 2")
    cursor = mysqlconn:execute(mysql_querry) --137 строка
    row = cursor:fetch ({}, "a")
    while row do
        print(string.format("Id: %s, Name: %s", row))
        row = cursor:fetch (row, "a")
    end
else
   sampAddChatMessage("Connection error", 0x0000FF)
end

--ошибка
137: attempt to index global 'mysqlconn' (a nil value)
все равно та же ошибка