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

Дядя Энрик.

Активный
319
75
можно как-то убрать квадраты в таком формате гуи? Или дайте пожалуйста примерно такой же формат гуи. Левая часть своего цвета, правая своего цвета.
Lua:
local renderWindow = new.bool()

local newFrame = imgui.OnFrame(
   function() return renderWindow[0] and not isPauseMenuActive() and not sampIsScoreboardOpen() end,
    function(player)
        imgui.SetNextWindowPos(imgui.ImVec2(600, 500), imgui.Cond.FirstUseEver, imgui.ImVec2(5, 5))
        imgui.SetNextWindowSize(imgui.ImVec2(800, 600), imgui.Cond.Always)
        imgui.Begin(thisScript().name, renderWindow, imgui.WindowFlags.NoResize + imgui.WindowFlags.NoCollapse + imgui.WindowFlags.NoTitleBar)

        local dl = imgui.GetWindowDrawList()
        local p = imgui.GetCursorScreenPos()
        imgui.BeginGroup()
        imgui.Dummy(imgui.ImVec2(210, imgui.GetWindowHeight())) --пробел от окна слева на чёрном фоне
        dl:AddRectFilled(p, imgui.ImVec2(p.x + imgui.GetWindowWidth(), p.y + imgui.GetWindowHeight()), imgui.GetColorU32Vec4(imgui.ColorConvertHexToFloat4('121212')), 2.5, 15) --тоже самое что и снизу описал, замена или как-то подругому сделать.
        dl:AddRectFilled(p, imgui.ImVec2(p.x + 200, p.y + 800), imgui.GetColorU32Vec4(imgui.GetStyleAttribute('Button')), 2.5, 15) --размер левой части гуи (ВОТ САМИ ШТУКИ В ГУИ, или их убрать или заменить на такие-же, но с возможностью менять WindowRounding (закругление углов))
        imgui.EndGroup()
        --cod
        imgui.End()
    end
)
 

percheklii

Известный
720
265
есть функция получения кордов прицела? https://www.blast.hk/threads/13380/page-6#post-302082 это крашит спустя 5 секунд работы
или как этой херней пользоваться правильно? https://www.blast.hk/threads/13380/page-10#post-413015
Lua:
local ffi = require("ffi")
local vec_out = ffi.new("float[3]")
local tmp_vec = ffi.new("float[3]")

function getCrosshairPos3D()
    ffi.cast(
        "void (__thiscall*)(void*, float, float, float, float, float*, float*)",
        0x514970
    )(
        ffi.cast("void*", 0xB6F028),
        15.0,
        tmp_vec[0], tmp_vec[1], tmp_vec[2],
        tmp_vec,
        vec_out
    )
    return vec_out[0], vec_out[1], vec_out[2]
end


Lua:
local memory = require("memory")
local ffi = require("ffi")
local vec_out = ffi.new("float[3]")
local tmp_vec = ffi.new("float[3]")

function main()
repeat wait(0) until isSampAvailable()
local font = renderCreateFont("Arial", 8, 13)
local cx, cy, cz = getCrosshairPos3D()
local ax, ay = convert3DCoordsToScreen(cx, cy, cz)
    while true do wait(0)
        while isKeyDown(2) do wait(0)
            local x1, y1, z1 = convertScreenCoordsToWorld3D(ax, ay, 1.0)
            local x2, y2, z2 = convertScreenCoordsToWorld3D(ax, ay, 1000.0)
            local result, data = processLineOfSight(x1, y1, z1, x2, y2, z2, true, true)
            if result and data and data.entityType == 2 then
                local x,y,z = getCarCoordinates(getVehiclePointerHandle(data.entity))
                local posX, posY = convert3DCoordsToScreen(x,y,z)
                local car = getVehiclePointerHandle(data.entity)
                local ped = getDriverOfCar(car)
                if ped and ped ~= PLAYER_PED then
                    local bool, id = sampGetPlayerIdByCharHandle(ped)
                    if bool and not isPlayerMask(id) then
                        local color = bit.tohex(sampGetPlayerColor(id), 6)
                        local nick = sampGetPlayerNickname(id)
                        frac = getPlayerFractionByHandle(ped)
                        local text = [[
{%s}%s
{%s}%s
]]
                        renderFontDrawText(font, text:format(
                        color,
                        nick,
                        color,
                        frac
                        ), posX, posY, 0xFFFFFFFF)
                    end
                end
            end
        end
    end
