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

News

Новичок
4
3
Всем добрый день, прошу вашей помощи
Перейду сразу к сути, мне надо сделать скрипт что бы он флудил клавишу N, до того момента как появится диалог
local state = false

function main()
while not isSampAvailable() do wait(0) end
while true do
wait(0)
if isKeyDown(0x10) and isKeyJustPressed(0x4E) then state = not state end
if state then
if sampisDialogActive then
state = false
else
math.randomseed(os.clock())
local delay = math.random(100, 1000) --от 100мс до 1000мс
setVirtualKeyDown(78, true)
wait(delay)
setVirtualKeyDown(78, false)
wait(delay)
end
end
end
end

вроде набросал небольшой код, но он не работает, даже когда диалог появляется скрипт все равно флудит клавишу n, желательно что бы скрипт вырубался после появления диалога, надеюсь кто то сможет помочь:)
 

Вложения

  • n.lua
    515 байт · Просмотры: 1

P U L V I L I Z A T O R

Участник
94
29
Всем добрый день, прошу вашей помощи
Перейду сразу к сути, мне надо сделать скрипт что бы он флудил клавишу N, до того момента как появится диалог
local state = false

function main()
while not isSampAvailable() do wait(0) end
while true do
wait(0)
if isKeyDown(0x10) and isKeyJustPressed(0x4E) then state = not state end
if state then
if sampisDialogActive then
state = false
else
math.randomseed(os.clock())
local delay = math.random(100, 1000) --от 100мс до 1000мс
setVirtualKeyDown(78, true)
wait(delay)
setVirtualKeyDown(78, false)
wait(delay)
end
end
end
end

вроде набросал небольшой код, но он не работает, даже когда диалог появляется скрипт все равно флудит клавишу n, желательно что бы скрипт вырубался после появления диалога, надеюсь кто то сможет помочь:)
У тебя sampIsDialogActive не вызывается как функция sampIsDialogActive()
 
  • Нравится
Реакции: News

nelit.dev

Участник
69
36
Использую отправку ассинхронного запроса по этому гайду - https://www.blast.hk/threads/20532/page-3#post-256096

не совсем понимаю как для метода POST передать тело запроса?

Lua:
function get()
    sampAddChatMessage("Ассинхронный запрос", -1)
    asyncHttpRequest('GET', 'https://www.google.com/robots.txt', nil, function(response)
       print(response.text)
    end,
    function(err)
        --
    end)
end

function asyncHttpRequest(method, url, args, resolve, reject)
    local request_thread = effil.thread(function (method, url, args)
       local requests = require 'requests'
       local result, response = pcall(requests.request, method, url, args)
       if result then
          response.json, response.xml = nil, nil
          return true, response
       else
          return false, response
       end
    end)(method, url, args)
    -- Если запрос без функций обработки ответа и ошибок.
    if not resolve then resolve = function() end end
    if not reject then reject = function() end end
    -- Проверка выполнения потока
    lua_thread.create(function()
       local runner = request_thread
       while true do
          local status, err = runner:status()
          if not err then
             if status == 'completed' then
                local result, response = runner:get()
                if result then
                   resolve(response)
                else
                   reject(response)
                end
                return
             elseif status == 'canceled' then
                return reject(status)
             end
          else
             return reject(err)
          end
          wait(0)
       end
    end)
end
 

P U L V I L I Z A T O R

Участник
94
29
Использую отправку ассинхронного запроса по этому гайду - https://www.blast.hk/threads/20532/page-3#post-256096

не совсем понимаю как для метода POST передать тело запроса?

Lua:
function get()
    sampAddChatMessage("Ассинхронный запрос", -1)
    asyncHttpRequest('GET', 'https://www.google.com/robots.txt', nil, function(response)
       print(response.text)
    end,
    function(err)
        --
    end)
end

function asyncHttpRequest(method, url, args, resolve, reject)
    local request_thread = effil.thread(function (method, url, args)
       local requests = require 'requests'
       local result, response = pcall(requests.request, method, url, args)
       if result then
          response.json, response.xml = nil, nil
          return true, response
       else
          return false, response
       end
    end)(method, url, args)
    -- Если запрос без функций обработки ответа и ошибок.
    if not resolve then resolve = function() end end
    if not reject then reject = function() end end
    -- Проверка выполнения потока
    lua_thread.create(function()
       local runner = request_thread
       while true do
          local status, err = runner:status()
          if not err then
             if status == 'completed' then
                local result, response = runner:get()
                if result then
                   resolve(response)
                else
                   reject(response)
                end
                return
             elseif status == 'canceled' then
                return reject(status)
             end
          else
             return reject(err)
          end
          wait(0)
       end
    end)
