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

kmsfax

Известный
154
89
Как оптимизировать это уебанство?
Lua:
function GetMoneySection(money)
    MoneySting = string.format('%d', money)
    if tonumber(string.len(money)) <= 3 then
        Summary = MoneySting
    end
    if tonumber(string.len(money)) == 4 then
        One = string.format('%s', string.sub(MoneySting, 1, 1))
        MoneySting = string.sub(MoneySting, 2)
        Summary = string.format('%s.%s', One, MoneySting)
    end
    if tonumber(string.len(money)) == 5 then
        One = string.format('%s', string.sub(MoneySting, 1, 2))
        MoneySting = string.sub(MoneySting, 3)
        Summary = string.format('%s.%s', One, MoneySting)
    end
    if tonumber(string.len(money)) == 6 then
        One = string.format('%s', string.sub(MoneySting, 1, 3))
        MoneySting = string.sub(MoneySting, 4)
        Summary = string.format('%s.%s', One, MoneySting)
    end
    if tonumber(string.len(money)) == 7 then
        One = string.format('%s', string.sub(MoneySting, 1, 1))
        MoneySting = string.sub(MoneySting, 2)
        Two = string.format('%s', string.sub(MoneySting, 1, 3))
        MoneySting = string.sub(MoneySting, 4)
        Summary = string.format('%s.%s.%s', One, Two, MoneySting)
    end
    if tonumber(string.len(money)) == 8 then
        One = string.format('%s', string.sub(MoneySting, 1, 2))
        MoneySting = string.sub(MoneySting, 3)
        Two = string.format('%s', string.sub(MoneySting, 1, 3))
        MoneySting = string.sub(MoneySting, 4)
        Summary = string.format('%s.%s.%s', One, Two, MoneySting)
    end
    if tonumber(string.len(money)) == 9 then
        One = string.format('%s', string.sub(MoneySting, 1, 3))
        MoneySting = string.sub(MoneySting, 4)
        Two = string.format('%s', string.sub(MoneySting, 1, 3))
        MoneySting = string.sub(MoneySting, 4)
        Summary = string.format('%s.%s.%s', One, Two, MoneySting)
    end
    if tonumber(string.len(money)) == 10 then
        One = string.format('%s', string.sub(MoneySting, 1, 1))
        MoneySting = string.sub(MoneySting, 2)
        Two = string.format('%s', string.sub(MoneySting, 1, 3))
        MoneySting = string.sub(MoneySting, 4)
        Three = string.format('%s', string.sub(MoneySting, 1, 3))
        MoneySting = string.sub(MoneySting, 4)
        if money > 2100000000 then Summary = string.format('2.100.000.000+')
        else Summary = string.format('%s.%s.%s.%s', One, Two, Three, MoneySting) end
    end
    return Summary
end
 

trefa

3d print
Всефорумный модератор
2,107
1,261
В чём проблема? На 1 секунду вылазит и всё.
Lua:
FontName = "Arial"
FontSize = 9
FontFlag = 13

function main()
    font = renderCreateFont( FontName, FontSize, FontFlag)
        x, y = getScreenResolution()
    sampRegisterChatCommand("sp", pig)
    thread = lua_thread.create_suspended(threadFunc)
    wait(-1)
end

function pig(arg)
  sampSendChat( string.format("/sp %d qq", arg) )
    if string.find(arg, "^%s*%d+%s*$") then
        local id = tonumber(string.match(arg, "^%s*(%d+)%s*$"))
        if sampIsPlayerConnected(id) then
            thread:run(id)
        end
    end
end

