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

StarFresko1227

Известный
46
1
Помогите пожалуйста, почему не работает?
Должно быть, если в чате появится Nick_Name[227] (( {FFE6E6}тест{FFFFFF} ))
он ответил тест сработал

помогите пожалуйста

Код:
local sampev = require 'lib.samp.events'

function sampev.onServerMessage(color, text)
    smsnick, smsid, smstext = string.match(text, "(%a+_%a+)[(%d+)] (( {FFE6E6}(.+){FFFFFF} ))")
    if string.find(smstext, "тест скрипта") then
        sampSendChat(string.format("/b привет %d, тест сработал", smsid))
    end
end
 

f0rtrix

Известный
208
15
Lua:
local game_weapons = require 'game.weapons'

lua_thread.create(function()
    while true do wait(0)
        if sampIsLocalPlayerSpawned() then
            local currentWeapon = getCurrentCharWeapon(playerPed)
            if isKeyJustPressed(0x02) then
                if currentWeapon ~= lastWeapon and game_weapons.get_name(currentWeapon) ~= 'Fist' then
                    sampSendChat('/me снял '..game_weapons.get_name(currentWeapon)..' с поясного держателя.')
                    lastWeapon = currentWeapon
                end
            else
                if currentWeapon ~= lastWeapon and game_weapons.get_name(currentWeapon) == 'Fist' then
                    sampSendChat('/me повесил оружие за поясной держатель.')
                    lastWeapon = currentWeapon
                end
            end
        end
    end
end)

Отыгровка оружия срабатывает только при нажатии ПКМ, чтобы при скролле не было всякого флуда и т.п, при убирании оружия нажимать ПКМ не нужно.
Это как то через чур костыльно для Lua. При нажатии ПКМ будет РП отыгровка оружия... И к тому же не каждый тип оружия можно "повесил оружие за поясной держатель". Я сомневаюсь что ты елду или нож будешь за поясный держатель вешать :D
 

ShuffleBoy

Известный
Друг
754
429
Это как то через чур костыльно для Lua. При нажатии ПКМ будет РП отыгровка оружия... И к тому же не каждый тип оружия можно "повесил оружие за поясной держатель". Я сомневаюсь что ты елду или нож будешь за поясный держатель вешать :D
Блять бери и допиливай сам, ничего тут костыльного нет
 

qojqva

Известный
56
2
Как сделать что бы при вводе команды /mq id
все последующие действия и оскорбления шли именно к этому человеку?
/mq 43
Matebal 43 id
 

trefa

Известный
Всефорумный модератор
2,097
1,233
Помогите пожалуйста, почему не работает?
Должно быть, если в чате появится Nick_Name[227] (( {FFE6E6}тест{FFFFFF} ))
он ответил тест сработал

помогите пожалуйста

Код:
local sampev = require 'lib.samp.events'

function sampev.onServerMessage(color, text)
    smsnick, smsid, smstext = string.match(text, "(%a+_%a+)[(%d+)] (( {FFE6E6}(.+){FFFFFF} ))")
    if string.find(smstext, "тест скрипта") then
        sampSendChat(string.format("/b привет %d, тест сработал", smsid))
    end
end
Lua:
local sampev = require 'lib.samp.events'

function sampev.onServerMessage(color, text)
if string.find(text, "(.*)%[(%d+)%]%s+%(%(%s+%{FFE6E6%}(.*)%{FFFFFF%}%s+%)%") then
local smsnick, smsid, smstext = string.match(text, "(.*)%[(%d+)%]%s+%(%(%s+%{FFE6E6%}(.*)%{FFFFFF%}%s+%)%)")
sampSendChat("/b привет "..smsid..", тест сработал")
end
end

Как сделать что бы при вводе команды /mq id
все последующие действия и оскорбления шли именно к этому человеку?
/mq 43
Matebal 43 id
Lua:
sampRegisterChatCommand("mq", mq) -- в main

function mq(id)
if tonumber(id) ~= nil then
sampSendChat("Matebal "..id.." id")
else
sampAddChatMessage("/mq [id]", -1)
end
end
 
Последнее редактирование модератором:

ShuffleBoy

Известный
Друг
754
429
Как можно отключить возможность управления с клавиатуры/мышки, чтобы только скрипт управлял персонажем?
 

штейн

Известный
Проверенный
1,001
687
(.+) (.-) (.*)
вот тебе 3 варианта замены.

