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

Hatiko

Известный
Проверенный
1,494
617
Можно ли как-то в lua копировать/вставлять или перемещать файлы? Просто мне нужно созданный скриншот скопировать или перетащит ьв другую папку.
 

Frapsy

Известный
Проверенный
393
227
Допустим, есть переменная pID, которая содержит в себе заданный айдишник, каким образом можно получить информацию о том, какой он дамаг нанес/получил? Ибо onSendGiveDamage и OnSendTakeDamage как я понял, они показывают информацию только обо мне(от кого я получаю и кому я даю урон).
 
Последнее редактирование:
1,417
1,032
Допустим, есть переменная pID, которая содержит в себе заданный айдишник, каким образом можно получить информацию о том, какой он дамаг нанес/получил? Ибо onSendGiveDamage и OnSendTakeDamage как я понял, они показывают информацию только обо мне(от кого я получаю и кому я даю урон).
Lua:
local q = require 'lib.samp.events'

function main()
    repeat wait(0) until isSampAvailable()
    wait(-1)
end

function q.onBulletSync(playerId, data)
    if playerId == pID then
        sampAddChatMessage('Target '..data.targetId..' WeaponId '..data.weaponId..' tX '..data.target.x..' tY '..data.target.y..' tZ '..data.target.z, -1)
    end
end
--[[
struct BulletSyncData
{
    uint8_t               targetType;
    uint16_t           targetId;
    struct VectorXYZ origin;
    struct VectorXYZ target;
    struct VectorXYZ center;
    uint8_t               weaponId;
} __attribute__ ((packed));
]]
 

ShuffleBoy

Известный
Друг
753
425
Lua:
ffi = require 'ffi'

ffi.cdef[[
struct stPickup
{
    int        iModelID;
    int        iType;
    float    fPosition[3];
};

struct stPickupPool
{
    int                iPickupsCount;
    uint32_t        ul_GTA_PickupID[4096];
    int                iPickupID[4096];
    int                iTimePickup[4096];
    uint8_t            unk[4096 * 3];
    struct stPickup pickup[4096];
};
]]

function sampGetInfoPickup(id)
    local pool = ffi.cast('struct stPickupPool*', sampGetPickupPoolPtr())
    return pool.pickup[id].iModelID, pool.pickup[id].iType
end
local model, type = sampGetInfoPickup(id)

Пробывал так:
Lua:
function sampGetInfoPickup(id)
    ffi.cdef[[
    struct stPickup
    {
        int        iModelID;
        int        iType;
        float    fPosition[3];
    };

    struct stPickupPool
    {
        int                iPickupsCount;
        uint32_t        ul_GTA_PickupID[4096];
        int                iPickupID[4096];
        int                iTimePickup[4096];
        uint8_t            unk[4096 * 3];
        struct stPickup pickup[4096];
    };
    ]]
    local pool = ffi.cast('struct stPickupPool*', sampGetPickupPoolPtr())
    return pool.pickup[id].iModelID, pool.pickup[id].iType
end

Получилось так:
Код:
[10:42:50.087901] (error)   test.lua: D:\Games\GTA San Andreas\moonloader\test.lua:186: attempt to redefine 'stPickup' at line 2
stack traceback:
    [C]: in function 'cdef'
    D:\Games\GTA San Andreas\moonloader\test.lua:186: in function 'sampGetInfoPickup'
    D:\Games\GTA San Andreas\moonloader\test.lua:59: in function <D:\Games\GTA San Andreas\moonloader\test.lua:52>
 

imring

Ride the Lightning
Всефорумный модератор
2,362
2,545
Пробывал так:
Lua:
function sampGetInfoPickup(id)
    ffi.cdef[[
    struct stPickup
    {
        int        iModelID;
        int        iType;
        float    fPosition[3];
    };

    struct stPickupPool
    {
        int                iPickupsCount;
        uint32_t        ul_GTA_PickupID[4096];
        int                iPickupID[4096];
        int                iTimePickup[4096];
        uint8_t            unk[4096 * 3];
        struct stPickup pickup[4096];
    };
    ]]
    local pool = ffi.cast('struct stPickupPool*', sampGetPickupPoolPtr())
    return pool.pickup[id].iModelID, pool.pickup[id].iType