function threadFunc(id)
    while true do
        wait(0)
        if not sampIsPlayerConnected(id) then
            sampAddChatMessage("Игрок отключился.", 0xD12323)
            return
        end
        local name = sampGetPlayerNickname(id)
        local color = sampGetPlayerColor(id)
        local ping = sampGetPlayerPing(id)
        local score = sampGetPlayerScore(id)
        local bool, handle = sampGetCharHandleBySampPlayerId(id)
        if bool and doesCharExist(handle) then
          local weapon = getCurrentCharWeapon(handle)
          local weap = getweaponname(weapon)
          local health = sampGetPlayerHealth(id)
          local armor = sampGetPlayerArmor(id)
          local pedspeed = getCharSpeed(handle)
          text = string.format("{%0.6x}Ник: %s[%d]\nЗдоровье: %d \nБроня: %d\nУровень: %d\nПинг: %d\nОружие: %s\nСкорость: %d\n %s", bit.band(color,0xffffff),name, id, health, armor, score, ping, weap, pedspeed)
          renderFontDrawText(font, text, x/35, y/2, -1)
        else
          textr = string.format("{%0.6x}Ник: %s[%d]\nУровень: %d\nПинг: %d\n{D12323}Игрока нет в зоне стрима.", bit.band(color,0xffffff),name, id, score, ping)
          renderFontDrawText(font, textr, x/35, y/2, -1)
    end
  end
end

function getweaponname(weapon)
  local names = {
  [0] = "Кулак",
  [1] = "Brass Knuckles",
  [2] = "Golf Club",
  [3] = "Дубинка",
  [4] = "Нож",
  [5] = "Бита",
  [6] = "Shovel",
  [7] = "Pool Cue",
  [8] = "Катана",
  [9] = "Бензопила",
  [10] = "Дилдо",
  [11] = "Дилдо",
  [12] = "Вибратор",
  [13] = "Вибратор",
  [14] = "Цветы",
  [15] = "Cane",
  [16] = "Граната",
  [17] = "Tear Gas",
  [18] = "Коктель Молотова",
  [22] = "9mm",
  [23] = "Пистолет с глушителем",
  [24] = "Дигл",
  [25] = "Дробовик",
  [26] = "Обрезы",
  [27] = "Боевой дробовик",
  [28] = "Узи",
  [29] = "MP5",
  [30] = "АК-47",
  [31] = "М4",
  [32] = "Тек-9",
  [33] = "Винтовка",
  [34] = "Снайперская винтовка",
  [35] = "РПГ",
  [36] = "HS Rocket",
  [37] = "Flamethrower",
  [38] = "Миниган",
  [39] = "Satchel Charge",
  [40] = "Детонатор",
  [41] = "Spraycan",
  [42] = "Fire Extinguisher",
  [43] = "Камера",
  [44] = "Night Vis Goggles",
  [45] = "Thermal Goggles",
  [46] = "Парашют" }
  return names[weapon]
end
 

ufdhbi

Известный
Проверенный
1,459
866
В чём проблема? На 1 секунду вылазит и всё.
Lua:
FontName = "Arial"
FontSize = 9
FontFlag = 13

function main()
    font = renderCreateFont( FontName, FontSize, FontFlag)
        x, y = getScreenResolution()
    sampRegisterChatCommand("sp", pig)
    thread = lua_thread.create_suspended(threadFunc)
    wait(-1)
end

function pig(arg)
  sampSendChat( string.format("/sp %d qq", arg) )
    if string.find(arg, "^%s*%d+%s*$") then
        local id = tonumber(string.match(arg, "^%s*(%d+)%s*$"))
        if sampIsPlayerConnected(id) then
            thread:run(id)
        end
    end
end