end

function getPlayerFractionByHandle(ped)
    local modelsList = {
        ["Yakuza"] = { 121, 122, 123, 228, 186, 120, 169 },
        ["La Cosa Nostra"] = { 98, 223, 46, 126, 124, 113, 233 },
        ["Russian Mafia"] = { 206, 112, 3, 111, 125, 272, 216 },
        ["Los Santos Vagos"] = { 108, 109, 110, 273, 12 },
        ["The Ballas Gang"] = { 28, 103, 101, 104, 13, 102 },
        ["The Grove Street"] = { 105, 107, 106, 269, 271, 270, 195, 86 },
        ["El Coronos"] = { 47, 114, 115, 116, 292, 298 },
        ["Street Racers"] = { 21, 180, 60, 250, 299, 48, 193 },
        ["San Fierro Rifa"] = { 184, 30, 174, 175, 173, 40 },
        ["The Triads Mafia"] = { 170, 117, 118, 208, 294, 141 },
        ["Hell Angels"] = { 248, 247, 100, 192, 254 },
        ["Black Kings"] = { 183, 24, 67, 66, 25, 297, 190 },
        ["LSPD"] = { 280, 284, 282, 283, 266, 267, 265, 306 },
        ["ФБР"] = { 285, 286, 163, 164, 211 },
        ["Армия"] = { 287, 191, 61 },
        ["МЧС"] = { 70, 156, 275, 274, 276, 308 },
        ["Репортёры"] = { 290, 188, 187, 295, 150 },
        ["LVPD"] = { 280, 284, 282, 283, 266, 267, 265, 306, 309 },
        ["Коллегия адвокатов"] = { 217, 20, 59, 240, 189, 171, 194 },
        ["Гражданский"] = {}
    }
    local model = getCharModel(ped)
    for key, value in pairs(modelsList) do
        for i=1,#value do
            if model == value[i] then
                return key
            end
        end
    end
    return "Гражданский"
end

function isPlayerMask(id)
    local StructPtr = memory.read(sampGetPlayerStructPtr(id), 4, true)
    local Element = getStructElement(StructPtr, 179, 2, false)
    return Element == 0
end

function getCrosshairPos3D()
    ffi.cast(
        "void (__thiscall*)(void*, float, float, float, float, float*, float*)",
        0x514970
    )(
        ffi.cast("void*", 0xB6F028),
        15.0,
        tmp_vec[0], tmp_vec[1], tmp_vec[2],
        tmp_vec,
        vec_out
    )
    return vec_out[0], vec_out[1], vec_out[2]
end
 

Julimba

Участник
108
10
qq, можно ли как то вставить какую то картинку в мимгуи, но чтобы не было жесткой потери кадров?
 

Дядя Энрик.

Активный
319
75
qq, можно ли как то вставить какую то картинку в мимгуи, но чтобы не было жесткой потери кадров?
Lua:
imgui.OnInitialize(function()
    img = imgui.CreateTextureFromFile(getGameDirectory() .. '\\moonloader\\images\\test.png')
end)

--в фрейме
imgui.Image(img, imgui.ImVec2(200, 80))
хз, вроде нормально работает и фпс не ест
 
  • Нравится
  • Влюблен
Реакции: Julimba и percheklii

percheklii

Известный
720
265
qq, можно ли как то вставить какую то картинку в мимгуи, но чтобы не было жесткой потери кадров?
Вот полный пример если надо)
Как написал @Дядя Энрик. , фпс не просидает, хотя я не знаю что в твоем понимание "жесткий потери кадров"

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)
 
  • Влюблен
Реакции: Julimba

XRLM

Известный
2,534
850
Lua:
local ffi = require("ffi")
local vec_out = ffi.new("float[3]")
local tmp_vec = ffi.new("float[3]")

