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

LelHack

Известный
456
124
есть txt point
coord1 = x,y,z
coord2 = x,y,z
coord3= x,y,z

как прочитать и достать координаты? Сначало coord1, потом coord2?
Вот так я делал в ракботе
kod:
        local pos = getIniString(getRakBotPath(1).."/settings/points.ini", 'trava', 'cord'..cord)
        for line in pos:gmatch('.*%,.*%,.*') do
            posx, posy, posz = line:match('(.*)%,(.*)%,(.*)')
        end
        coordMasterStart(tonumber(posx), tonumber(posy), tonumber(posz))
 
Последнее редактирование:

Gorskin

{Reverse Developer} ✓
Проверенный
1,255
1,057
вообще можно по кд писать эту хуйню, хукать сообщение получать текст и ужалять
А можно сделать так.
По хорошему:
local function round(num, idp)
    local mult = 10 ^ (idp or 0)
    return math.floor(num * mult + 0.5) / mult
end

function get_memory()
    return round(memory.read(0x8E4CB4, 4, true) / 1048576, 1)
end
print(get_memory())
 

YourAssistant

Участник
144
17
Можно сделать одну функцию для команд через sampRegisterChatCommand(), но чтобы вызывалась с разными argument?
Есть несколько команд с одинаковым телом, разница только в числах, вот и хочу одну функцию для всех, но с разными аргументами. Пробовал - не выходит. Возможно не так делаю.
 
Последнее редактирование:

chapo

🫡 В армии с 17.10.2023. В ЛС НЕ ОТВЕЧАЮ
Друг
8,776
11,226
@chapo @Cosmo Вы у нас топовые дизайнеры , как это может быть реализовано (Показатель онлайна / наказаний и тд...)
Lua:
local status = true

imgui.Text(u8'Включить:')
imgui.SameLine()
imgui.TextColored(status and imgui.ImVec4(0, 1, 0, 1) or imgui.ImVec4(1, 0, 0, 1), status and 'on' or 'off')
--'on' и 'off' замени на иконки
 
  • Влюблен
Реакции: shadow80962

yooze

Новичок
11
0
Как сделать чтобы при вводе кмд /ygtime 19 11 11 111(время) и когда наступало это время в чат отправлялось 4 команду /capture
 

chapo

🫡 В армии с 17.10.2023. В ЛС НЕ ОТВЕЧАЮ
Друг
8,776
11,226
как получить углы поворота камеры по x, y и z? (от 0 до 360)
 

ARMOR

kjor32 is legend
Модератор
4,846
6,100
Можно ли как-то сделать кнопку из imgui.Text? Типо нажимаешь на текст и выполняется действие. Как тут renderDrawButton

UP: Ответ нашел: imgui.TextButton
 
Последнее редактирование:

mzxer

Активный
81
119
как получить углы поворота камеры по x, y и z? (от 0 до 360)
жта хранит углы поворота камеры в радианах, и хранит только горизонтальный и вертикальный углы
ща будет чуток полуси кода, не обессудь

Lua:
local ffi = require("ffi")

-- кончено же лучше определить структ данных CCamera и его поинтер кастить
-- но я не вижу смысла делать это ради двух переменных, поэтому будут просто оффсетики
_G.TheCameraPtr = 0xB6F028 -- место под класс у нас выделяется не динамически, поэтому всё шик блеск и дохера разыменований не требуется. просто храним адрес

-- return: float (deg)
local radToDeg = function(rad)
    return rad * 57.2957795785523
end

-- return: float (deg)
local getHorizontalCameraAngle = function()
    -- TheCamera+560 = TheCamera.m_aCams[0].m_fHorizontalAngle
    local angle = ffi.cast("float*", _G.TheCameraPtr + 560)[0] -- ну и разыменовываем наш указатель, получаем сюдым радианы
    angle = radToDeg(angle) -- переводим радианы в градусы
    return tonumber(angle)
end

-- всё тож самое, ток оффестик другой. можно изящнее всё реализовать, но мне лень
-- return: float (deg)
local getVerticalCameraAngle = function()
    -- TheCamera+544 = TheCamera.m_aCams[0].m_fVerticalAngle
    local angle = ffi.cast("float*", _G.TheCameraPtr + 544)[0]
    angle = radToDeg(angle)
    return tonumber(angle)