function threadFunc(id)
    while true do
        wait(0)
        if not sampIsPlayerConnected(id) then
            sampAddChatMessage("Игрок отключился.", 0xD12323)
            return
        end
        local name = sampGetPlayerNickname(id)
        local color = sampGetPlayerColor(id)
        local ping = sampGetPlayerPing(id)
        local score = sampGetPlayerScore(id)
        local bool, handle = sampGetCharHandleBySampPlayerId(id)
        if bool and doesCharExist(handle) then
          local weapon = getCurrentCharWeapon(handle)
          local weap = getweaponname(weapon)
          local health = sampGetPlayerHealth(id)
          local armor = sampGetPlayerArmor(id)
          local pedspeed = getCharSpeed(handle)
          text = string.format("{%0.6x}Ник: %s[%d]\nЗдоровье: %d \nБроня: %d\nУровень: %d\nПинг: %d\nОружие: %s\nСкорость: %d\n %s", bit.band(color,0xffffff),name, id, health, armor, score, ping, weap, pedspeed)
          renderFontDrawText(font, text, x/35, y/2, -1)
        else
          textr = string.format("{%0.6x}Ник: %s[%d]\nУровень: %d\nПинг: %d\n{D12323}Игрока нет в зоне стрима.", bit.band(color,0xffffff),name, id, score, ping)
          renderFontDrawText(font, textr, x/35, y/2, -1)
    end
  end
end

function getweaponname(weapon)
  local names = {
  [0] = "Кулак",
  [1] = "Brass Knuckles",
  [2] = "Golf Club",
  [3] = "Дубинка",
  [4] = "Нож",
  [5] = "Бита",
  [6] = "Shovel",
  [7] = "Pool Cue",
  [8] = "Катана",
  [9] = "Бензопила",
  [10] = "Дилдо",
  [11] = "Дилдо",
  [12] = "Вибратор",
  [13] = "Вибратор",
  [14] = "Цветы",
  [15] = "Cane",
  [16] = "Граната",
  [17] = "Tear Gas",
  [18] = "Коктель Молотова",
  [22] = "9mm",
  [23] = "Пистолет с глушителем",
  [24] = "Дигл",
  [25] = "Дробовик",
  [26] = "Обрезы",
  [27] = "Боевой дробовик",
  [28] = "Узи",
  [29] = "MP5",
  [30] = "АК-47",
  [31] = "М4",
  [32] = "Тек-9",
  [33] = "Винтовка",
  [34] = "Снайперская винтовка",
  [35] = "РПГ",
  [36] = "HS Rocket",
  [37] = "Flamethrower",
  [38] = "Миниган",
  [39] = "Satchel Charge",
  [40] = "Детонатор",
  [41] = "Spraycan",
  [42] = "Fire Extinguisher",
  [43] = "Камера",
  [44] = "Night Vis Goggles",
  [45] = "Thermal Goggles",
  [46] = "Парашют" }
  return names[weapon]
end
рендер в майн неси в потоке забей переменный, в майне if true then render end
 

kmsfax

Известный
154
89
Lua:
require 'lib.moonloader'
require 'lib.sampfuncs'

FontName = "Arial"
FontSize = 9
FontFlag = 13

function main()
    font = renderCreateFont( FontName, FontSize, FontFlag)
    x, y = getScreenResolution()
    sampRegisterChatCommand("sp", pig)
    thread = lua_thread.create_suspended(threadFunc)
    wait(-1)
end

function pig(arg)   
    local ID = string.match(arg, '(%d+)')
    if ID ~= nil then
        if sampIsPlayerConnected(ID) then
            sampSendChat(string.format("/sp %d qq", ID))
            thread:run(ID)
        end
    end
end

function threadFunc(ID)
    while true do
        wait(0)
        if not sampIsPlayerConnected(ID) then
            sampAddChatMessage("Игрок отключился.", 0xD12323)
            return
        end
        local name = sampGetPlayerNickname(ID)
        local color = sampGetPlayerColor(ID)
        local ping = sampGetPlayerPing(ID)
        local score = sampGetPlayerScore(ID)
        local bool, handle = sampGetCharHandleBySampPlayerId(ID)
        if bool and doesCharExist(handle) then
            local weapon = getCurrentCharWeapon(handle)
            local weap = getweaponname(weapon)
            local health = sampGetPlayerHealth(ID)
            local armor = sampGetPlayerArmor(ID)
            local pedspeed = getCharSpeed(handle)
            local text = string.format("Ник: %s[%d]\nЗдоровье: %d \nБроня: %d\nУровень: %d\nПинг: %d\nОружие: %s\nСкорость: %d", name, ID, health, armor, score, ping, weap, pedspeed)
            renderFontDrawText(font, text, x/35, y/2, -1)
        else
            local textr = string.format("Ник: %s[%d]\nУровень: %d\nПинг: %d\n{D12323}Игрока нет в зоне стрима.", name, ID, score, ping)
            renderFontDrawText(font, text, x/35, y/2, -1)
        end
    end
