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

EndoHokage

Активный
136
55
Если я onShowDialog верну false, то диалог вообще не появится или покажется но скрытым( он как бы показался но мы его не видим )
 

Limonchek

Участник
85
7
Lua:
activate = false

function main()
    if not isSampfuncsLoaded() or not isSampLoaded() then return end
    while not isSampAvailable() do wait(100) end
    sampRegisterChatCommand("stop/start", function()
        activate = not activate
        if activate then
       thisScript():pause()
       sampAddChatMessage("Скрипт на паузе!", -1)
    elseif not activate then
       thisScript():resume()
       sampAddChatMessage("Скрипт снят с паузы!", -1)
    end
    end)
    sampRegisterChatCommand('dell', dell)
    wait(-1)
end

function dell()
      sampSendChat("проверка")
end
Неа, /dell работает даже при паузе скрипта.
 

Limonchek

Участник
85
7
объясни суть скрипта перепишу сделаю нормально
Вообщем. Если я ввожу: /stop/start - Скрипт ставился на паузу *Функции никакие не работали.* Если я ввожу опять /stop/start скрипт снимается с паузы, и остальные функции такие как: /dell - sampSendChat("Проверка") начинают работать.. Если скрипт на паузе аналогично эти функции не работают.
 

xdswd

Известный
365
252
Привет.
Хочу сделать чтобы скрипт брал айпи юзера с сайта, и отправлял его в телеграм, мучаюсь уже час, никак не могу разобраться.


4:
local send = ('https://api.telegram.org/bot' .. token .. '/sendMessage?chat_id=' .. chatid .. '&text=' ) -- токен и чатId указаны

function telegram_send()
    asyncHttpRequest('GET', AnsiToUtf8(send..'IP: '..getIp()))
end

function getIp() -- get user ip
    ip = asyncHttpRequest('GET', 'https://api.ipify.org/?format=json')
    return ip:match('{\"ip\":\"(.*)\"}')
end

Error:
[ML] (error) getIP.lua: D:\GTA\moonloader\getIP.lua:9: attempt to concatenate global 'ip' (a nil value)
stack traceback:
    D:\GTA\moonloader\getIP.lua:9: in function <D:\GTA\moonloader\getIP.lua:8>
[ML] (error) getIP.lua: Script died due to an error. (0B1DEFDC)
 

cheremuxa

Известный
430
200
Получается что даже после false, нам нужно дополнительно закрывать его командой?
не помню
Привет.
Хочу сделать чтобы скрипт брал айпи юзера с сайта, и отправлял его в телеграм, мучаюсь уже час, никак не могу разобраться.


4:
local send = ('https://api.telegram.org/bot' .. token .. '/sendMessage?chat_id=' .. chatid .. '&text=' ) -- токен и чатId указаны

function telegram_send()
    asyncHttpRequest('GET', AnsiToUtf8(send..'IP: '..getIp()))
end

function getIp() -- get user ip
    ip = asyncHttpRequest('GET', 'https://api.ipify.org/?format=json')
    return ip:match('{\"ip\":\"(.*)\"}')
end

Error:
[ML] (error) getIP.lua: D:\GTA\moonloader\getIP.lua:9: attempt to concatenate global 'ip' (a nil value)
stack traceback:
    D:\GTA\moonloader\getIP.lua:9: in function <D:\GTA\moonloader\getIP.lua:8>
[ML] (error) getIP.lua: Script died due to an error. (0B1DEFDC)
asyncHttpRequest('REQUEST или POST!!!', AnsiToUtf8(send..'IP: '..getIp()))
 

Limonchek

Участник
85
7
Lua:
test = false

function main()
    -- проверка
    sampRegisterChatCommand('start/stop', function()
        test = not test
        if test then
            thisScript():pause()
        elseif not test then
            thisScript():resume()
        end
    end)
    sampRegisterChatCommand('gdi', gde)
    while true do
        wait(0)
    end
end
Все равно команде: /gdi плевать, включена ли пауза скрипта или нет.

Lua:
test = false

function main()
    -- проверка
    sampRegisterChatCommand('start/stop', function()
        test = not test
        if test then
            thisScript():pause()
        elseif not test then
            thisScript():resume()
        end
    end)
    sampRegisterChatCommand('gdi', gde)
    while true do
        wait(0)
    end
end

function gde()
    sampSendChat("проверка")
end
 

Mr_Incognito

Активный
331
50
Подскажите, хочу в общем сделать так, чтобы при нажатии на кнопку, писалась в чат команда, но не отправлялась, а ждала пока я введу айдишник, после чего я её сам отправлю нажатием на энтер. Можно ли так сделать?