end

угол будет от -180 до 180, я думаю ты не банан ебаный и сможешь перевести в 0-360, если так нужно

вообще можно по кд писать эту хуйню, хукать сообщение получать текст и ужалять
вообще можно зайти в иду про и посмотреть откуда самп берёт значение
Lua:
-- return: unsigned int (mem_usage)
function getMemoryUsage()
    return tonumber(ffi.cast("unsigned int*", 0x8A5A80)[0])
end
 
Последнее редактирование:

DeagleC+

Известный
48
3
Здравствуйте. Есть два диалога на команду /onecmd и /twocmd. При выборе 1 кнопки - sampSendChat в первом диалоге работает, но почему-то во втором не хочет работать. В чём проблема?


Lua:
require "lib.moonloader"

function main()

        while not isSampAvailable() do wait(0) end
    
            sampRegisterChatCommand("onecmd", onecmd) -- 1
            
            sampRegisterChatCommand("twocmd", twocmd) -- 2
            
        while true do
        wait(0)
        
        local result, button, list, input = sampHasDialogRespond(20) -- 1
                if result then
                        if button == 1 and list == 0 then
                            lua_thread.create(function()
                            sampSendChat("1 cmd")
                            end)
                        end
                        if button == 0 then
                        sampCloseCurrentDialogWithButton(0)
                        end
                end
        end       
                
        local result, button, list, input = sampHasDialogRespond(21) -- 2
                if result then
                    if button == 1 and list == 0 then
                            lua_thread.create(function()
                            sampSendChat("2 cmd.")
                            end)
                    end
                    if button == 0 then
                        sampCloseCurrentDialogWithButton(0)
                    end
                end   
        end



function onecmd() -- 1
    sampShowDialog(20, "{34C924}1", string.format("{FFFFFF}1) {FF8282}OneCmd"), "Выбрать", "Отмена", 2)
    end
    
function twocmd() -- 2
    sampShowDialog(21, "{34C924}2", string.format("{FFFFFF}1) {FF8282}TwoCmd"), "Выбрать", "Отмена", 2)
    end
 

mzxer

Активный
81
119
Здравствуйте. Есть два диалога на команду /onecmd и /twocmd. При выборе 1 кнопки - sampSendChat в первом диалоге работает, но почему-то во втором не хочет работать. В чём проблема?


Lua:
require "lib.moonloader"

function main()

        while not isSampAvailable() do wait(0) end
   
            sampRegisterChatCommand("onecmd", onecmd) -- 1
           
            sampRegisterChatCommand("twocmd", twocmd) -- 2
           
        while true do
        wait(0)
       
        local result, button, list, input = sampHasDialogRespond(20) -- 1
                if result then
                        if button == 1 and list == 0 then
                            lua_thread.create(function()
                            sampSendChat("1 cmd")
                            end)
                        end
                        if button == 0 then
                        sampCloseCurrentDialogWithButton(0)
                        end
                end
        end      
               
        local result, button, list, input = sampHasDialogRespond(21) -- 2
                if result then
                    if button == 1 and list == 0 then
                            lua_thread.create(function()
                            sampSendChat("2 cmd.")
                            end)
                    end
                    if button == 0 then
                        sampCloseCurrentDialogWithButton(0)
                    end
                end  
        end



function onecmd() -- 1
    sampShowDialog(20, "{34C924}1", string.format("{FFFFFF}1) {FF8282}OneCmd"), "Выбрать", "Отмена", 2)
    end
   
function twocmd() -- 2
    sampShowDialog(21, "{34C924}2", string.format("{FFFFFF}1) {FF8282}TwoCmd"), "Выбрать", "Отмена", 2)
    end
Lua:
require "lib.moonloader"

