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

sep

Известный
701
79
плиз помогите голову сломал

54885558102_6cd63f409a_m.jpg

function sampev.onShowTextDraw(id, data)
if data.position.x > 530 and data.position.y < 26 then
return false
end
end

данная функция убирает все что на скрине а мне надо оставть ид 218 и 219
как это сделать
((ид постоянно меняются))

как скоректировать data.position.x > 530 and data.position.y < 26 в душе не ебу
 

chapo

tg/inst: @moujeek
Всефорумный модератор
9,205
12,533
плиз помогите голову сломал

54885558102_6cd63f409a_m.jpg

function sampev.onShowTextDraw(id, data)
if data.position.x > 530 and data.position.y < 26 then
return false
end
end

данная функция убирает все что на скрине а мне надо оставть ид 218 и 219
как это сделать
((ид постоянно меняются))

как скоректировать data.position.x > 530 and data.position.y < 26 в душе не ебу
Получи точные координаты этих двух текстдравов и добавь and x ~= *** and y ~= ***, либо проверку по спрайту (data.text)
 
  • Нравится
Реакции: sep

sep

Известный
701
79
Получи точные координаты этих двух текстдравов и добавь and x ~= *** and y ~= ***, либо проверку по спрайту (data.text)
ID: 218 | Text: HUD:radar_burgershot Pos X: 614 | Pos Y: 6

1) а куда добавить ?
если сюда
if data.position.x > 530 and data.position.y < 26 then
return false
то они будут также не видны

2) скажите как кликнуть по тексдруйву x и y

-- Функция, выполняющая одиночный клик левой кнопкой мыши по указанным координатам
function clickAt(x, y)
performMouseClick("left", x, y)
end

-- Пример использования: кликнем по точке (500, 300)
clickAt(500, 300)
то что я нашёл напашет
ид тексдрава постоянно меняется поэтому только 1 способ кликнуть по координатам
текст тоже у 1 отсутстует
ID: 2050 | Text: Box
ID: 2054 | Text: particle:lamp_shad_64
ID: 2069 | Text: _
также пробывал


function sampev.onShowTextDraw(id, data)
if data.position.x == положениеX and data.position.y == положениеY then
sampSendClickTextdraw(id)
end
end

тоже что то не пашет
если указат ид sampSendClickTextdraw("2096") конешно работает но ид меняются постоянно
 
Последнее редактирование:

chapo

tg/inst: @moujeek
Всефорумный модератор
9,205
12,533
ID: 218 | Text: HUD:radar_burgershot Pos X: 614 | Pos Y: 6

1) а куда добавить ?
если сюда
if data.position.x > 530 and data.position.y < 26 then
return false
то они будут также не видны

2) скажите как кликнуть по тексдруйву x и y

-- Функция, выполняющая одиночный клик левой кнопкой мыши по указанным координатам
function clickAt(x, y)
performMouseClick("left", x, y)
end

-- Пример использования: кликнем по точке (500, 300)
clickAt(500, 300)
то что я нашёл напашет
ид тексдрава постоянно меняется поэтому только 1 способ кликнуть по координатам
текст тоже у 1 отсутстует
ID: 2050 | Text: Box
ID: 2054 | Text: particle:lamp_shad_64
ID: 2069 | Text: _
также пробывал


function sampev.onShowTextDraw(id, data)
if data.position.x == положениеX and data.position.y == положениеY then
sampSendClickTextdraw(id)
end
end

тоже что то не пашет
если указат ид sampSendClickTextdraw("2096") конешно работает но ид меняются постоянно
бля, братиш, я в ахуе, ты уже который год задаешь сюда самые банальные вопросы. Такое ощущение что ты даже и не пытаешься что-либо понять.

1. получаешь data.text этих двух текстдравов
2.
Lua:
function sampev.onShowTextDraw(textdrawId, data)
    if data.position.x > 530 and data.position.y < 26 and data.text ~= 'текст первого' and data.text ~= 'текст второго' then
        return false
    end
end
 
  • Грустно
Реакции: sep

chapo

tg/inst: @moujeek
Всефорумный модератор
9,205
12,533
2) скажите как кликнуть по тексдруйву x и y

-- Функция, выполняющая одиночный клик левой кнопкой мыши по указанным координатам
function clickAt(x, y)
performMouseClick("left", x, y)
end

-- Пример использования: кликнем по точке (500, 300)
clickAt(500, 300)
то что я нашёл напашет
ид тексдрава постоянно меняется поэтому только 1 способ кликнуть по координатам
текст тоже у 1 отсутстует
ID: 2050 | Text: Box
ID: 2054 | Text: particle:lamp_shad_64
ID: 2069 | Text: _
также пробывал