Lua:
function floodPlayerCommand(param)
    lua_thread.create(function()
        local command, sec, sec2, text = string.match(param, '(.*) (%d+) (%d+) %s*(.+)')
        if not flww and not flcc then
            if not flff then
                if sec ~= nil and sec2 ~= nil and command ~= nil and text ~= nil then
                    thissec = sec
                    thissec2 = sec2
                    thistext = text
                    thiscommand = command
                    sampAddChatMessage("[ FLOODER ]: {ffffff}Флудер в {6666FF}/"..thiscommand.." {ffffff}с задержкой в {6666FF}"..thissec.." {ffffff}секунд, на протяжении ..", 0x6666FF)
                    wait(50)
                    sampAddChatMessage("[ FLOODER ]: {ffffff}.. {6666FF}"..thissec2.." {ffffff}секунд активирован.", 0x6666FF)
                    wait(200)
                    sampAddChatMessage("[ FLOODER ]: {ffffff}Для деактивации флудера введите /flf ещё раз.", 0x6666FF)
                    flff = true
                else
                    sampAddChatMessage("[ FLOODER ]: {ffffff}Для активации флудера вводите - {6666FF}[ /flf {ffffff}COMMAND SEC SEC2 TEXT{6666FF} ]{ffffff}.", 0x6666FF)
                    sampAddChatMessage("[ FLOODER ]: {ffffff}Если Вы желаете использовать флудер в обычный чат, вместо COMMAND вводите {6666FF}0{ffffff}.", 0x6666FF)
                end
            else
                if flff or flcc then
                    flff = false
                    flcc = false
                    sampAddChatMessage("[ FLOODER ]: {ffffff}Флудер остановлен принудительно.", 0x6666FF)
                end
            end
        else
            if thiscommand == '0' then
                sampAddChatMessage("[ FLOODER ]: {ffffff}Флудер в обычный чат с задержкой в {6666FF}"..thissec.." {ffffff}секунд, на протяжении ..", 0x6666FF)
                sampAddChatMessage("[ FLOODER ]: {ffffff}.. {6666FF}"..thissec2.." {ffffff}секунд активирован.", 0x6666FF)
                sampAddChatMessage("[ FLOODER ]: {ffffff}Для деактивации флудера введите /flf ещё раз.", 0x6666FF)
                flcc = true
            end
            lua_thread.create(function()
                if flff then
                    wait(thissec2 * 1000)
                    sampAddChatMessage("[ FLOODER ]: {ffffff}Флудер остановлен.", 0x6666FF)
                    flff = false
                    flcc = false
                end
            end)
            if ogran then
                if thissec < '3' then
                    sampAddChatMessage("[ FLOODER ]: {ffffff}Задержка не может быть меньше трёх секунд.", 0x6666FF)
                    sampAddChatMessage("[ FLOODER ]: {ffffff}Для отключения безопасного режима - {6666FF}[ /offogran ]{ffffff}.", 0x6666FF)
                end
            end
        end
    end)
end

почему этот код (убогий) не работает, точнее работает, но не совсем как надо, типа если я ввожу /flc 0 1 10 text, он во-первых со включенным ogran не будет говорить типа не меньше трёх секунд, и по идее он при вводу /flc 0 должен писать в обычный чат, а он пишет в /0
 

trefa

Известный
Всефорумный модератор
2,097
1,233
Lua:
function floodPlayerCommand(param)
    lua_thread.create(function()
        local command, sec, sec2, text = string.match(param, '(.*) (%d+) (%d+) %s*(.+)')
        if not flww and not flcc then
            if not flff then
                if sec ~= nil and sec2 ~= nil and command ~= nil and text ~= nil then
                    thissec = sec
                    thissec2 = sec2
                    thistext = text
                    thiscommand = command
                    sampAddChatMessage("[ FLOODER ]: {ffffff}Флудер в {6666FF}/"..thiscommand.." {ffffff}с задержкой в {6666FF}"..thissec.." {ffffff}секунд, на протяжении ..", 0x6666FF)
                    wait(50)
                    sampAddChatMessage("[ FLOODER ]: {ffffff}.. {6666FF}"..thissec2.." {ffffff}секунд активирован.", 0x6666FF)
                    wait(200)
                    sampAddChatMessage("[ FLOODER ]: {ffffff}Для деактивации флудера введите /flf ещё раз.", 0x6666FF)
                    flff = true
                else
                    sampAddChatMessage("[ FLOODER ]: {ffffff}Для активации флудера вводите - {6666FF}[ /flf {ffffff}COMMAND SEC SEC2 TEXT{6666FF} ]{ffffff}.", 0x6666FF)
                    sampAddChatMessage("[ FLOODER ]: {ffffff}Если Вы желаете использовать флудер в обычный чат, вместо COMMAND вводите {6666FF}0{ffffff}.", 0x6666FF)
                end
            else
                if flff or flcc then
                    flff = false
                    flcc = false
                    sampAddChatMessage("[ FLOODER ]: {ffffff}Флудер остановлен принудительно.", 0x6666FF)
                end
            end
        else
            if thiscommand == '0' then
                sampAddChatMessage("[ FLOODER ]: {ffffff}Флудер в обычный чат с задержкой в {6666FF}"..thissec.." {ffffff}секунд, на протяжении ..", 0x6666FF)
                sampAddChatMessage("[ FLOODER ]: {ffffff}.. {6666FF}"..thissec2.." {ffffff}секунд активирован.", 0x6666FF)
                sampAddChatMessage("[ FLOODER ]: {ffffff}Для деактивации флудера введите /flf ещё раз.", 0x6666FF)
                flcc = true
            end
            lua_thread.create(function()
                if flff then
                    wait(thissec2 * 1000)
                    sampAddChatMessage("[ FLOODER ]: {ffffff}Флудер остановлен.", 0x6666FF)
                    flff = false
                    flcc = false
                end
            end)
            if ogran then
                if thissec < '3' then
                    sampAddChatMessage("[ FLOODER ]: {ffffff}Задержка не может быть меньше трёх секунд.", 0x6666FF)
                    sampAddChatMessage("[ FLOODER ]: {ffffff}Для отключения безопасного режима - {6666FF}[ /offogran ]{ffffff}.", 0x6666FF)
                end
            end
        end
    end)