function getCrosshairPos3D()
    ffi.cast(
        "void (__thiscall*)(void*, float, float, float, float, float*, float*)",
        0x514970
    )(
        ffi.cast("void*", 0xB6F028),
        15.0,
        tmp_vec[0], tmp_vec[1], tmp_vec[2],
        tmp_vec,
        vec_out
    )
    return vec_out[0], vec_out[1], vec_out[2]
end


Lua:
local memory = require("memory")
local ffi = require("ffi")
local vec_out = ffi.new("float[3]")
local tmp_vec = ffi.new("float[3]")

function main()
repeat wait(0) until isSampAvailable()
local font = renderCreateFont("Arial", 8, 13)
local cx, cy, cz = getCrosshairPos3D()
local ax, ay = convert3DCoordsToScreen(cx, cy, cz)
    while true do wait(0)
        while isKeyDown(2) do wait(0)
            local x1, y1, z1 = convertScreenCoordsToWorld3D(ax, ay, 1.0)
            local x2, y2, z2 = convertScreenCoordsToWorld3D(ax, ay, 1000.0)
            local result, data = processLineOfSight(x1, y1, z1, x2, y2, z2, true, true)
            if result and data and data.entityType == 2 then
                local x,y,z = getCarCoordinates(getVehiclePointerHandle(data.entity))
                local posX, posY = convert3DCoordsToScreen(x,y,z)
                local car = getVehiclePointerHandle(data.entity)
                local ped = getDriverOfCar(car)
                if ped and ped ~= PLAYER_PED then
                    local bool, id = sampGetPlayerIdByCharHandle(ped)
                    if bool and not isPlayerMask(id) then
                        local color = bit.tohex(sampGetPlayerColor(id), 6)
                        local nick = sampGetPlayerNickname(id)
                        frac = getPlayerFractionByHandle(ped)
                        local text = [[
{%s}%s
{%s}%s
]]
                        renderFontDrawText(font, text:format(
                        color,
                        nick,
                        color,
                        frac
                        ), posX, posY, 0xFFFFFFFF)
                    end
                end
            end
        end
    end
end

function getPlayerFractionByHandle(ped)
    local modelsList = {
        ["Yakuza"] = { 121, 122, 123, 228, 186, 120, 169 },
        ["La Cosa Nostra"] = { 98, 223, 46, 126, 124, 113, 233 },
        ["Russian Mafia"] = { 206, 112, 3, 111, 125, 272, 216 },
        ["Los Santos Vagos"] = { 108, 109, 110, 273, 12 },
        ["The Ballas Gang"] = { 28, 103, 101, 104, 13, 102 },
        ["The Grove Street"] = { 105, 107, 106, 269, 271, 270, 195, 86 },
        ["El Coronos"] = { 47, 114, 115, 116, 292, 298 },
        ["Street Racers"] = { 21, 180, 60, 250, 299, 48, 193 },
        ["San Fierro Rifa"] = { 184, 30, 174, 175, 173, 40 },
        ["The Triads Mafia"] = { 170, 117, 118, 208, 294, 141 },
        ["Hell Angels"] = { 248, 247, 100, 192, 254 },
        ["Black Kings"] = { 183, 24, 67, 66, 25, 297, 190 },
        ["LSPD"] = { 280, 284, 282, 283, 266, 267, 265, 306 },
        ["ФБР"] = { 285, 286, 163, 164, 211 },
        ["Армия"] = { 287, 191, 61 },
        ["МЧС"] = { 70, 156, 275, 274, 276, 308 },
        ["Репортёры"] = { 290, 188, 187, 295, 150 },
        ["LVPD"] = { 280, 284, 282, 283, 266, 267, 265, 306, 309 },
        ["Коллегия адвокатов"] = { 217, 20, 59, 240, 189, 171, 194 },
        ["Гражданский"] = {}
    }
    local model = getCharModel(ped)
    for key, value in pairs(modelsList) do
        for i=1,#value do
            if model == value[i] then
                return key
            end
        end
    end
    return "Гражданский"
end

function isPlayerMask(id)
    local StructPtr = memory.read(sampGetPlayerStructPtr(id), 4, true)
    local Element = getStructElement(StructPtr, 179, 2, false)
    return Element == 0
end

