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

itsLegend

Фонд борьбы за жуков 🐞
Администратор
2,695
1,448
Lua:
setVirtualKeyDown(--[[int]] vkey, --[[bool]] down)  -- 0C72
 
  • Нравится
Реакции: CAPTA!N

CAPTA!N

Новичок
220
49
Lua:
setVirtualKeyDown(--[[int]] vkey, --[[bool]] down)  -- 0C72
да-да, уже нашел, спасибо

Короч я хз ваще как мне это время получить. Мне хэннеси сказали что вот этот рпц RPC_UpdateSystemTime, но с ним нихрена не выходит. Насколько я понимаю из кода мунмода, там нужно ставить рпц, которые капсом написаны:
Lua:
if id == RPC_SCRWORLDVEHICLEADD then
        local id = raknetBitStreamReadInt16(bs)
        VehiclePool[id] = {gtaid = nil}
    elseif id == RPC_SCRWORLDVEHICLEREMOVE then
        local id = raknetBitStreamReadInt16(bs)
        VehiclePool[id] = nil
    end
Вот мой код, который сделан для теста, что бы проверить получаю ли я его. Но нет, не получаю.
Lua:
function onReceiveRpc(id, bs)
    if id == RPC_UpdateSystemTime then
        sampAddChatMessage("RPC_UpdateSystemTime", 0xFFFFFF)
    end

И еще вопрос. Я хочу заменить все приходящие строки чата своими. Я не пойму как
 
Последнее редактирование модератором:

RollUp

Участник
52
38
Как получить хп игрока, если они больше чем 100? Например 160
 

nname

Новичок
66
5
Как сделать, чтобы хп(в цифрах) игрока(не нашего персонажа) всегда было там же где и его полоска хп? Есть скрипт, показывающий его хп, но только место выбираешь ты и оно не меняется, а нужно чтобы оно было над его ХП
 

CAPTA!N

Новичок
220
49
Ребят, я знаю, я уже заебал, но все равно не могу понять как правильно сделать
да-да, уже нашел, спасибо

Короч я хз ваще как мне это время получить. Мне хэннеси сказали что вот этот рпц RPC_UpdateSystemTime, но с ним нихрена не выходит. Насколько я понимаю из кода мунмода, там нужно ставить рпц, которые капсом написаны:
Lua:
if id == RPC_SCRWORLDVEHICLEADD then
        local id = raknetBitStreamReadInt16(bs)
        VehiclePool[id] = {gtaid = nil}
    elseif id == RPC_SCRWORLDVEHICLEREMOVE then
        local id = raknetBitStreamReadInt16(bs)
        VehiclePool[id] = nil
    end
Вот мой код, который сделан для теста, что бы проверить получаю ли я его. Но нет, не получаю.
Lua:
function onReceiveRpc(id, bs)
    if id == RPC_UpdateSystemTime then
        sampAddChatMessage("RPC_UpdateSystemTime", 0xFFFFFF)
    end

И еще вопрос. Я хочу заменить все приходящие строки чата своими. Я не пойму как
 

FYP

Известный
Автор темы
Администратор
1,758
5,718
Короч я хз ваще как мне это время получить. Мне хэннеси сказали что вот этот рпц RPC_UpdateSystemTime, но с ним нихрена не выходит. Насколько я понимаю из кода мунмода, там нужно ставить рпц, которые капсом написаны:
Lua:
if id == RPC_SCRWORLDVEHICLEADD then
        local id = raknetBitStreamReadInt16(bs)
        VehiclePool[id] = {gtaid = nil}
    elseif id == RPC_SCRWORLDVEHICLEREMOVE then
        local id = raknetBitStreamReadInt16(bs)
        VehiclePool[id] = nil
    end
Вот мой код, который сделан для теста, что бы проверить получаю ли я его. Но нет, не получаю.
Lua:
function onReceiveRpc(id, bs)
    if id == RPC_UpdateSystemTime then
        sampAddChatMessage("RPC_UpdateSystemTime", 0xFFFFFF)
    end
все эти RPC, которые ты нашёл в мунмоде находятся в файле lib/sampfuncs.lua, но RPC_UpdateSystemTime почему-то туда не попал. в своём скрипте можно фильтровать его указав ид.
Lua:
RPC_UpdateSystemTime = 60

function onReceiveRpc(id, bs)
    if id == RPC_UpdateSystemTime then
        sampAddChatMessage("RPC_UpdateSystemTime", 0xFFFFFF)
    end
end
И еще вопрос. Я хочу заменить все приходящие строки чата своими. Я не пойму как
фильтровать RPC_CHAT и RPC_SCRCLIENTMESSAGE, затем перезаписывать входящий битстрим нужными данными. можно и иначе - ловить эти RPC и добавлять в очередь, а затем в основном потоке заменять значения функцией sampSetChatString.
 
  • Нравится
Реакции: CAPTA!N

CAPTA!N

