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

percheklii

Известный
650
235
Проблема актуальна? Попробуй так, должно сработать:
Код:
local inicfg = require("inicfg")
local hook = require("samp.events")
local imgui = require("mimgui")
local ffi = require("ffi")

local encoding = require("encoding")
encoding.default = 'CP1251'
local u8 = encoding.UTF8

local ini = inicfg.load({
    Nicknames = {}
}, "Angar.ini")

local window_state = imgui.new.bool()
local buffer_size = 512
local buffer = imgui.new.char[buffer_size]()

function main()
    repeat wait(0) until isSampAvailable()
    sampRegisterChatCommand("angar", function()
        window_state[0] = not window_state[0]
    end)
    wait(-1)
end

imgui.OnFrame(function() return window_state[0] end, function(player)
    local sw, sh = getScreenResolution()
    imgui.SetNextWindowSize(imgui.ImVec2(320, 390))
    imgui.SetNextWindowPos(imgui.ImVec2(sw / 2, sh / 2), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
    imgui.Begin(u8'Помощник для Ангара', window_state, imgui.WindowFlags.AlwaysAutoResize)
    imgui.Text(u8('Список ников:'))
    local nicknames_text = table.concat(ini.Nicknames, "\n")
    for i = 1, math.min(buffer_size, #nicknames_text) do
        buffer[i - 1] = nicknames_text:sub(i, i):byte()
    end
  
    if imgui.InputTextMultiline('##team', buffer, buffer_size) then
        ini.Nicknames = {}
        local buffer_text = ffi.string(buffer)
        for line in buffer_text:gmatch("[^\r\n]+") do
            table.insert(ini.Nicknames, line)
        end
    end

    if imgui.Button(u8('Сохранить настройка'), imgui.ImVec2(300,30)) then
        if inicfg.save(ini, path) then
            sampAddChatMessage('{FB4343}[Помощник для Ангара]{FFFFFF}: Настройки успешно сохранены.', 0xFFFFFF)
        else
            sampAddChatMessage('{FB4343}[Помощник для Ангара]{FFFFFF}: Настройки не хотят сохранятся, ничего не могу поделать :(', 0xFFFFFF)
        end
    end

    imgui.End()
end)
Уже решил, спасибо)
 

percheklii

Известный
650
235
Мой тоже вроде работает, кинь сюда, если не сложно. Интересно посмотреть каким способом)
Lua:
local inicfg = require("inicfg")
local sampev = require("samp.events")
local imgui = require("mimgui")
local ffi = require("ffi")
local encoding = require("encoding")
encoding.default = ("CP1251")
local u8 = encoding.UTF8

local ini = inicfg.load({
    nicknames = {}
}, "Angar.ini")

local window = imgui.new.bool()
local buffer = imgui.new.char[256](u8(table.concat(ini.nicknames, "\n")))

function main()
    repeat wait(0) until isSampAvailable()
    sampRegisterChatCommand("angar", function()
        window[0] = not window[0]
    end)
    wait(-1)
end

imgui.OnInitialize(function()
    imgui.GetIO().IniFilename = nil
end)