end
В описании либы на гите используется такой подход. В твоем случае наверное туда где args надо вставить { data = "data" } объект и название метода на POST указать понятное дело.

Lua:
 response = requests.post('http://httpbin.org/post', {data = 'random data'})
 
  • Нравится
Реакции: nelit.dev

0x73616D

Активный
140
42
What's wrong? that dont work.
Lua:
if enabled and isCharInAnyCar(PLAYER_PED) and not isCharOnAnyBike(PLAYER_PED) then
    ffi.cdef("void __thiscall CDamageManagerSetLightStatus(void* this, int light, unsigned int status);")
    local CDamageManagerSetLightStatus = ffi.cast("void* (__thiscall *)(void*, int, unsigned int)", 0x6C2100)
    CDamageManagerSetLightStatus(ffi.cast("void*", getCarPointer(storeCarCharIsInNoSave(PLAYER_PED))), 0, 1)
    CDamageManagerSetLightStatus(ffi.cast("void*", getCarPointer(storeCarCharIsInNoSave(PLAYER_PED))), 1, 1)
    CDamageManagerSetLightStatus(ffi.cast("void*", getCarPointer(storeCarCharIsInNoSave(PLAYER_PED))), 3, 1)
end
 

nelit.dev

Участник
69
36
научите пожалуйста питониста отправлять на сервер запросы с луа. пытался отправлять таблицу без encodeJson, но на сервере ловлю код 422
"POST /api/users/create/ HTTP/1.1" 422 Unprocessable Entity

Lua:
require "lib.moonloader"

local effil = require "effil"

function asyncHttpRequest(method, url, args, resolve, reject)
   local request_thread = effil.thread(function (method, url, args)
      local requests = require 'requests'
      local result, response = pcall(requests.request, method, url, args)
      if result then
         response.json, response.xml = nil, nil
         return true, response
      else
         return false, response
      end
   end)(method, url, args)
    -- Если запрос без функций обработки ответа и ошибок.
   if not resolve then resolve = function() end end
   if not reject then reject = function() end end
    -- Проверка выполнения потока
   lua_thread.create(function()
      local runner = request_thread
      while true do
         local status, err = runner:status()
         if not err then
            if status == 'completed' then
               local result, response = runner:get()
               if result then
                  resolve(response)
               else
                  reject(response)
               end
               return
            elseif status == 'canceled' then
               return reject(status)
            end
         else
            return reject(err)
         end
         wait(0)
      end
   end)
end

function main()
   if not isSampLoaded() or not isSampfuncsLoaded() then return end
   while not isSampAvailable() do wait(100) end

   -- wait(1000)
   sampAddChatMessage("{57BB74}" .. thisScript().name .. " ver " .. thisScript().version .. " {FFFFFF}загружен. Главное меню: {57BB74}/sa", -1)

   sampRegisterChatCommand("reg", function(data)
      local username, password = string.match(data, "(%S+)%s+(%S+)")
      sampAddChatMessage("{57BB74}" .. thisScript().name .. " " .. username .. " " .. password, -1)
      
      if username ~= nil and password ~= nil then
         local data = {
            username = username,
            password = password
         }
         local json_data = encodeJson(data)
         local response = encodeJson({ body = json_data, headers = {["Content-Type"] = "application/json"}})

         sampAddChatMessage("{57BB74}" .. thisScript().name .. " запрос отправлен!", -1)
         asyncHttpRequest("POST", "http://10.10.10.10:8080/api/users/create/", response,
            function(success_response)
               print(success_response.body)
            end,
            function(error_response)
               print(error_response)
            end
         )
      else
         sampAddChatMessage("{57BB74}" .. thisScript().name .. " {FFFFFF}Используйте {57BB74}/reg [Логин] [Пароль]", -1)
      end
   end)

   while true do
      wait(0)
   end
end

на сервере написал чёто такое, но в случае отправки json таблицы даже не доходит до выполнения проверки. запрос падает сразу как сервер на понимает, что не получил нужные ему данные.

