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

wintreist

Активный
308
71
Если tostring() переводит в стринг всё, включая числа, то как из стринга перевести в число? Это требуется для проверки if toint(number) <=\>= number then
 

.Makarov.

Известный
190
35
Как это в луа сделать? Короче, по активации команды я должен кликнуть по одному текстдраву, потом чтобы повторялись клики задержкой?
Если я правильно тебя понял, то:


Lua:
local samp = require 'lib.samp.events'
local enable = false
function main()
    if not isSampLoaded() or not isSampfuncsLoaded() then return end
    while not isSampAvailable() do wait(100) end
    clickwaits = 1
    sampRegisterChatCommand("start", function(arg)
        enable = not enable
        arg = tonumber(arg)
        sampAddChatMessage('Текстдрав кликер: '..(enable and '{32C13E}only{FFFFFF}' or '{E21F1F}offline{FFFFFF}'), -1)
        if enable then
            if not arg then
                clickwaits = 1
                sampAddChatMessage("Задержка не указана. Действуем без нее",-1)
            else
                clickwaits = arg
                sampAddChatMessage("Задежка установлена на: "..clickwaits,-1)
            end       
        end
    end)
    while true do wait(1)
        if enable then --Если скрипт активен
            if isKeyDown(113) then --Если зажата кнопка F2
                sampSendClickTextdraw(clickTD)
                wait(clickwaits)
            end
        end
    end
end
function samp.onSendClickTextDraw(tdid)
    if enable then
        --sampAddChatMessage(tdid,-1)
        clickTD = tdid
    end
end
 
  • Нравится
Реакции: eqipatential

Double Tap Inside

Известный
Проверенный
1,899
1,254
Вопрос для умных

Lua:
var = false

-- Что быстрее?

-- это?
var = true

-- или это?
if not var then
..
 

Double Tap Inside

Известный
Проверенный
1,899
1,254
Еще вопрос: как на 100 процентов получить достоверные данные, что игрок заспавнен после логина.

Пакетами PACKET_PLAYER_SYNC пытался, но на аризоне эти пакеты проскакивают при реконекте.
Через LVL игрока со значением 0, такая же херня на аризоне при реконекте остается старый лвл, а потом меняется на ноль, тось тоже проскакивает.
функцией isPlayerSpawned() тоже пытался, но на даймонде она возвращает True в окне логина.
 

alexmarkel0v

Известный
12
1
i need some help
Lua:
function cmd_cfind(param)
    tonumber(param)
    --if param:match('(%d+)') ~= nil then
    --    else end sampAddChatMessage('[ Мысли ] Постоянный поиск игрока [ /cfind ID ]', 0xAFAFAFAA)
    confind2 = param
    if confind == false then
        confind = true
        if sampIsPlayerConnected(param) then
            if not isNull(param) then
                --if confind2 ~= nil then
                    lua_thread.create(function()
                        while confind == true do
                            if confind == false then break end
                            sampSendChat("/find "..confind2)
                            wait(3000)
                        end
                    end)
                --else end
            else sampAddChatMessage('[ Мысли ] Постоянный поиск игрока [ /cfind ID ]', 0xAFAFAFAA)
            end
        else sampAddChatMessage('[ Мысли ] Я не знаю такого', 0xAFAFAFAA)
        end
    else
        sampAddChatMessage('[ Мысли ] Постоянный поиск прекращён', 0xAFAFAFAA)
        confind = false
    end
end

function isNull(x)
  return not not tostring(x):find("^%s*$")
end
у меня есть команда /cfind для постоянного поиска игрока, то есть чтобы каждые 3 секунды флудил /find,но есть проблема.
Если ввести какой-то id, затем выключить (то есть повторно ввести, чтобы не искал) и буквально через секунду другой ID, то он будет флудить дважды одного и того же игрока.
Можно как-то пофиксить это?
 

Double Tap Inside