end

почему этот код (убогий) не работает, точнее работает, но не совсем как надо, типа если я ввожу /flc 0 1 10 text, он во-первых со включенным ogran не будет говорить типа не меньше трёх секунд, и по идее он при вводу /flc 0 должен писать в обычный чат, а он пишет в /0
Lua:
local command, sec, sec2, text = string.match(param, '(.*)%s+(%d+)%s+(%d+)%s+(.*)')
 

штейн

Известный
Проверенный
1,001
687
Lua:
local command, sec, sec2, text = string.match(param, '(.*)%s+(%d+)%s+(%d+)%s+(.*)')
измени на
Lua:
if command == '0' then
не помогло

SEC и SEC2 за что они отвечают?
SEC - задержка во время флуда (пихается в сам бесконечный цикл)
SEC2 - кол-во времени которое будет флудить
 
Последнее редактирование модератором:

imring

Ride the Lightning
Всефорумный модератор
2,355
2,518
@crybaby
Lua:
-- start script
flood_parameters = { cmd = '', delay = 0, duration = 0, text = '', start_flood = 0 }
flooder = lua_thread.create_suspended(function(params)
    local cmd, delay, duration, text, start_flood = params.cmd, params.delay, params.duration, params.text, params.start_flood
    while os.clock() - start_flood < duration do
        wait(delay * 1000)
        sampSendChat((cmd == '0' and '' or '/'..cmd)..' '..text)
        if not start then return end
    end
    start = false
end)

-- function main while true do
if start and flooder:status() ~= 'running' then
    flooder:run(flood_parameters)
end

-- functions or sampRegisterChatCommand
function flood(params)
    local cmd, delay, duration, text = params:match('^(.+)%s+(%d+)%s+(%d+)%s+(.+)$')
    if cmd then
        start = not start
        if start then
            flood_parameters = { cmd = cmd, delay = tonumber(delay), duration = tonumber(duration), text = text, start_flood = os.clock() }
            print('start flood.')
        else print('stop flood.') end
    end
end)
 
  • Нравится
Реакции: штейн

штейн

Известный
Проверенный
1,001
687
@crybaby
Lua:
-- start script
flood_parameters = { cmd = '', delay = 0, duration = 0, text = '', start_flood = 0 }
flooder = lua_thread.create_suspended(function(params)
    local cmd, delay, duration, text, start_flood = params.cmd, params.delay, params.duration, params.text, params.start_flood
    while os.clock() - start_flood < duration do
        wait(delay * 1000)
        sampSendChat((cmd == '0' and '' or '/'..cmd)..' '..text)
        if not start then return end
    end
    start = false
end)

-- function main while true do
if start and flooder:status() ~= 'running' then
    flooder:run(flood_parameters)
end

-- functions or sampRegisterChatCommand
function flood(params)
    local cmd, delay, duration, text = params:match('^(.+)%s+(%d+)%s+(%d+)%s+(.+)$')
    if cmd then
        start = not start
        if start then
            flood_parameters = { cmd = cmd, delay = tonumber(delay), duration = tonumber(duration), text = text, start_flood = os.clock() }
            print('start flood.')
        else print('stop flood.') end
    end
end)
классно, только я хочу сделать это своим, быдлянским способом ибо делаю флудер не для того чтобы его использовать, а для того, чтобы научиться что-то делать новое