function main()

    while not isSampAvailable() do wait(0) end

    sampRegisterChatCommand("onecmd", onecmd) -- 1
    sampRegisterChatCommand("twocmd", twocmd) -- 2

    while true do
        wait(0)

        local result, button, list, input = sampHasDialogRespond(20) -- 1
        if result then
            if button == 1 and list == 0 then
                lua_thread.create(function()
                    sampSendChat("1 cmd")
                end)
            end
            if button == 0 then sampCloseCurrentDialogWithButton(0) end
        end
    
        result, button, list, input = sampHasDialogRespond(21) -- 2
        if result then
            if button == 1 and list == 0 then
                lua_thread.create(function() sampSendChat("2 cmd.") end)
            end
            if button == 0 then sampCloseCurrentDialogWithButton(0) end
        end
    end
end

function onecmd() -- 1
    sampShowDialog(20, "{34C924}1", string.format("{FFFFFF}1) {FF8282}OneCmd"),
                   "Выбрать", "Отмена", 2)
end

function twocmd() -- 2
    sampShowDialog(21, "{34C924}2", string.format("{FFFFFF}1) {FF8282}TwoCmd"),
                   "Выбрать", "Отмена", 2)
end
 
  • Нравится
Реакции: DeagleC+

IT clown

Участник
45
2
как объединить 2 функции самп ивентс в 1

Lua:
function ev.onShowTextDraw(id, data)
    if id == 1 then
        function sampev.onSendPlayerSync(data)
            print('its work')
        end
    end
end
 

DeagleC+

Известный
48
3
Lua:
require "lib.moonloader"

function main()

    while not isSampAvailable() do wait(0) end

    sampRegisterChatCommand("onecmd", onecmd) -- 1
    sampRegisterChatCommand("twocmd", twocmd) -- 2

    while true do
        wait(0)

        local result, button, list, input = sampHasDialogRespond(20) -- 1
        if result then
            if button == 1 and list == 0 then
                lua_thread.create(function()
                    sampSendChat("1 cmd")
                end)
            end
            if button == 0 then sampCloseCurrentDialogWithButton(0) end
        end
   
        result, button, list, input = sampHasDialogRespond(21) -- 2
        if result then
            if button == 1 and list == 0 then
                lua_thread.create(function() sampSendChat("2 cmd.") end)
            end
            if button == 0 then sampCloseCurrentDialogWithButton(0) end
        end
    end
end

function onecmd() -- 1
    sampShowDialog(20, "{34C924}1", string.format("{FFFFFF}1) {FF8282}OneCmd"),
                   "Выбрать", "Отмена", 2)
end

function twocmd() -- 2
    sampShowDialog(21, "{34C924}2", string.format("{FFFFFF}1) {FF8282}TwoCmd"),
                   "Выбрать", "Отмена", 2)
end
Можешь сказать, а что именно влияло на это? Что ты изменил?
 

mzxer

Активный
81
119
Можешь сказать, а что именно влияло на это? Что ты изменил?
ты не туда скопировал обработчик для второй команды и он был под циклом


Lua:
require "lib.moonloader"

function main()

    while not isSampAvailable() do wait(0) end

    sampRegisterChatCommand("onecmd", onecmd) -- 1

    sampRegisterChatCommand("twocmd", twocmd) -- 2

    while true do -- начало бесконечного цикла
        -- тело бесконечного цикла
        wait(0)

        local result, button, list, input = sampHasDialogRespond(20) -- 1
        if result then
            if button == 1 and list == 0 then
                lua_thread.create(function()
                    sampSendChat("1 cmd")
                end)
            end
            if button == 0 then sampCloseCurrentDialogWithButton(0) end
        end
    end -- конец бесконечного цикла

    -- обработка второй команды, которая никогда не выполнится, ибо бесконечный цикл не прекращает свою работу
    local result, button, list, input = sampHasDialogRespond(21) -- 2
    if result then
        if button == 1 and list == 0 then
            lua_thread.create(function() sampSendChat("2 cmd.") end)
        end
        if button == 0 then sampCloseCurrentDialogWithButton(0) end
    end
end

function onecmd() -- 1
    sampShowDialog(20, "{34C924}1", string.format("{FFFFFF}1) {FF8282}OneCmd"),
                   "Выбрать", "Отмена", 2)
end

function twocmd() -- 2
    sampShowDialog(21, "{34C924}2", string.format("{FFFFFF}1) {FF8282}TwoCmd"),
                   "Выбрать", "Отмена", 2)
end
 
  • Нравится
Реакции: DeagleC+