Python:
@app.post("/api/users/create/")
async def create_user(data=Body()):
    print(data)

    username = data.get("username")
    password = data.get("password")

    if username and password:
        print(username)
        print(password)
        return JSONResponse({"message": "Успешно!"})
    else:
        return JSONResponse({"error": "Неверные данные"}, status_code=422)
 

Milukation

Участник
46
10
Люди, мне нужно увеличить imgui.InputTextMultiline, но не в ширину.
(С imgui.ImVec2 тоже не сработает скрипт выдает ошибку)
Lua:
imgui.PushItemWidth(250 * MONET_DPI_SCALE)
if imgui.InputTextMultiline("##MyMultilineInput", zapiska) then
end
 

MLycoris

На вид оружие массового семяизвержения
Проверенный
1,992
2,186
Люди, мне нужно увеличить imgui.InputTextMultiline, но не в ширину.
(С imgui.ImVec2 тоже не сработает скрипт выдает ошибку)
Lua:
imgui.PushItemWidth(250 * MONET_DPI_SCALE)
if imgui.InputTextMultiline("##MyMultilineInput", zapiska) then
end
Код:
imgui.InputTextMultiline("##MyMultilineInput", zapiska,512,imgui.ImVec2(100,150))
 
  • Нравится
Реакции: Milukation

Дядя Энрик.

Активный
337
81
каким образом можно получить вторую строчку от первой? Видел я уже где-то на BH подобный вопрос, но не могу найти.
Lua:
Игрок сказал: аааааааааааааааааааааааааааааааааааа... -- эту строчку можно получить
...аааааааааааааааа --а как получить эту строчку от первой?
 

Milukation

Участник
46
10
Люди, я видел в палатке луа есть функция которая сканирует средние цены на сайте, и средние цены перемещаются в скрипт. Кто-нибудь знает как это сделать с любым сайтом?
 

nelit.dev

Участник
69
36
Люди, я видел в палатке луа есть функция которая сканирует средние цены на сайте, и средние цены перемещаются в скрипт. Кто-нибудь знает как это сделать с любым сайтом?
парсишь сайт луашником. ну или можешь написать на условном питоне парсер и записывать в бд. а с луа посылать гет запросы на получение цены
 
  • Нравится
Реакции: Milukation

nelit.dev

Участник
69
36
А как гет запросы отправлять?
пишешь например на питоне сервер. на форуме есть тема с ассинхронными запросами. на сервере пишешь подключение к бд и получение из неё данных. возвращаешь джсоном данные. с луа отправляешь функцией ассинхронные запрос гет на тот эндпоинт, который ты написал на сервере. вот моя тема, там я прошу помощи с пост запросом. но на форуме есть тема с гет. поищи

 
  • Нравится
Реакции: Milukation

Milukation

Участник
46
10
пишешь например на питоне сервер. на форуме есть тема с ассинхронными запросами. на сервере пишешь подключение к бд и получение из неё данных. возвращаешь джсоном данные. с луа отправляешь функцией ассинхронные запрос гет на тот эндпоинт, который ты написал на сервере. вот моя тема, там я прошу помощи с пост запросом. но на форуме есть тема с гет. поищи

Стоп стоп стоп, что за сервер? Нужно будет платить за него? Все остальное я понял.
 

nelit.dev

Участник
69
36
Стоп стоп стоп, что за сервер? Нужно будет платить за него? Все остальное я понял.
помимо скрипта ты должен написать ещё и сервер для него. покупаешь какую-то вдску (я системный администратор, у меня физические сервера свои есть. тебе вероятно надо будет купить вдску). ставишь убунту, питон. пишешь на питоне сервер. юзаешь условный Джанго, фастапи или фласк. пишешь нужные тебе эндпоинты и для них нужную логику.

пример:
в скрипте две формы и кнопка. юзер заполнил данные. кидаешь ассинхронный пост запрос с введёнными данными на сервер. представим что у нас эндпоинт /api/user_create/. ловишь питоном запрос. из тела запроса достаешь данные и делаешь с ними какое-то взаимодействие. например запись в базу данных.

ну или сделай проще. в самом скрипте напиши парсер. но как по мне так неинтересно)
 
  • Нравится
Реакции: Milukation