end

function getweaponname(weapon)
  local names = {
  [0] = "Кулак",
  [1] = "Brass Knuckles",
  [2] = "Golf Club",
  [3] = "Дубинка",
  [4] = "Нож",
  [5] = "Бита",
  [6] = "Shovel",
  [7] = "Pool Cue",
  [8] = "Катана",
  [9] = "Бензопила",
  [10] = "Дилдо",
  [11] = "Дилдо",
  [12] = "Вибратор",
  [13] = "Вибратор",
  [14] = "Цветы",
  [15] = "Cane",
  [16] = "Граната",
  [17] = "Tear Gas",
  [18] = "Коктель Молотова",
  [22] = "9mm",
  [23] = "Пистолет с глушителем",
  [24] = "Дигл",
  [25] = "Дробовик",
  [26] = "Обрезы",
  [27] = "Боевой дробовик",
  [28] = "Узи",
  [29] = "MP5",
  [30] = "АК-47",
  [31] = "М4",
  [32] = "Тек-9",
  [33] = "Винтовка",
  [34] = "Снайперская винтовка",
  [35] = "РПГ",
  [36] = "HS Rocket",
  [37] = "Flamethrower",
  [38] = "Миниган",
  [39] = "Satchel Charge",
  [40] = "Детонатор",
  [41] = "Spraycan",
  [42] = "Fire Extinguisher",
  [43] = "Камера",
  [44] = "Night Vis Goggles",
  [45] = "Thermal Goggles",
  [46] = "Парашют" }
  return names[weapon]
end
 

itsLegend

Фонд борьбы за жуков 🐞
Администратор
2,696
1,468
Как оптимизировать это уебанство?
Lua:
function GetMoneySection(money)
    MoneySting = string.format('%d', money)
    if tonumber(string.len(money)) <= 3 then
        Summary = MoneySting
    end
    if tonumber(string.len(money)) == 4 then
        One = string.format('%s', string.sub(MoneySting, 1, 1))
        MoneySting = string.sub(MoneySting, 2)
        Summary = string.format('%s.%s', One, MoneySting)
    end
    if tonumber(string.len(money)) == 5 then
        One = string.format('%s', string.sub(MoneySting, 1, 2))
        MoneySting = string.sub(MoneySting, 3)
        Summary = string.format('%s.%s', One, MoneySting)
    end
    if tonumber(string.len(money)) == 6 then
        One = string.format('%s', string.sub(MoneySting, 1, 3))
        MoneySting = string.sub(MoneySting, 4)
        Summary = string.format('%s.%s', One, MoneySting)
    end
    if tonumber(string.len(money)) == 7 then
        One = string.format('%s', string.sub(MoneySting, 1, 1))
        MoneySting = string.sub(MoneySting, 2)
        Two = string.format('%s', string.sub(MoneySting, 1, 3))
        MoneySting = string.sub(MoneySting, 4)
        Summary = string.format('%s.%s.%s', One, Two, MoneySting)
    end
    if tonumber(string.len(money)) == 8 then
        One = string.format('%s', string.sub(MoneySting, 1, 2))
        MoneySting = string.sub(MoneySting, 3)
        Two = string.format('%s', string.sub(MoneySting, 1, 3))
        MoneySting = string.sub(MoneySting, 4)
        Summary = string.format('%s.%s.%s', One, Two, MoneySting)
    end
    if tonumber(string.len(money)) == 9 then
        One = string.format('%s', string.sub(MoneySting, 1, 3))
        MoneySting = string.sub(MoneySting, 4)
        Two = string.format('%s', string.sub(MoneySting, 1, 3))
        MoneySting = string.sub(MoneySting, 4)
        Summary = string.format('%s.%s.%s', One, Two, MoneySting)
    end
    if tonumber(string.len(money)) == 10 then
        One = string.format('%s', string.sub(MoneySting, 1, 1))
        MoneySting = string.sub(MoneySting, 2)
        Two = string.format('%s', string.sub(MoneySting, 1, 3))
        MoneySting = string.sub(MoneySting, 4)
        Three = string.format('%s', string.sub(MoneySting, 1, 3))
        MoneySting = string.sub(MoneySting, 4)
        if money > 2100000000 then Summary = string.format('2.100.000.000+')
        else Summary = string.format('%s.%s.%s.%s', One, Two, Three, MoneySting) end
    end
    return Summary