end

Получилось так:
Код:
[10:42:50.087901] (error)   test.lua: D:\Games\GTA San Andreas\moonloader\test.lua:186: attempt to redefine 'stPickup' at line 2
stack traceback:
    [C]: in function 'cdef'
    D:\Games\GTA San Andreas\moonloader\test.lua:186: in function 'sampGetInfoPickup'
    D:\Games\GTA San Andreas\moonloader\test.lua:59: in function <D:\Games\GTA San Andreas\moonloader\test.lua:52>
вынеси ffi.cdef за функцию.
 
  • Нравится
Реакции: ShuffleBoy

штейн

Известный
Проверенный
1,003
688
Lua:
function checkall2()
    local data = LIP.load('moonloader\\config\\secret.ini')
    local ip = sampGetCurrentServerAddress()
    if data.AL.SERVER ~= nil then
        server = data.AL.SERVER
        local ip = data.AL.SERVER:gsub(':7777', '')
        if ip == 'ip' or not server == ip then
            sampAddChatMessage("[ {808080}GAuth {ffffff}]: IP сервера не указан, укажите его командой - [ {808080}/setserver {ffffff}].", 0xFFFFFF)
            checkall3()
        else
            if server == ip then
            checkall3()
          end
    end
  end
end

function checkall3()
    local data = LIP.load('moonloader\\config\\secret.ini')
    if data.AL.NAME ~= nil then
        name = data.AL.NAME
        local nick = sampGetPlayerNickname(id)
        local name = data.AL.NAME:gsub('_', ' ')
        if name == 'Nick_Name' or not name == nick then
            sampAddChatMessage("[ {808080}GAuth {ffffff}]: Ник не указан, укажите его командой [ {808080}/setnick {ffffff}].", 0xFFFFFF)
            checkall4()
        else
            if name ~= nil then
                checkall4()
          end
        end
    end
end

function checkall4()
    local data = LIP.load('moonloader\\config\\secret.ini')
    local ip = sampGetCurrentServerAddress()
    local sname = servers[sampGetCurrentServerAddress()]
    nick = sampGetPlayerNickname(id)
    secret = data.AL.SECRET
    name = data.AL.NAME
    server = data.AL.SERVER
    if secret == 'secret' or name == 'Nick_Name' or not name == nick or not server == ip then
        lua_thread.create(firstThread)
        gauth = false
    else
    if secret ~= nil and name ~= nil and server ~= nil then
        sampAddChatMessage("[ {808080}GAuth {ffffff}]: Все данные для работы {808080}GAuth {ffffff}указаны верно.", 0xFFFFFF)
        sampAddChatMessage("[ {808080}GAuth {ffffff}]: Версия скрипта - "..thisScript().version, 0xFFFFFF)
      end
  end
end

почему если ник указан верно он всё равно говорит мне типо не верно, с ip точно так же
в checkall4() он мне вообще ничего не показывает
 

imring

Ride the Lightning
Всефорумный модератор
2,362
2,545
Lua:
function checkall2()
    local data = LIP.load('moonloader\\config\\secret.ini')
    local ip = sampGetCurrentServerAddress()
    if data.AL.SERVER ~= nil then
        server = data.AL.SERVER
        local ip = data.AL.SERVER:gsub(':7777', '')
        if ip == 'ip' or not server == ip then
            sampAddChatMessage("[ {808080}GAuth {ffffff}]: IP сервера не указан, укажите его командой - [ {808080}/setserver {ffffff}].", 0xFFFFFF)
            checkall3()
        else
            if server == ip then
            checkall3()
          end
    end
  end
end