function sampev.onShowTextDraw(id, data)
if data.position.x == положениеX and data.position.y == положениеY then
sampSendClickTextdraw(id)
end
end

тоже что то не пашет
если указат ид sampSendClickTextdraw("2096") конешно работает но ид меняются постоянно
Lua:
-- способ 1
local targetTextdraw = {
    x = 123,
    y = 123,
    id = nil
};

local function click()
    sampSendClickTextdraw(targetTextdraw.id);
end

function sampev.onShowTextDraw(textdrawId, data)
    if data.position.x == targetTextdraw.x and data.position.y == targetTextdraw.y then
        targetTextdraw.id = textdrawId;
    end
end

-- способ 2
local function clickAtTextdrawAtPos(x, y)
    for id = 0, 4096 do
        if (sampTextdrawIsExists(id)) then
            local tdX, tdY = sampTextdrawGetPos(id);
            if (tdX == x and tdY == y) then
                sampSendClickTextdraw(id);
            end
        end
    end
end
 
  • Нравится
Реакции: sep

sep

Известный
701
79
бля, братиш, я в ахуе, ты уже который год задаешь сюда самые банальные вопросы. Такое ощущение что ты даже и не пытаешься что-либо понять.
да есть веши которые я просто не понимаю

а ты сам понел что написал ?


луа:
function sampev.onShowTextDraw(textdrawId, data)
    if data.position.x > 530 and data.position.y < 26 and data.text ~= 'текст первого' and data.text ~= 'текст второго' then
        return false
    end
end

я просил не удалить ID: 218 | Text: HUD:radar_burgershot Pos X: 614 | Pos Y: 6
а наоборот показать а ты его суешь в перед return false
а насколько я знаю return false для того чтобы скрыть
а мне надо показать и текст бывает не у всех
вот пример ID: 2069 | Text: _
 

chapo

tg/inst: @moujeek
Всефорумный модератор
9,205
12,533
да есть веши которые я просто не понимаю

а ты сам понел что написал ?

луа:
function sampev.onShowTextDraw(textdrawId, data)
    if data.position.x > 530 and data.position.y < 26 and data.text ~= 'текст первого' and data.text ~= 'текст второго' then
        return false
    end
end

я просил не удалить ID: 218 | Text: HUD:radar_burgershot Pos X: 614 | Pos Y: 6
а наоборот показать а ты его суешь в перед return false
а насколько я знаю return false для того чтобы скрыть
а мне надо показать и текст бывает не у всех
вот пример ID: 2069 | Text: _
Что блять? Он его и не удалит если ты укажешь текст этого текстдрава.
 

sep

Известный
701
79
Что блять? Он его и не удалит если ты укажешь текст этого текстдрава.
стаю на асфальте я в лыже обутый толь лыжы не едут толь я ебанутый
без скрипта
54887052609_37ff8c6b17_m.jpg

со скриптом
54885937697_99625759ee_m.jpg

chapo плиз научи придурка богу молится​

плиз почему без скрипта ид логотипа не скрываются
а со скриптом скрываются

мне надо чтобы скрывались все что на скрине кроме бургера вот его данные
ID: 218 | Text: HUD:radar_burgershot Pos X: 614 | Pos Y: 6
зеленый лототип это другой скрипт эго не удаляем удаляем стандартный

ПО МОЕМУ ЕБАНУТОМУ МНЕНИЮ ДАННАЯ ХУЙНЯ

ЛУА:
function sampev.onShowTextDraw(id, data)
    if data.position.x  > 530 and data.position.y < 26 then
        return false
    end
end

и скрывает старый логотип

=========================================================================================


Что блять? Он его и не удалит если ты укажешь текст этого текстдрава.
ага блять return false а он его не удалить ладно я рукажопый а ты что курил ?

вот так работает не знаю мож это и колхоз но пашет
function sampev.onShowTextDraw(id, data)

if id == 218 then
return true -- показывает
end

if data.position.x > 530 and data.position.y < 26 then
return false -- удаляет
end

end
 
Последнее редактирование:

chapo

tg/inst: @moujeek
Всефорумный модератор
9,205
12,533
стаю на асфальте я в лыже обутый толь лыжы не едут толь я ебанутый
без скрипта
54887052609_37ff8c6b17_m.jpg

со скриптом
54885937697_99625759ee_m.jpg

chapo плиз научи придурка богу молится​

плиз почему без скрипта ид логотипа не скрываются
а со скриптом скрываются