end
https://stackoverflow.com/a/10992898/4654612
 
  • Нравится
Реакции: imring

FYP

Известный
Автор темы
Администратор
1,763
5,906
Но вторая проблема остаётся. Если поток перезапустить, то он перестанет работать, когда игра на паузе.
баг в мунлоадере, он уже исправлен
Столкнулся с проблемой. Некоторые функции в C++ аргументы принимают как структуру, и если отправить в качестве аргумента - таблицу, в неё ничего не сохранится.

Каким образом вызвать функцию из виндосовской либы и получить её данные, если она требует структуру для их сохранения?

Я так же читал о том что аргументы пакуются в таблицу и отсылаются функции, из чего сделал вывод что можно попробовать просто указать две переменных куда сохранятся результаты структуры, но нет - не сохранились.

Пробовал через callMethod т.к. там надо указывать структуру (подумал, что это для таких случаев), но либо ошибся, либо оно не работает:
Lua:
getCPresult = callMethod(GetCursorPosAddress,point,0,0)
call*** функции не умеют возвращать значения по ссылке, используй ffi.
Такой вопрос: как из одного скрипта передать переменную, значение которой постоянно меняется, в другой? Пробовал через require - значение первый раз получается, но потом не изменяется (а нужно что менялось). Пробовал и кэш модулей очищать (package.loaded.mymodule = nil) - нифига не пашет. Конечно, можно записывать переменную в файл и читать её, но это совсем зашквар. Есть какое-нибудь решение?
лучше так, особенно если нужно сделать что-то посложнее передачи значения другому скрипту: moonloader - exports | BlastHack — DEV_WIKI(https://blast.hk/wiki/moonloader:exports)
Так-то всё круто, но когда 3, 6, 9 значные числа, то в самом начале возвращает точку (.100, .100.000), как это её можно убрать?
в последнем gsub тоже нужно заменить запятую точкой
 

imring

Ride the Lightning
Всефорумный модератор
2,362
2,545
Как скрыть этот textdraw?
mjpXbo7.png

Пытаюсь скрыть - не получается. sampTextdrawDelete не предлагайте т.к. этот textdraw будет появляться снова.
Код:
Lua:
function sampev.onShowTextDraw(ID, data)
    if ID == 2054 then
        local speed = string.match(data.text, '(%d+) KM/H')
        SPEED = string.format("{0088ff}Speed: {ffffff}%d", speed)
    end
end
 

hnnssy

Известный
Друг
2,684
2,762
Как скрыть этот textdraw?
mjpXbo7.png

Пытаюсь скрыть - не получается. sampTextdrawDelete не предлагайте т.к. этот textdraw будет появляться снова.
Код:
Lua:
function sampev.onShowTextDraw(ID, data)
    if ID == 2054 then
        local speed = string.match(data.text, '(%d+) KM/H')
        SPEED = string.format("{0088ff}Speed: {ffffff}%d", speed)
    end
end
не вижу в коде, чтобы ты пытался его скрыть