function getCrosshairPos3D()
    ffi.cast(
        "void (__thiscall*)(void*, float, float, float, float, float*, float*)",
        0x514970
    )(
        ffi.cast("void*", 0xB6F028),
        15.0,
        tmp_vec[0], tmp_vec[1], tmp_vec[2],
        tmp_vec,
        vec_out
    )
    return vec_out[0], vec_out[1], vec_out[2]
end
Lua:
table overflow
stack traceback:
[C]: in function 'cast'
один хуй так же крашит с той же причиной
 
  • Грустно
Реакции: percheklii

percheklii

Известный
720
265
есть функция получения кордов прицела? https://www.blast.hk/threads/13380/page-6#post-302082 это крашит спустя 5 секунд работы
или как этой херней пользоваться правильно? https://www.blast.hk/threads/13380/page-10#post-413015
Правда я думаю это не то что тебе нужно, но все же, взято с https://www.blast.hk/threads/171588/
Lua:
function getCrosshairPositionOnScreen()
    local resolutionX, resolutionY = getScreenResolution()
    local onScreenX = resolutionX * 0.5299999714
    local onScreenY = resolutionY * 0.4
    return onScreenX, onScreenY
end

Как проверить, находится ли игрок в AFK?
/afk id
works only in the player's line of sight
Lua:
function main()
    sampRegisterChatCommand("afk", function(id)
        local result = sampIsPlayerPaused(id)
        if result then
            sampAddChatMessage("PLAYER AFK", 0xFFFFFF)
        else
            sampAddChatMessage("PLAYER NO AFK", 0xFFFFFF)
        end
    end)
    wait(-1)
end
 
Последнее редактирование:
  • Нравится
Реакции: SyLvy и XRLM

Julimba

Участник
108
10
Lua:
function hook.onServerMessage(clr, text) -- выше мейн, библиотеки все подключены
    if text:find('Чебупель') then
        sampSendChat('/hi 567')
        if text:find('Данного ID нет на сервере') then
            sampAddChatMessage('Фыр фыр фыр', -1)
        end
    end
end

qq, такая тема, скрипт должен изначально найти слово "Чебупель", если он его находит, то пишет сообщение в чат и если после этого сообщения пишет "Данного ID нет на сервере'", то должно выводить какое то сообщение в чат. По итогу скрипт запускается, все норм, но просто изначальное сообщение "Чебупель" даже не тригерит скрипт вообще.
 

Дядя Энрик.

Активный
319
75
Lua:
function hook.onServerMessage(clr, text) -- выше мейн, библиотеки все подключены
    if text:find('Чебупель') then
        sampSendChat('/hi 567')
        if text:find('Данного ID нет на сервере') then
            sampAddChatMessage('Фыр фыр фыр', -1)
        end
    end
end

qq, такая тема, скрипт должен изначально найти слово "Чебупель", если он его находит, то пишет сообщение в чат и если после этого сообщения пишет "Данного ID нет на сервере'", то должно выводить какое то сообщение в чат. По итогу скрипт запускается, все норм, но просто изначальное сообщение "Чебупель" даже не тригерит скрипт вообще.
Код:
function sampev.onServerMessage(color, text)
    if text:find('Чебупель') then
           sampSendChat('/hi 567')
               else if text:find('На сервере не найдено игроков по указанным вами параметрам') then
               sampAddChatMessage('Фыр фыр фыр', -1)
        end
    end
end
Хз, всё работает, видимо текст не так вводишь или с ошибкой
 
Последнее редактирование:

joumey

Активный
195
43
Lua:
function hook.onServerMessage(clr, text) -- выше мейн, библиотеки все подключены
    if text:find('Чебупель') then
        sampSendChat('/hi 567')
        if text:find('Данного ID нет на сервере') then
            sampAddChatMessage('Фыр фыр фыр', -1)
        end
    end
end

qq, такая тема, скрипт должен изначально найти слово "Чебупель", если он его находит, то пишет сообщение в чат и если после этого сообщения пишет "Данного ID нет на сервере'", то должно выводить какое то сообщение в чат. По итогу скрипт запускается, все норм, но просто изначальное сообщение "Чебупель" даже не тригерит скрипт вообще.
проверь кодировку файла