мне надо чтобы скрывались все что на скрине кроме бургера вот его данные
ID: 218 | Text: HUD:radar_burgershot Pos X: 614 | Pos Y: 6
зеленый лототип это другой скрипт эго не удаляем удаляем стандартный

ПО МОЕМУ ЕБАНУТОМУ МНЕНИЮ ДАННАЯ ХУЙНЯ

ЛУА:
function sampev.onShowTextDraw(id, data)
    if data.position.x  > 530 and data.position.y < 26 then
        return false
    end
end

и скрывает старый логотип

=========================================================================================



ага блять return false а он его не удалить ладно я рукажопый а ты что курил ?

вот так работает не знаю мож это и колхоз но пашет
function sampev.onShowTextDraw(id, data)

if id == 218 then
return true -- показывает
end

if data.position.x > 530 and data.position.y < 26 then
return false -- удаляет
end

end
так ты блять перечитай еще и еще раз.
Lua:
function sampev.onShowTextDraw(textdrawId, data)
    if data.position.x > 530 and data.position.y < 26 and not data.text:find('radar_burgershot') then
        --[[
            код который находится тут сработает (текстдрав удалится) только если:
            1. x текстдрава более 530
            2. y текстдрава < 26
            3. текст текстдрава это НЕ ЕБАНЫЫЙ БУРГЕР (для олигофренов: бургер не удалится)
        ]]
        return false
    end
end
 

sep

Известный
701
79
так ты блять перечитай еще и еще раз.
Lua:
function sampev.onShowTextDraw(textdrawId, data)
    if data.position.x > 530 and data.position.y < 26 and not data.text:find('radar_burgershot') then
        --[[
            код который находится тут сработает (текстдрав удалится) только если:
            1. x текстдрава более 530
            2. y текстдрава < 26
            3. текст текстдрава это НЕ ЕБАНЫЫЙ БУРГЕР (для олигофренов: бургер не удалится)
        ]]
        return false
    end
end
но он сука удаляется
 

RaMero

Известный
446
134
Подскажите плес как зарендерить txd в imgui.Image?

В MoonAdditions есть апи для получения текстурки:

Lua:
txd = mad.load_txd(getGameDirectory() .. '/models/hud.txd')

texture_from_txd = txd:get_texture('radar_centre')

Но в texture_from_txd падает че-то типо такого userdata: 0x142e2898

И как это передать в imgui.Image
 

Andrinall

Известный
704
527
Подскажите плес как зарендерить txd в imgui.Image?

В MoonAdditions есть апи для получения текстурки:

Lua:
txd = mad.load_txd(getGameDirectory() .. '/models/hud.txd')

texture_from_txd = txd:get_texture('radar_centre')

Но в texture_from_txd падает че-то типо такого userdata: 0x142e2898

И как это передать в imgui.Image
На сколько я помню - texture_from_txd:get_pointer()

 

RaMero

Известный
446
134
На сколько я помню - texture_from_txd:get_pointer()

Да, нашёл решение через MoonAdditions

Lua:
local imgui = require("mimgui")
local ffi = require('ffi')
local mad = require("MoonAdditions")

ffi.cdef[[
    typedef unsigned char RwUInt8;
    typedef int RwInt32;
    typedef short RwInt16;
    typedef struct RwRaster RwRaster;
    typedef struct RwTexture RwTexture;

    struct RwRaster {
        struct RwRaster*            parent;
        RwUInt8*                    cpPixels;
        RwUInt8*                    palette;
        RwInt32                     width, height, depth;
        RwInt32                     stride;
        RwInt16                     nOffsetX, nOffsetY;
        RwUInt8                     cType;
        RwUInt8                     cFlags;
        RwUInt8                     privateFlags;
        RwUInt8                     cFormat;
        RwUInt8*                    originalPixels;
        RwInt32                     originalWidth;
        RwInt32                     originalHeight;
        RwInt32                     originalStride;
        void*                       texture_ptr;
    };

    struct RwTexture {
        RwRaster* raster;
    };
]]

function loadTextureFromTXD(txdPath, textureName)
    local txd = mad.load_txd(txdPath)
    -- local txd = mad.get_txd(txdPath)

    if not txd then
        print(string.format("[TXD] Не удалось загрузить TXD: %s", txdPath))
        return nil
    end

    local texture = txd:get_texture(textureName)
    if not texture then
        print(string.format("[TXD] Текстура '%s' не найдена в TXD '%s'", textureName, txdPath))
        return nil
    end

    local rwTexture = ffi.cast("RwTexture*", texture:get_pointer())
    if not rwTexture or rwTexture == ffi.NULL then
        print("[TXD] Ошибка: указатель на RwTexture неверен.")
        return nil
    end

    if not rwTexture.raster or rwTexture.raster == ffi.NULL then
        print("[TXD] Ошибка: у RwTexture отсутствует RwRaster.")
        return nil
    end

    local width = rwTexture.raster.width
    local height = rwTexture.raster.height

    print(string.format("[TXD] Текстура '%s' загружена (%dx%d)", textureName, width, height))

    return rwTexture.raster.texture_ptr, width, height