function checkall3()
    local data = LIP.load('moonloader\\config\\secret.ini')
    if data.AL.NAME ~= nil then
        name = data.AL.NAME
        local nick = sampGetPlayerNickname(id)
        local name = data.AL.NAME:gsub('_', ' ')
        if name == 'Nick_Name' or not name == nick then
            sampAddChatMessage("[ {808080}GAuth {ffffff}]: Ник не указан, укажите его командой [ {808080}/setnick {ffffff}].", 0xFFFFFF)
            checkall4()
        else
            if name ~= nil then
                checkall4()
          end
        end
    end
end

function checkall4()
    local data = LIP.load('moonloader\\config\\secret.ini')
    local ip = sampGetCurrentServerAddress()
    local sname = servers[sampGetCurrentServerAddress()]
    nick = sampGetPlayerNickname(id)
    secret = data.AL.SECRET
    name = data.AL.NAME
    server = data.AL.SERVER
    if secret == 'secret' or name == 'Nick_Name' or not name == nick or not server == ip then
        lua_thread.create(firstThread)
        gauth = false
    else
    if secret ~= nil and name ~= nil and server ~= nil then
        sampAddChatMessage("[ {808080}GAuth {ffffff}]: Все данные для работы {808080}GAuth {ffffff}указаны верно.", 0xFFFFFF)
        sampAddChatMessage("[ {808080}GAuth {ffffff}]: Версия скрипта - "..thisScript().version, 0xFFFFFF)
      end
  end
end

почему если ник указан верно он всё равно говорит мне типо не верно, с ip точно так же
в checkall4() он мне вообще ничего не показывает
moonloader/config/secret.ini скинь.
 

штейн

Известный
Проверенный
1,003
688
Lua:
function checkall2()
    local data = LIP.load('moonloader\\config\\secret.ini')
    local ip = sampGetCurrentServerAddress()
    if data.AL.SERVER ~= nil then
        server = data.AL.SERVER
        local ip = data.AL.SERVER:gsub(':7777', '')
        if server == 'ip' or ip ~= server then
            sampAddChatMessage("[ {808080}GAuth {ffffff}]: IP сервера указан не верно, укажите его командой - [ {808080}/setserver {ffffff}].", 0xFFFFFF)
            checkall3()
        else
            if ip ~= server then
            checkall3()
          end
    end
  end
end

function checkall3()
    local data = LIP.load('moonloader\\config\\secret.ini')
    if data.AL.NAME ~= nil then
        name = data.AL.NAME
        nick = sampGetPlayerNickname(id)
        local name = data.AL.NAME:gsub('_', ' ')
        if name == 'Nick_Name' or nick ~= name then
            sampAddChatMessage("[ {808080}GAuth {ffffff}]: Ник указан не верно, укажите его командой - [ {808080}/setnick {ffffff}].", 0xFFFFFF)
            checkall4()
        else
            if not name == 'Nick_Name' and name == nick then
                checkall4()
          end
        end
    end
end

function checkall4()
    local data = LIP.load('moonloader\\config\\secret.ini')
    local ip = sampGetCurrentServerAddress()
    local sname = servers[sampGetCurrentServerAddress()]
    local nick = sampGetPlayerNickname(id)
    secret = data.AL.SECRET
    name = data.AL.NAME
    server = data.AL.SERVER
    if secret == 'secret' or name == 'Nick_Name' or server == 'ip' or not nick == name or not ip == server then
        lua_thread.create(firstThread)
        gauth = false
    else
    if secret ~= nil and nick == name and ip == server then
        sampAddChatMessage("[ {808080}GAuth {ffffff}]: Все данные для работы {808080}GAuth {ffffff}указаны верно.", 0xFFFFFF)
        sampAddChatMessage("[ {808080}GAuth {ffffff}]: Версия скрипта - "..thisScript().version, 0xFFFFFF)
      end
  end
end

теперь скрипт работает когда IP пишу стандартный (т.е. 'ip'), но если указать вообще что-либо кроме "ip" - он никак не хочет работать дальше (т.е. он даже до checkall3() не доходит, но сам скрипт не крашится)
с ником точно так же, но он почему-то уже всегда показывает что всё указано не верно, даже если я напишу всё правильно
 