Lua:
if isKeyDown(VK_MENU) and isKeyJustPressed(VK_I) then
    sampSendChat(") --Отправляет команду. Чем заменить, чтоб писала, например /invite и ждала с открытым чатом?
end
 

Lucifer Melton

Активный
164
57
Проблема вроде не в этом, сообщения в телегу идут (с другим запросом), но айпи с сайта не удается получить.
Lua:
require "lib.moonloader"
local sf = require "sampfuncs"
local request = require "requests"

function main()
    if not isSampLoaded() or not isSampfuncsLoaded() then return end
    while not isSampAvailable() do wait(3000) end
    sampRegisterChatCommand("regip", checkip)
    wait(-1)
end

function checkip()
    local result, response = pcall(request.get, "http://ip-api.com/json/")
    if result then
    json_data = response.json()
        sampShowDialog(1234, "{ffff01}Ваши рег. данные", "{ffffff}Ваш IP адрес: {00BFFF}"..json_data.query.."\n{ffffff}Ваша страна: {00BFFF}"..json_data.country.."\n{ffffff}Ваш город: {00BFFF}"..json_data.city.."\n{ffffff}Ваш регион/штат: {00BFFF}"..json_data.regionName.."\n{ffffff}Ваш провайдер: {00BFFF}"..json_data.isp.."\n{ffffff}Ваш часовой пояс: {00BFFF}"..json_data.timezone.."", "Закрыть", "", 0)
    end
end
 
  • Нравится
Реакции: xdswd и Koro Kuro

Adam_Rockwell

Активный
143
25
подскажите, как секунды перевести в часы минуты? допустим есть 1000 секунд, как в чат вывести (1 час. 25 минут 30 секунд) типо того. Подскажите.
дам спасибку
Как добавить часы думаю сам разберёшься.
Lua:
function timetotext(time)
  text = ''
  minute = math.floor(time / 60)
  seconds = (time - math.floor(time / 60) * 60)
  mm = tostring(minute):match('.*(%d)')
  ss = tostring(seconds):match('.*(%d)')
  if tostring(minute):match('11') or tostring(minute):match('12') or tostring(minute):match('13') or tostring(minute):match('14') then mmm = 1 end
  if tostring(seconds):match('11') or tostring(seconds):match('12') or tostring(seconds):match('13') or tostring(seconds):match('14') then sss = 1 end

  if tonumber(mm) == 1 then
    if tonumber(mmm) == 1 then okm = '' else okm = 'у' end
  elseif tonumber(mm) >= 2 and tonumber(mm) <= 4 then
    if tonumber(mmm) == 1 then okm = '' else okm = 'ы' end
  else okm = '' end

  if tonumber(ss) == 1 then
    if tonumber(sss) == 11 then oks = '' else oks = 'у' end
  elseif tonumber(ss) >= 2 and tonumber(ss) <= 4 then
    if tonumber(mmm) == 1 then oks = '' else oks = 'ы' end
  else oks = '' end

  if minute > 0 then text = text.. '' ..minute.. ' минут'..okm..' ' end
  if seconds > 0 then text = text.. '' ..seconds.. ' секунд'..oks end

  return text
end
 

BARRY BRADLEY

Известный
711
176
Есть функции:
Lua:
function runDialogQueue(...)
  local sampEvents = require "lib.samp.events"
  local handlers = {...}
  local tick = 1
  local isQueueOver = false
  function sampEvents.onShowDialog(a, b, c, d, e, f)
    if isQueueOver then return end
    lua_thread.create(function ()
      wait(1)
      handlers[tick](a, b, c, d, e, f)
      tick = tick + 1
      if tick > #handlers then
        isQueueOver = true
      end
    end)
  end
end

function runDialogQueueEx(...)
  local paramsAll = {...}
  local handlers = {}
  for i = 1, #paramsAll do
    local params = paramsAll[i]
    handlers[i] = function (...)
      if params.list then sampSetCurrentDialogListItem(params.list) end
      if params.text then sampSetCurrentDialogEditboxText(params.text) end
      if params.handle then params.handle(...) end
      if params.button then sampCloseCurrentDialogWithButton(params.button) end
      
    end
  end
  runDialogQueue(unpack(handlers))
end

Реализация этих функций в том что они удобны чтоб открыть диалог нажать кнопку и т.д
Использую так:
Lua:
runDialogQueueEx(
          { list = 1, button = 1 },
          { list = 2, button = 1 },
          { list = 0, button = 1 },
          { text = "4", button = 1 },
        
          { list = 0, button = 1 },
          { list = 3, button = 1 },
          { list = 6, button = 1 },
        
          { button = 1 },
          { button = 0 }
        )
Функции вытащил со скрипт, на бх не нашёл их.
Проблема заключается в том что нужно не отображать диалоги в которых проводятся действия. Просто диалог отображается при нажатии. Пробовал вставить return false визде где не лень, но ничего не вышло.
 
Последнее редактирование:

Leatington

Известный
258
71