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

r4nx

Известный
Друг
201
263
Такой вопрос: как из одного скрипта передать переменную, значение которой постоянно меняется, в другой? Пробовал через require - значение первый раз получается, но потом не изменяется (а нужно что менялось). Пробовал и кэш модулей очищать (package.loaded.mymodule = nil) - нифига не пашет. Конечно, можно записывать переменную в файл и читать её, но это совсем зашквар. Есть какое-нибудь решение?
 

k1sher

Известный
201
4
onSendChat(message) - это хук исходящего рпц я так понял. А есть что-то чтоб хукнуть именно то что я отправляют в чат?
 

Moonlight_Ru

Известный
66
21
onSendChat(message) - это хук исходящего рпц я так понял. А есть что-то чтоб хукнуть именно то что я отправляют в чат?
onSendChat(message) - исходящие сообщения в чат, не являющиеся командами (Без /).
onSendCommand(command) - исходящие команды (Все те, которые начинаются с /).

Открывай 'moonloader\\lib\\samp\\events.lua' - по названиям там всё понятно должно быть.
 
  • Нравится
Реакции: k1sher

uryukhai

Активный
196
104
Есть предложения почему не отправляет ответы в чат? ( . - Любой символ)
Код:
require "lib.moonloader"
local hook = require 'lib.samp.events'

function main()
    sendChat = lua_thread.create_suspended(sendChatFunc)
    wait(-1)
end
function hook.onServerMessage(color, text)
    if string.find(text, "^%[AntiAFK%]: {ffffff}%S%Sеди ответ: (%d+).(%d+) = %{ff0000}? %{ffff00}| У тебя есть %d секунд, что бы ответить!$") then
        local num1, num2 = string.match(text, "^%[AntiAFK%]: {ffffff}%S%Sеди ответ: (%d+).(%d+) = %{ff0000}? %{ffff00}| У тебя есть %d секунд, что бы ответить!$")
        answer = tonumber(num1) . tonumber(num2)
        sampSendChat(tostring(answer))
    end
end
 

штейн

Известный
Проверенный
1,003
688
Помогите решить проблему.

Lua:
 while true do
    wait(0)
    resX, resY = getScreenResolution()
           cordX = resX/2+resX/4
           cordY = resY/25
           local _, myid = sampGetPlayerIdByCharHandle(playerPed)
           local ping = sampGetPlayerPing(myid)
           renderFontDrawText(font, "ID: "..myid.." | PING: "..ping, cordX-10, cordY-15, 0xFFFF0000)
        end
    local re, bu, li, inp = sampHasDialogRespond(9904)
    if re and bu == 1 then
        sampShowDialog(9956, "{00cc99} Выдача розыска", nzv2, "{ffffff}Далее", "{ffffff}Закрыть", "", 0)
    end
    local re, bu, li, inp = sampHasDialogRespond(9956)
    if re and bu == 1 then
        sampShowDialog(9957, "{00cc99} Выдача розыска", nzv3, "{ffffff}Закрыть", "", 0)
    end
            if isKeyDown(VK_Y) and not sampIsChatInputActive() and not sampIsDialogActive() and not isPauseMenuActive() then
                res, handle = getCharPlayerIsTargeting(playerHandle)
                if res then
                    resid, Rid = sampGetPlayerIdByCharHandle(handle)
                    Rname = sampGetPlayerNickname(Rid)
                    sampShowDialog(906, string.format("{ffffff}Меню взаимодействия с {00cc99}%s{ffffff}[%d]", Rname, Rid), hmenu, "{ffffff}Далее", "Закрыть", 2)
                    sampAddChatMessage(string.format("{ffffff}Меню взаимодействия с {00cc99}%s{ffffff}[%d]", Rname, Rid), 0xC1C1C1)
                end
            end
        local re, bu, li, inp = sampHasDialogRespond(906)
        if re == true and bu == 1 then
            if li == 0 then sampSendChat(string.format("/arest %d", Rid)) end
            if li == 1 then sampSendChat(string.format("/cuff %d", Rid)) end
            if li == 2 then sampSendChat(string.format("/frisk %d", Rid)) end 
            if li == 3 then sampSendChat(string.format("/findgun %d", Rid)) end
            if li == 4 then sampSendChat(string.format("/invite %d", Rid)) end
            if li == 5 then sampSendChat(string.format("/ud %d", Rid)) end
        end
- Когда я делаю так, то диалоги не работают, а текст драв - работает, если же я опущу текст драв ниже диалогов, то диалоги будут работать, а текст драв нет, на сколько я понимаю, это из-за while true do, но как мне сделать иначе?
 

itsLegend

Фонд борьбы за жуков 🐞
Администратор
2,696
1,468
как мне сделать иначе?
Начать с нормального табулирования, и узнать как обозначается конец цикла. Конец цикла обозначается end'ом (как и другие конструкции в принципе). Этот end у тебя зачесался на 9 строке, а значит после него ничего выполняться не будет.
 

hnnssy