Известный
Проверенный
1,899
1,254
i need some help
Lua:
function cmd_cfind(param)
    tonumber(param)
    --if param:match('(%d+)') ~= nil then
    --    else end sampAddChatMessage('[ Мысли ] Постоянный поиск игрока [ /cfind ID ]', 0xAFAFAFAA)
    confind2 = param
    if confind == false then
        confind = true
        if sampIsPlayerConnected(param) then
            if not isNull(param) then
                --if confind2 ~= nil then
                    lua_thread.create(function()
                        while confind == true do
                            if confind == false then break end
                            sampSendChat("/find "..confind2)
                            wait(3000)
                        end
                    end)
                --else end
            else sampAddChatMessage('[ Мысли ] Постоянный поиск игрока [ /cfind ID ]', 0xAFAFAFAA)
            end
        else sampAddChatMessage('[ Мысли ] Я не знаю такого', 0xAFAFAFAA)
        end
    else
        sampAddChatMessage('[ Мысли ] Постоянный поиск прекращён', 0xAFAFAFAA)
        confind = false
    end
end

function isNull(x)
  return not not tostring(x):find("^%s*$")
end
у меня есть команда /cfind для постоянного поиска игрока, то есть чтобы каждые 3 секунды флудил /find,но есть проблема.
Если ввести какой-то id, затем выключить (то есть повторно ввести, чтобы не искал) и буквально через секунду другой ID, то он будет флудить дважды одного и того же игрока.
Можно как-то пофиксить это?
Lua:
confind_thread = nil

function cmd_cfind(param)
    tonumber(param)
    --if param:match('(%d+)') ~= nil then
    --    else end sampAddChatMessage('[ Мысли ] Постоянный поиск игрока [ /cfind ID ]', 0xAFAFAFAA)
    confind2 = param
    if confind == false then
        confind = true
        if sampIsPlayerConnected(param) then
            if not isNull(param) then
                --if confind2 ~= nil then
                 
                    if confind_thread then
                        confind_thread:terminate()
                    end
             
                    confind_thread = lua_thread.create_suspended(function()
                        while confind == true do
                            if confind == false then break end
                            sampSendChat("/find "..confind2)
                            wait(3000)
                        end
                    end)
                    confind_thread:run()
                 
                --else end
            else sampAddChatMessage('[ Мысли ] Постоянный поиск игрока [ /cfind ID ]', 0xAFAFAFAA)
            end
        else sampAddChatMessage('[ Мысли ] Я не знаю такого', 0xAFAFAFAA)
        end
    else
        sampAddChatMessage('[ Мысли ] Постоянный поиск прекращён', 0xAFAFAFAA)
        confind = false
    end
end

function isNull(x)
  return not not tostring(x):find("^%s*$")
end

Если поток уже существует, то убиваем его.
Запускаем поток и сохраняем его в переменную.
 
  • Нравится
  • Влюблен
Реакции: koncumone и alexmarkel0v

wintreist

Активный
308
71
Lua:
confind_thread = nil

function cmd_cfind(param)
    tonumber(param)
    --if param:match('(%d+)') ~= nil then
    --    else end sampAddChatMessage('[ Мысли ] Постоянный поиск игрока [ /cfind ID ]', 0xAFAFAFAA)
    confind2 = param
    if confind == false then
        confind = true
        if sampIsPlayerConnected(param) then
            if not isNull(param) then
                --if confind2 ~= nil then
                
                    if confind_thread then
                        confind_thread:terminate()
                    end
            
                    confind_thread = lua_thread.create_suspended(function()
                        while confind == true do
                            if confind == false then break end
                            sampSendChat("/find "..confind2)
                            wait(3000)
                        end
                    end)
                    confind_thread:run()
                
                --else end
            else sampAddChatMessage('[ Мысли ] Постоянный поиск игрока [ /cfind ID ]', 0xAFAFAFAA)
            end
        else sampAddChatMessage('[ Мысли ] Я не знаю такого', 0xAFAFAFAA)
        end
    else
        sampAddChatMessage('[ Мысли ] Постоянный поиск прекращён', 0xAFAFAFAA)
        confind = false
    end
end

function isNull(x)
  return not not tostring(x):find("^%s*$")
end

Если поток уже существует, то убиваем его.
Запускаем поток и сохраняем его в переменную.
Я 100% тупой, но зачем делать дважды not not?

return not not tostring(x):find("^%s*$")
 

fsdfsdfsdfsd1312312312

Новичок
3
0
function sampev.onServerMessage(col, text)
if active and text:match('^SAPD:{FFFFFF} ”ровень преступности в штате составил {FF0000}.*') then
sampSendDialogResponse(966, 1, cline, -1)
sampSendDialogResponse(967, 1, -1, -1)
end
end
За что отвечает эта функция?
 