Последнее редактирование:

штейн

Известный
Проверенный
1,003
688
прив ещё раз, короче
т.к. я бомж пытался сделать что-то годное но чет не оч получается, хотел сделать чтоб при отправке какого-то сообщения в чат то у меня выполнялась определённая функция, но я не очень разбираюсь в этом, и естественно у меня это не получилось

если можно, объясните[!!!!!!] как сделать что-то подобное:
Lua:
function sampev.onServerMessage(color, text)
  if text:find('%{.+%}.+%[.+%] говорит:%{.+%} .+') then -- если найдена строка с таким форматом
    local thisnick, thistext = text:match('%{.+%}(.+)%[.+%] говорит:%{.+%} (.+)') -- получаем текст из этой строки
    if thisnick and thistext then -- если удачно
      local thisid = sampGetPlayerIdByNickname(thisnick) -- получаем ID по NickName (функция imring)
      local color = string.format("%06X", ARGBtoRGB(sampGetPlayerColor(thisid))) -- получаем цвет через ID
      sampAddChatMessage('{'..color..'}'..thisnick..' {ffffff}говорит: '..thistext, -1) -- отправляем в чат
      return false -- игнорируем прошлый текст, который без форматирования.
    end
  end
end

что значит вот это: %{.+%}.+%[.+%] говорит:%{.+%} .+, как можно их различать и тп, и ещё если можно что-нибудь по этому поводу разъясните мне)
 

#Northn

Pears Project — уже запущен!
Всефорумный модератор
2,650
2,535
Как правильно достать слово выключи из строки 'Бомж, выключи музон'
Lua:
local off = text:match('Бомж, (.+) музон')
if off then
 print(off)
end

--------

прив ещё раз, короче
т.к. я бомж пытался сделать что-то годное но чет не оч получается, хотел сделать чтоб при отправке какого-то сообщения в чат то у меня выполнялась определённая функция, но я не очень разбираюсь в этом, и естественно у меня это не получилось

если можно, объясните[!!!!!!] как сделать что-то подобное:
Lua:
function sampev.onServerMessage(color, text)
  if text:find('%{.+%}.+%[.+%] говорит:%{.+%} .+') then -- если найдена строка с таким форматом
    local thisnick, thistext = text:match('%{.+%}(.+)%[.+%] говорит:%{.+%} (.+)') -- получаем текст из этой строки
    if thisnick and thistext then -- если удачно
      local thisid = sampGetPlayerIdByNickname(thisnick) -- получаем ID по NickName (функция imring)
      local color = string.format("%06X", ARGBtoRGB(sampGetPlayerColor(thisid))) -- получаем цвет через ID
      sampAddChatMessage('{'..color..'}'..thisnick..' {ffffff}говорит: '..thistext, -1) -- отправляем в чат
      return false -- игнорируем прошлый текст, который без форматирования.
    end
  end
end

что значит вот это: %{.+%}.+%[.+%] говорит:%{.+%} .+, как можно их различать и тп, и ещё если можно что-нибудь по этому поводу разъясните мне)
В начало каждого знака: [ ] { } ставится знак процента: %
.+ обозначает любой символ, цифру или букву
%d+ обозначает цифру
%g+ ники (если не ошибаюсь)
Исходя из этого всего строится предложение.
Текст, который хочешь получить бери в скобки.
 
Последнее редактирование:

imring

Ride the Lightning
Всефорумный модератор
2,362
2,545
Lua:
local off = text:match('Бомж (.+) музон')
if off then
 print(off)
end
у тебя off будет nil.
Lua:
local off = ('Бомж, выключи музон'):match('Бомж%C%s(.+)%sмузон')
print(off)

UPD: а лучше так:
Lua:
local off = ('Эй, бомж! выруби музон! И уйди от сюда.'):rlower():match('^.-бомж%C-%s+(.+)%s+музон.-$')
print(off)
 
Последнее редактирование:
  • Нравится
Реакции: user116675 и #Northn