Известный
Друг
2,684
2,762
Помогите решить проблему.

Lua:
 while true do
    wait(0)
    resX, resY = getScreenResolution()
           cordX = resX/2+resX/4
           cordY = resY/25
           local _, myid = sampGetPlayerIdByCharHandle(playerPed)
           local ping = sampGetPlayerPing(myid)
           renderFontDrawText(font, "ID: "..myid.." | PING: "..ping, cordX-10, cordY-15, 0xFFFF0000)
        end
    local re, bu, li, inp = sampHasDialogRespond(9904)
    if re and bu == 1 then
        sampShowDialog(9956, "{00cc99} Выдача розыска", nzv2, "{ffffff}Далее", "{ffffff}Закрыть", "", 0)
    end
    local re, bu, li, inp = sampHasDialogRespond(9956)
    if re and bu == 1 then
        sampShowDialog(9957, "{00cc99} Выдача розыска", nzv3, "{ffffff}Закрыть", "", 0)
    end
            if isKeyDown(VK_Y) and not sampIsChatInputActive() and not sampIsDialogActive() and not isPauseMenuActive() then
                res, handle = getCharPlayerIsTargeting(playerHandle)
                if res then
                    resid, Rid = sampGetPlayerIdByCharHandle(handle)
                    Rname = sampGetPlayerNickname(Rid)
                    sampShowDialog(906, string.format("{ffffff}Меню взаимодействия с {00cc99}%s{ffffff}[%d]", Rname, Rid), hmenu, "{ffffff}Далее", "Закрыть", 2)
                    sampAddChatMessage(string.format("{ffffff}Меню взаимодействия с {00cc99}%s{ffffff}[%d]", Rname, Rid), 0xC1C1C1)
                end
            end
        local re, bu, li, inp = sampHasDialogRespond(906)
        if re == true and bu == 1 then
            if li == 0 then sampSendChat(string.format("/arest %d", Rid)) end
            if li == 1 then sampSendChat(string.format("/cuff %d", Rid)) end
            if li == 2 then sampSendChat(string.format("/frisk %d", Rid)) end
            if li == 3 then sampSendChat(string.format("/findgun %d", Rid)) end
            if li == 4 then sampSendChat(string.format("/invite %d", Rid)) end
            if li == 5 then sampSendChat(string.format("/ud %d", Rid)) end
        end
- Когда я делаю так, то диалоги не работают, а текст драв - работает, если же я опущу текст драв ниже диалогов, то диалоги будут работать, а текст драв нет, на сколько я понимаю, это из-за while true do, но как мне сделать иначе?
всё в один цикл либо подключить второй поток
 

штейн

Известный
Проверенный
1,003
688
Начать с нормального табулирования, и узнать как обозначается конец цикла. Конец цикла обозначается end'ом (как и другие конструкции в принципе). Этот end у тебя зачесался на 9 строке, а значит после него ничего выполняться не будет.
я чего-то не понимаю, я уже пробовал убирать end, но как и ожидалось скрипт просто не запускался, если я что-то не так понял, уточни пожалуйста.
 

hnnssy

Известный
Друг
2,684
2,762
я чего-то не понимаю, я уже пробовал убирать end, но как и ожидалось скрипт просто не запускался, если я что-то не так понял, уточни пожалуйста.
у тебя цикл
Lua:
while true do
    wait(0)
    resX, resY = getScreenResolution()
           cordX = resX/2+resX/4
           cordY = resY/25
           local _, myid = sampGetPlayerIdByCharHandle(playerPed)
           local ping = sampGetPlayerPing(myid)
           renderFontDrawText(font, "ID: "..myid.." | PING: "..ping, cordX-10, cordY-15, 0xFFFF0000)
        end
дальше него работа скрипта уйти не может попросту, тебе нужно в этом цикле уместить весь рабочий код
 
  • Нравится
Реакции: штейн и imring

Alfinity

Известный
94
53
Пишу простенький FlyCam (возможность летать камерой). Но позиция камеры упорно не хочет меняться ( setFixedCameraPosition() ). Добрые люди подсказали ф-цию setCameraPositionUnfixed(), но я не допёр что в нее передавать. Помогите заставить камеру подчиняться, пожалуйста :)
 
  • Нравится
Реакции: Ya Zaregalsya

kraft1k

Вынь х*й из головы и все получится © hnnssy
Друг
1,480
1,168
Почему не блокируется?
Lua:
local sampev = require "samp.events"

function sampev.onApplyPlayerAnimation(playerId, _, animName, _, _, _, _, _)
    myid = sampGetPlayerIdByCharHandle(playerPed)
    if playerId == myid and animName == "GYM_TREAD_FALLOFF" then
        return false
    end
end
 

mrdiimax

Известный
566
79
Как делать такое гуи? (Ссылки если можно)
Jbnz68JV0Sqz0iJB7dIYOk4ixS2wTnXxpuC4Oj0GWjgEHPVV_YoBJZy-5H_LgtmUvCLe7x-mBitmpaJ79CL2HQ%3D%3D