imgui.OnFrame(function() return window[0] end, function(player)
    local sw, sh = getScreenResolution()
    imgui.SetNextWindowPos(imgui.ImVec2(sw / 2, sh / 2), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
    imgui.Begin("Angar", window, imgui.WindowFlags.NoCollapse + imgui.WindowFlags.AlwaysAutoResize)
    
    imgui.PushItemWidth(200)

    if imgui.InputTextMultiline("##1", buffer, 256) then
        local text = ffi.string(buffer)
        ini.nicknames = {}
        for line in text:gmatch("[^\r\n]+") do
            table.insert(ini.nicknames, line)
        end
        inicfg.save(ini, "Angar.ini")
    end

    imgui.PopItemWidth()
    imgui.End()
end)
 

pugovkin228

Участник
33
2
Как сделать рендер на скин?
Спизжено у чапо
Код:
local Font = renderCreateFont('Trebuchet MS', 13, 5)

function main()
    while not isSampAvailable() do wait(0) end
    while true do
        wait(0)
        for _, ped in ipairs(getAllChars()) do
            if isCharOnScreen(ped) and getCharModel(ped) == ID SKIN then
                local x, y = convert3DCoordsToScreen(getCharCoordinates(ped))
                renderFontDrawText(Font, 'RENDER NA SKIN', x, y, -1)
            end
        end
    end
end
 
  • Эм
Реакции: ChromiusJ

ARMOR

I'm sorry that I let you down
Модератор
4,815
5,926
Как сделать рендер на скин?
Самое крутое ВХ ( можно типо добавить что чамсы рендерятся цветом клиста и будет прикольно )
 
  • Вау
Реакции: percheklii

percheklii

Известный
650
235
Как сделать рендер на скин?
Я как-то еще такое делал
Рендерит точку на скине игрока с цветом игрока.
Еще если поставить везде false в isLineOfSightClear, будет что-то типо вх. 😆

Lua:
require("moonloader")

function main()
    repeat wait(0) until isSampAvailable()

    while true do wait(0)
        
        if wasKeyPressed(VK_F2) then;
            on = not on
            printStyledString("~w~DotOnSkin: " .. (on and "~g~ON" or "~r~OFF"), 1000, 5)
        end

        if on then
            for i = 0, sampGetMaxPlayerId() do
                if sampIsPlayerConnected(i) then
                    local result, ped = sampGetCharHandleBySampPlayerId(i)
                    local color = sampGetPlayerColor(i)
                    if result then
                        xx, yy, zz = getCharCoordinates(PLAYER_PED)
                        x, y, z = getCharCoordinates(ped)
                        if isLineOfSightClear(xx, yy, zz, x, y , z, true, false, false, true, false) then
                            if doesCharExist(ped) and isCharOnScreen(ped) then
                                x, y = convert3DCoordsToScreen(x, y, z)
                                renderDrawPolygon(x, y, 6, 6, 40, 0, color)
                            end
                        end
                    end
                end
            end
        end
    end
end
 

tsunamiqq

Участник
422
15
Хелпаните, нужно сделать меню, которая будет выводиться если она включена к примеру через чекбокс, и будет оставаться на экране всегда, пока соответственно не выключу её
 

percheklii

Известный
650
235
Хелпаните, нужно сделать меню, которая будет выводиться если она включена к примеру через чекбокс, и будет оставаться на экране всегда, пока соответственно не выключу её
Lua:
local imgui = require("mimgui")

local firstWindow, secondWindow = imgui.new.bool(), imgui.new.bool()
local checkbox = imgui.new.bool()

imgui.OnFrame(function() return firstWindow[0] end, function(player)
    local sx, sy = getScreenResolution()
    imgui.SetNextWindowPos(imgui.ImVec2(sx / 2, sy /2), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
    imgui.Begin("Test", firstWindow, imgui.WindowFlags.NoCollapse + imgui.WindowFlags.AlwaysAutoResize)
    if imgui.Checkbox("ON/OFF", checkbox) then
        secondWindow[0] = not secondWindow[0]
    end
    imgui.End()
end)

imgui.OnFrame(function() return secondWindow[0] end, function(player)
    player.HideCursor = true
    imgui.SetNextWindowPos(imgui.ImVec2(500, 500), imgui.Cond.Always, imgui.ImVec2(1, 1))
    imgui.SetNextWindowSize(imgui.ImVec2(130, 175), imgui.Cond.Always)
    imgui.Begin("", secondWindow, imgui.WindowFlags.NoDecoration, imgui.WindowFlags.NoSavedSettings, imgui.WindowFlags.NoMove, imgui.WindowFlags.NoInputs)
    imgui.Text("Hello, world!")
    imgui.End()
end)

function main()
    repeat wait(0) until isSampAvailable()
    sampRegisterChatCommand("test", function()
        firstWindow[0] = not firstWindow[0]
    end)
    wait(-1)
end
 
  • Нравится
Реакции: ChromiusJ

Stepaa

Новичок
13
2
Загрузил картинку в IMGUI , работает пару секунд и вместо картинки появляется - Белый квадрат
Как можно решить
 
  • Эм
Реакции: YarikVL

Stepaa

Новичок
13
2
local image = {
file = getWorkingDirectory()..'\\resource\\ava.png',
handle = nil
}



imgui.BeginChild('##asdasdada', imgui.ImVec2(125, 100), false, imgui.WindowFlags.NoScrollbar + imgui.WindowFlags.NoScrollbar + imgui.WindowFlags.NoScrollbar)


if doesFileExist(image.file) then
image.handle = imgui.CreateTextureFromFile(image.file)
end

if image.handle then
imgui.SetCursorPos(imgui.ImVec2(10, 1))
imgui.Image(image.handle, imgui.ImVec2(100, 100))
end


imgui.EndChild()
 

percheklii

Известный
650
235
local image = {
file = getWorkingDirectory()..'\\resource\\ava.png',
handle = nil
}



imgui.BeginChild('##asdasdada', imgui.ImVec2(125, 100), false, imgui.WindowFlags.NoScrollbar + imgui.WindowFlags.NoScrollbar + imgui.WindowFlags.NoScrollbar)


if doesFileExist(image.file) then
image.handle = imgui.CreateTextureFromFile(image.file)
end

if image.handle then
imgui.SetCursorPos(imgui.ImVec2(10, 1))
imgui.Image(image.handle, imgui.ImVec2(100, 100))
end


imgui.EndChild()
Lua:
local imgui = require("mimgui")
local window = imgui.new.bool(true)

imgui.OnInitialize(function()
    imgui.GetIO().IniFilename = nil
    img = imgui.CreateTextureFromFile(getGameDirectory() .. '\\moonloader\\recource\\123.png') -- Путь к картинке
end)

local newFrame = imgui.OnFrame(function() return window[0] end, function(self)
    local resX, resY = getScreenResolution()
    local sizeX, sizeY = 600, 600
    imgui.SetNextWindowPos(imgui.ImVec2(resX / 2, resY / 2), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
    imgui.SetNextWindowSize(imgui.ImVec2(sizeX, sizeY), imgui.Cond.FirstUseEver)
    imgui.Begin("test", window)
    imgui.Image(img, imgui.ImVec2(300,300))
    imgui.End()
end)
 

Stepaa

Новичок
13
2
imgui

Lua:
local imgui = require("mimgui")
local window = imgui.new.bool(true)

imgui.OnInitialize(function()
    imgui.GetIO().IniFilename = nil
    img = imgui.CreateTextureFromFile(getGameDirectory() .. '\\moonloader\\recource\\123.png') -- Путь к картинке
end)

local newFrame = imgui.OnFrame(function() return window[0] end, function(self)
    local resX, resY = getScreenResolution()
    local sizeX, sizeY = 600, 600
    imgui.SetNextWindowPos(imgui.ImVec2(resX / 2, resY / 2), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
    imgui.SetNextWindowSize(imgui.ImVec2(sizeX, sizeY), imgui.Cond.FirstUseEver)
    imgui.Begin("test", window)
    imgui.Image(img, imgui.ImVec2(300,300))
    imgui.End()
end)
у меня на imgui
 

percheklii

Известный
650
235
imgui


у меня на imgui
Lua:
local imgui = require("imgui")
local window = imgui.ImBool(false)
        
function main()
    while not isSampAvailable() do wait(200) end
    imgui.Process = false
    sampgui_texture = imgui.CreateTextureFromFile(getGameDirectory() .. '\\moonloader\\recource\\123.png')
    window.v = true
    while true do
        wait(0)
        imgui.Process = window.v
    end
end
        
function imgui.OnDrawFrame()
    if window.v then
        local resX, resY = getScreenResolution()
        local sizeX, sizeY = 300, 300 -- WINDOW SIZE
        imgui.SetNextWindowPos(imgui.ImVec2(resX / 2 - sizeX / 2, resY / 2 - sizeY / 2), imgui.Cond.FirstUseEver)
        imgui.SetNextWindowSize(imgui.ImVec2(sizeX, sizeY), imgui.Cond.FirstUseEver)
        imgui.Begin('Window Title', window)
        imgui.Image(sampgui_texture, imgui.ImVec2(250, 200))
        imgui.End()
    end
end
 

Yans

Активный
191
33
Рендерит в 2 стороны

Render:
local font = renderCreateFont('ShellyAllegroC',13,5)

local massive = {
    [12642] = "Кот",
    [26] = "Турист"
}

function main()
    if not isSampLoaded() or not isSampfuncsLoaded() then return end
    while not isSampAvailable() do wait(100) end
    active = false
    sampRegisterChatCommand("Quest", function() active = not active sampAddChatMessage(active and ("Работаю") or ("Выключен"), 0x5A90CE) end)
    while true do
        wait(0)
        if active then
            for _, v in pairs(getAllChars()) do
                for obj, text in pairs(massive) do
                    if getCharModel(v) == obj then
                        if isCharOnScreen(v) then
                            local pX, pY, pZ = getCharCoordinates(PLAYER_PED)
                            local result, oX, oY, oZ = getCharCoordinates(v)
                            if result then
                                local dist = math.floor(getDistanceBetweenCoords3d(pX, pY, pZ, oX, oY, oZ))
                                local pOSx, pOSy = convert3DCoordsToScreen(pX, pY, pZ)
                                local oOSx, oOSy = convert3DCoordsToScreen(oX, oY, oZ)
                                renderDrawLine(pOSx, pOSy, oOSx, oOSy, 1, 0xFFFFFF00)
                                renderFontDrawText(font, '{669900}'..text..'[{FFFFFF}'..dist..'{669900}]', oOSx, oOSy,-1)
                            end
                        end
                    end
                end
            end
        end
    end
end