end


local texture, width, height = loadTextureFromTXD(getGameDirectory() .. "/models/hud.txd", "arrow")

imgui.OnFrame(
    function() return true end,
    function(this)
        if texture then
            imgui.Image(texture, imgui.ImVec2(width, height))
        end

    end
)

function main()
    while not isSampAvailable() do wait(0) end
    wait(-1)
end

1762085832967.png


Единственное не пойму, почему Txd txd = get_txd(string name) не удаётся получить загруженную гташкой txd. Например, mad.get_txd("hud") он находит и загружает, а вот mad.get_txd("fronten2") и другие не находит. Но это уже не так важно (просто не хочется грузить копию такого-же txd, если он загружен уже самой гташкой и его можно было бы спокойно прочитать и извлечь текстуры)

Да, нашёл решение через MoonAdditions

Lua:
local imgui = require("mimgui")
local ffi = require('ffi')
local mad = require("MoonAdditions")

ffi.cdef[[
    typedef unsigned char RwUInt8;
    typedef int RwInt32;
    typedef short RwInt16;
    typedef struct RwRaster RwRaster;
    typedef struct RwTexture RwTexture;

    struct RwRaster {
        struct RwRaster*            parent;
        RwUInt8*                    cpPixels;
        RwUInt8*                    palette;
        RwInt32                     width, height, depth;
        RwInt32                     stride;
        RwInt16                     nOffsetX, nOffsetY;
        RwUInt8                     cType;
        RwUInt8                     cFlags;
        RwUInt8                     privateFlags;
        RwUInt8                     cFormat;
        RwUInt8*                    originalPixels;
        RwInt32                     originalWidth;
        RwInt32                     originalHeight;
        RwInt32                     originalStride;
        void*                       texture_ptr;
    };

    struct RwTexture {
        RwRaster* raster;
    };
]]

function loadTextureFromTXD(txdPath, textureName)
    local txd = mad.load_txd(txdPath)
    -- local txd = mad.get_txd(txdPath)

    if not txd then
        print(string.format("[TXD] Не удалось загрузить TXD: %s", txdPath))
        return nil
    end

    local texture = txd:get_texture(textureName)
    if not texture then
        print(string.format("[TXD] Текстура '%s' не найдена в TXD '%s'", textureName, txdPath))
        return nil
    end

    local rwTexture = ffi.cast("RwTexture*", texture:get_pointer())
    if not rwTexture or rwTexture == ffi.NULL then
        print("[TXD] Ошибка: указатель на RwTexture неверен.")
        return nil
    end

    if not rwTexture.raster or rwTexture.raster == ffi.NULL then
        print("[TXD] Ошибка: у RwTexture отсутствует RwRaster.")
        return nil
    end

    local width = rwTexture.raster.width
    local height = rwTexture.raster.height

    print(string.format("[TXD] Текстура '%s' загружена (%dx%d)", textureName, width, height))

    return rwTexture.raster.texture_ptr, width, height
end


local texture, width, height = loadTextureFromTXD(getGameDirectory() .. "/models/hud.txd", "arrow")

imgui.OnFrame(
    function() return true end,
    function(this)
        if texture then
            imgui.Image(texture, imgui.ImVec2(width, height))
        end

    end
)

function main()
    while not isSampAvailable() do wait(0) end
    wait(-1)
end
Единственное не пойму, почему Txd txd = get_txd(string name) не удаётся получить загруженную гташкой txd. Например, mad.get_txd("hud") он находит и загружает, а вот mad.get_txd("fronten2") и другие не находит. Но это уже не так важно (просто не хочется грузить копию такого-же txd, если он загружен уже самой гташкой и его можно было бы спокойно прочитать и извлечь текстуры)
Кстати, намного оптимизированее загружать текстуры из TXD, нежели грузить их через imgui.CreateTextureFromFile. Загружая текстуру 4096х4096 из txd ушло в среднем 13мс Загружая такое-же изображение 4096х4096 через imgui.CreateTextureFromFile в среднем ушло 400мс (результат на лицо)
 
Последнее редактирование: