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

wulfandr

Известный
636
260
Lua:
    while not isSampAvailable() do wait(100) end
    while true do
        wait(0)
        while isKeyDown(VK_Z) and not sampIsChatInputActive() and not sampIsDialogActive() do
            wait(0)
            for k,v in ipairs(getAllChars()) do
                local posX, posY, posZ = getCharCoordinates(v)
                local pPosX, pPosY, pPosZ = getCharCoordinates(playerPed)
                if getDistanceBetweenCoords3d(posX, posY, posZ, pPosX, pPosY, pPosZ) <= 180.0 then
                    local wPosX, wPosY = convert3DCoordsToScreen(posX, posY, posZ)
                    res, id = sampGetPlayerIdByCharHandle(v)
                    if res then
                        renderDrawBoxWithBorder(wPosX - 65 / 2, wPosY - 60, 65, 120, 0x00FFFFFF, 2, 0xFF00FF00)
                    end
                end
            end
        end
    end
end
Как можно сделать кнопку активации по выбору в игре?
у тебя подпись не правильная, перед форматом текста нужно поставить f перед ковычками
 
  • Ха-ха
Реакции: Eugene Crabs и Akionka

Next..

Известный
343
136
Lua:
    while not isSampAvailable() do wait(100) end
    while true do
        wait(0)
        while isKeyDown(VK_Z) and not sampIsChatInputActive() and not sampIsDialogActive() do
            wait(0)
            for k,v in ipairs(getAllChars()) do
                local posX, posY, posZ = getCharCoordinates(v)
                local pPosX, pPosY, pPosZ = getCharCoordinates(playerPed)
                if getDistanceBetweenCoords3d(posX, posY, posZ, pPosX, pPosY, pPosZ) <= 180.0 then
                    local wPosX, wPosY = convert3DCoordsToScreen(posX, posY, posZ)
                    res, id = sampGetPlayerIdByCharHandle(v)
                    if res then
                        renderDrawBoxWithBorder(wPosX - 65 / 2, wPosY - 60, 65, 120, 0x00FFFFFF, 2, 0xFF00FF00)
                    end
                end
            end
        end
    end
end
Как можно сделать кнопку активации по выбору в игре?
 

shinoa

Известный
297
206
Есть ли у кого готовая функция для проверки находится ли игрок внутри координат? (не через радиус от центра, а внутри "фигуры", которая составлена из 4+ координат)
 

wulfandr

Известный
636
260
Есть ли у кого готовая функция для проверки находится ли игрок внутри координат? (не через радиус от центра, а внутри "фигуры", которая составлена из 4+ координат)
Внутри каких координат? Минимум 4 координаты нужно, иначе как узнать какая область вас интересует
 

kin4stat

mq-team · kin4@naebalovo.team
Всефорумный модератор
2,744
4,806
Чтобы область можно было задать из четырех и более координат
 
  • Нравится
Реакции: Eugene Crabs

BARRY BRADLEY

Известный
711
176
Есть ли у кого готовая функция для проверки находится ли игрок внутри координат? (не через радиус от центра, а внутри "фигуры", которая составлена из 4+ координат)
 
  • Нравится
Реакции: PoundFoolish

PoundFoolish

Участник
81
1
Как оформить подтверждение по нажатию клавиши? Тут не работает.
Еще проблема, если он находит в чате слово определенное - реагирует, но как только находит слово в другом любом чате (допустим в /f), то перестает работать скрипт, help!
Lua:
local vk = require "vkeys"
local se = require "lib.samp.events"
local timer = 0
local mat = {"блять"}

function main()
   while not isSampAvailable() do
        wait(0)
    end
   while true do wait(0)
      if searchMat then
         local tick = os.clock() * 1000
         if tick - timer > 30 * 1000 then -- Время на ответ 30 сек, если больше то удаляем ник и выключаем кнопки
          searchMat = false
          playerNameMat = nil
         end
        if isKeyCheckAvailable() then
           -- Кнопка для отмены
            if isKeyJustPressed(vk.VK_ESCAPE) then
               searchMat = false
              playerNameMat = nil
               sampAddChatMessage("Вы отменили мут", -1)
           -- Кнопка для мута
            elseif isKeyJustPressed(vk.VK_RETURN) then
               if playerNameMat then
                 sampSendChat("/mute "..playerNameMat.." 30 мат") -- Мутим
               end
            end
        end
     end
   end
end


---В этом поиске---
  --if text:find("") then
    --  local name, text = text:match("")

---local message, nick, id = text:match("- (.+) %((.+)%)%[(%d+)%]")

-- events не забудь подключить
function se.onServerMessage(color, text)
   local message, nick = text:match('- (.*) ((.*))$')
   for key, val in pairs(mat) do
      if string.lower(text):find(val) then
         sampAddChatMessage('Тут матюкнулися. Его ник: '..nick..'. Он написал запрещённое слово: '..val, -1)
      end
   end
end

-- Проверка на открытие диалога и консоли сампфункс, а так же чата
function isKeyCheckAvailable()
    if not isSampLoaded() then
        return true
    end
    if not isSampfuncsLoaded() then
        return not sampIsChatInputActive() and not sampIsDialogActive()
    end
    return not sampIsChatInputActive() and not sampIsDialogActive() and not isSampfuncsConsoleActive()
end
 

BARRY BRADLEY

Известный
711
176
[
Как оформить подтверждение по нажатию клавиши? Тут не работает.
Еще проблема, если он находит в чате слово определенное - реагирует, но как только находит слово в другом любом чате (допустим в /f), то перестает работать скрипт, help!
Lua:
local vk = require "vkeys"
local se = require "lib.samp.events"
local timer = 0
local mat = {"блять"}

function main()
   while not isSampAvailable() do
        wait(0)
    end
   while true do wait(0)
      if searchMat then
         local tick = os.clock() * 1000
         if tick - timer > 30 * 1000 then -- Время на ответ 30 сек, если больше то удаляем ник и выключаем кнопки
          searchMat = false
          playerNameMat = nil
         end
        if isKeyCheckAvailable() then
           -- Кнопка для отмены
            if isKeyJustPressed(vk.VK_ESCAPE) then
               searchMat = false
              playerNameMat = nil
               sampAddChatMessage("Вы отменили мут", -1)
           -- Кнопка для мута
            elseif isKeyJustPressed(vk.VK_RETURN) then
               if playerNameMat then
                 sampSendChat("/mute "..playerNameMat.." 30 мат") -- Мутим
               end
            end
        end
     end
   end
end


---В этом поиске---
  --if text:find("") then
    --  local name, text = text:match("")

---local message, nick, id = text:match("- (.+) %((.+)%)%[(%d+)%]")

-- events не забудь подключить
function se.onServerMessage(color, text)
   local message, nick = text:match('- (.*) ((.*))$')
   for key, val in pairs(mat) do
      if string.lower(text):find(val) then
         sampAddChatMessage('Тут матюкнулися. Его ник: '..nick..'. Он написал запрещённое слово: '..val, -1)
      end
   end
end

-- Проверка на открытие диалога и консоли сампфункс, а так же чата
function isKeyCheckAvailable()
    if not isSampLoaded() then
        return true
    end
    if not isSampfuncsLoaded() then
        return not sampIsChatInputActive() and not sampIsDialogActive()
    end
    return not sampIsChatInputActive() and not sampIsDialogActive() and not isSampfuncsConsoleActive()
end
Оно и не будет работать ибо ты не активировал searchMat = trueи не обновил таймер timer = os.clock() * 1000 когда нашел строку
Внимательно код смотри:
 
Последнее редактирование:
  • Нравится
Реакции: PoundFoolish

Tristan

Участник
43
0
В чем тут проблема? Я нажимаю на F4, после пишется команда, а дальше просто стоит, хотя должно нажать на Энтер.


Lua:
        if wasKeyPressed(115) then
    sampSendChat("/taxilist")
    if sampIsDialogActive() then
    wait(500)
    setVirtualKeyDown(13,true)
    wait(100)
    setVirtualKeyDown(13,false)
    end
    end
 

Eugene Crabs

Активный
544
30
В чем тут проблема? Я нажимаю на F4, после пишется команда, а дальше просто стоит, хотя должно нажать на Энтер.


Lua:
        if wasKeyPressed(115) then
    sampSendChat("/taxilist")
    if sampIsDialogActive() then
    wait(500)
    setVirtualKeyDown(13,true)
    wait(100)
    setVirtualKeyDown(13,false)
    end
    end
После ввода команды попробуй поставить задержку. Ну или проверяй в while'е, пока диалог не появится
 
  • Нравится
Реакции: Tristan

Quasper

Известный
835
354
В чем тут проблема? Я нажимаю на F4, после пишется команда, а дальше просто стоит, хотя должно нажать на Энтер.


Lua:
        if wasKeyPressed(115) then
    sampSendChat("/taxilist")
    if sampIsDialogActive() then
    wait(500)
    setVirtualKeyDown(13,true)
    wait(100)
    setVirtualKeyDown(13,false)
    end
    end
потому что диалог не приходит от сервера моментально, нужно подождать некоторое время пока он не появится
Lua:
if wasKeyPressed(115) then
    sampSendChat("/taxilist")
    while not sampIsDialogActive() do --тут собственно и ждём появление диалога, после  появления цикл прекратится
        wait(100)
    end
    setVirtualKeyDown(13, true) -- после появление прожимаем ентер
    wait(100)
    setVirtualKeyDown(13, false)
end
 
  • Нравится
Реакции: Tristan и Eugene Crabs

Eugene Crabs

Активный
544
30
потому что диалог не приходит от сервера моментально, нужно подождать некоторое время пока он не появится
Lua:
if wasKeyPressed(115) then
    sampSendChat("/taxilist")
    while not sampIsDialogActive() do --тут собственно и ждём появление диалога, после  появления цикл прекратится
        wait(100)
    end
    setVirtualKeyDown(13, true) -- после появление прожимаем ентер
    wait(100)
    setVirtualKeyDown(13, false)
end
О, может у тебя еще опыт перейму. Из таблицы Excel как-нибудь можно достать/записать данные в определенную ячейку? (На подобии массива, print(Mass[1][1]); Mass[1][1] = 1 и т.д.)

p.s. Со JSON разбираюсь, небеспокойтесь