Новичок
220
49
все эти RPC, которые ты нашёл в мунмоде находятся в файле lib/sampfuncs.lua, но RPC_UpdateSystemTime почему-то туда не попал. в своём скрипте можно фильтровать его указав ид.
Lua:
RPC_UpdateSystemTime = 60

function onReceiveRpc(id, bs)
    if id == RPC_UpdateSystemTime then
        sampAddChatMessage("RPC_UpdateSystemTime", 0xFFFFFF)
    end
end

фильтровать RPC_CHAT и RPC_SCRCLIENTMESSAGE, затем перезаписывать входящий битстрим нужными данными. можно и иначе - ловить эти RPC и добавлять в очередь, а затем в основном потоке заменять значения функцией sampSetChatString.
Значит попробовал я и то и другое. Код первого:
Lua:
if id == 60 then
        local timems = raknetBitStreamReadInt32(bs)
        sampAddChatMessage(string.format("%i", timems), 0xFFFFFF)
    end
На момент проверки выводило число 65563839. Если перевести в часы, то получаем 18 часов с копейками. Но на сервере 22. Мне кажется что этот рпц - это время от перезагрузки сервера, потому что рестарт у нас в 4, и если прибавить еще 18 получиться 22. А мне же нужно время, которое показывается при /time.

На счет второго. Просто не работает, не знаю в чем проблема :с Вынес я в отдельную функцию, потому что структура у них одинаковая, только битстрим разный. Если что, то я пытался и без выноса в отдельную функцию
Lua:
function onReceiveRpc(id, bs)
    if id == RPC_CHAT then
        processChat(bs)
    end
    if id == RPC_SCRCLIENTMESSAGE then
        processChat(bs)
    end
end

function processChat(bs)
    local colorORid = raknetBitStreamReadInt16(bs) -- читаю не нужные числа, потому что где то
    local strlen = raknetBitStreamReadInt8(bs) -- слышал что нучжно считывать или записывать
    local text = raknetBitStreamReadString(bs, strlen) -- (точно не помню) по порядку
    local id = nil
    for id = 0, 1000 do
        if sampIsPlayerConnected(id) then
            local nick = sampGetPlayerNickname(id)
            if string.match(text, nick) ~= nil then
                local text = string.gsub(text, nick, string.format("%s[%i]", nick, id))
            end
        end
    end
    raknetBitStreamWriteInt16(bs, colorORid)
    raknetBitStreamWriteInt8(bs, strlen)
    raknetBitStreamWriteString(bs, text)
end
 

FYP

Известный
Автор темы
Администратор
1,758
5,718

FYP

Известный
Автор темы
Администратор
1,758
5,718
На момент проверки выводило число 65563839. Если перевести в часы, то получаем 18 часов с копейками. Но на сервере 22. Мне кажется что этот рпц - это время от перезагрузки сервера, потому что рестарт у нас в 4, и если прибавить еще 18 получиться 22. А мне же нужно время, которое показывается при /time.
так и есть, в linux это время с момента запуска сервера, в windows с момента запуска системы. и оно в миллисекундах. а время, которое в /time, кроме как отправкой команды /time никак не получишь. так что вот. у тебя есть время работы сервера в миллисекундах, время в /time и своё системное время, дальше уже вертись как хочешь.
такое уже делали.
На счет второго. Просто не работает, не знаю в чем проблема :с Вынес я в отдельную функцию, потому что структура у них одинаковая, только битстрим разный. Если что, то я пытался и без выноса в отдельную функцию
а require('lib.sampfuncs') то сделал?
 
  • Нравится
Реакции: 4el0ve4ik

CAPTA!N

Новичок
220
49
так и есть, в linux это время с момента запуска сервера, в windows с момента запуска системы. и оно в миллисекундах. а время, которое в /time, кроме как отправкой команды /time никак не получишь. так что вот. у тебя есть время работы сервера в миллисекундах, время в /time и своё системное время, дальше уже вертись как хочешь.
такое уже делали.

а require('lib.sampfuncs') то сделал?
есть
 

RedBoxWhite

Известный
337
27
Что не так? Диалог получает, но не ищет строку
Lua:
function main()
    if not isSampfuncsLoaded() or not isSampLoaded() then return end
    while true do
    wait(0)
        if sampIsDialogActive() then
        local dialog = sampGetDialogText()
            if string.find(dialog, "Ваш логин") then
            sampSetCurrentDialogEditboxText("123")
            sampCloseCurrentDialogWithButton(1)
            end
        end
    end
end
 
  • Нравится
Реакции: Jason2222

FYP

Известный
Автор темы
Администратор
1,758
5,718
у этих rpc разная структура.
для перезаписи битстрима нужно перед записью задать оффсет для записи - raknetBitStreamSetWriteOffset.
и вместо string.match в этом случае лучше бы использовать string.find.
@RedBoxWhite наверно не та кодировка.
 
  • Нравится
Реакции: CAPTA!N и RedBoxWhite