ShikamaruRU

Участник
55
1
И снова всем бластзакерам привет.

Lua:
function mc()
    lua_thread.create(function ()
    sampSendChat("Здравствуйте, я сотрудник медицинского центра, я так понимаю вам нужна мед.карта. сейчас ее оформим.")
    wait(1000)
    sampSendChat("Не могли бы вы показать свой паспорт,чтобы я смог определить цену. ")
    ...............
    end)
end
В общем. Хочу сделать такую вещь. эти 2 строчки пишутся и далее нужно нажать 1 - отмена отыгровок. 2 - продолжить отыгровки. Как так сделать?)
Здравствуйте, я сотрудник медицинского центра, я так понимаю вам нужна мед.карта. сейчас ее оформим.
Не могли бы вы показать свой паспорт,чтобы я смог определить цену.
(Тут ответ от игрока, т.е эти самые действия 1 - отмена 2 - продолжить)
/me правой рукой берет паспорт и просматривает его,после чего кладет на стойку
Хорошо, для вас медицинская карта обойдётся в сумма$, оплатите и продолжим.
Сейчас скажите ваш рост, вес и немного о своих вредных привычках.
(Тут ответ от игрока, т.е эти самые действия 1 - отмена 2 - продолжить)
/do В правом кармане рубашки находится блокнот и ручка.
/me правой рукой достает блокнот и ручку, после чего открывает его иделает записи
/todo Хорошо, имеются ли у вас аллергические реакции?*смотря на пациента
/todo Я вас понял*делая записи в блокнот
/do На плече висит небольшая сумка с документацией.
/me достает из сумки мед.карту и заполняет содержимое с блокнота и данные паспорта
/me заполнив мед.карту ,убирает блокнот и ручку в карман, подбирает паспорт со стола...
/me ... и передает человеку напротив.
/medcard
 

fsdfsdfsdfsd1312312312

Новичок
3
0
Lua:
function sampev.onShowDialog(id)
    if id == 967 then
        return false
    end
end
А вот это за что?967 я так понимаю,айди диалога,если не найден,то повтора не будет? или шо
 
Последнее редактирование модератором:

trefa

Известный
Всефорумный модератор
2,097
1,231
Lua:
function sampev.onShowDialog(id)
    if id == 967 then
        return false
    end
end
А вот это за что?967 я так понимаю,айди диалога,если не найден,то повтора не будет? или шо
Эта функция так называемый хук, срабатывает тогда когда приходит RPC(пакет данных). Если ид диалога не равен числу "967" то диалог откроется.
 

Михайло

Участник
13
6
Lua:
function mc()
    lua_thread.create(function ()
        sampSendChat("Здравствуйте, я сотрудник медицинского центра, я так понимаю вам нужна мед.карта. сейчас ее оформим.")
        wait(1000)
        sampSendChat("Не могли бы вы показать свой паспорт,чтобы я смог определить цену. ")
        repeat
            if isKeyJustPressed(VK_U) then
                sampAddChatMessage("Прервано", -1)
                return
            end
            wait(0)
        until isKeyJustPressed(VK_Y)

     sampAddChatMessage("продолжение", -1)
    end)
end
Updated
Еще вопрос: как на 100 процентов получить достоверные данные, что игрок заспавнен после логина.

Пакетами PACKET_PLAYER_SYNC пытался, но на аризоне эти пакеты проскакивают при реконекте.
Через LVL игрока со значением 0, такая же херня на аризоне при реконекте остается старый лвл, а потом меняется на ноль, тось тоже проскакивает.
функцией isPlayerSpawned() тоже пытался, но на даймонде она возвращает True в окне логина.
isPlayerPlaying()
 
Последнее редактирование:
  • Нравится
Реакции: ShikamaruRU

ShikamaruRU

Участник
55
1
function mc() lua_thread.create(function () sampSendChat("Здравствуйте, я сотрудник медицинского центра, я так понимаю вам нужна мед.карта. сейчас ее оформим.") wait(1000) sampSendChat("Не могли бы вы показать свой паспорт,чтобы я смог определить цену. ") repeat if isKeyJustPressed(VK_U) then sampAddChatMessage("Прервано", -1) return end until isKeyJustPressed(VK_Y) sampAddChatMessage("продолжение", -1) end) end
Игра вылетает и усе О.о