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

Naito

Участник
69
19
Lua:
local font = renderCreateFont('Arial', 10, 5)
local skins = {
    [59] = 'skinname'
}
local select_id = 0
function main()
    while not isSampAvailable() do wait(0) end
    sampRegisterChatCommand('wh', function (params)
        if #params > 0 then
            if tonumber(params) then
                select_id = tonumber(params)
            else
                local result, id = table_find(skins, params)
                if result then
                    select_id = id
                end
            end
        end
    end)
    while true do
        wait(0)
        for k, ped in pairs(getAllChars()) do
            if isCharOnScreen(ped) then
                if not sampGetPlayerIdByCharHandle(ped) then -- NPC check
                    local skin = getCharModel(ped)
                    if skin == select_id then
                        local pos = {getCharCoordinates(ped)}
                        local x, y = convert3DCoordsToScreen(pos[1], pos[2], pos[3])
                        renderFontDrawText(font, skin, x, y, -1)
                    end
                end
            end
        end
    end
end
function table_find(t, value)
    for k, v in pairs(t) do
        if v == value then
            return true, k
        end
    end
    return false, -1
end
thank youaaaaaassss i loveee
 
  • Нравится
Реакции: Willy4ka

sirues

Новичок
3
0
Lua:
local sampev = require('lib.samp.events')
function sampev.onApplyPlayerAnimation(playerId, animLib, animName, frameDelta, loop, lockX, lockY, freeze, time)
    if playerId == select(2, sampGetPlayerIdByCharHandle(1)) then
        if (animLib == "PED" and animName == "IDLE_CHAT") or (animLib == "CARRY" and animName == "crry_prtial") then
            return false
        end
    end
end
Спасибо большое, вопрос, как добавить еще одну анимацию в блок?
 

Ancwork

Новичок
12
0
Как с ini работать в imgui. Хочу сохранение из imgui.InputText

Lua:
local inicfg = require('inicfg');
local IniFilename = 'setting.ini'
local ini = inicfg.load({
    player = {
        name = 'Ivan Ivanov',
        phone = '123-123'
    }
}, IniFilename);
inicfg.save(ini, IniFilename);
local main_window_state = imgui.ImBool(false)

function imgui.OnDrawFrame()
  if main_window_state.v then
    imgui.SetNextWindowSize(imgui.ImVec2(600, 300), imgui.Cond.FirstUseEver)
    imgui.Begin('Setting', main_window_state)
    imgui.Text('')
    imgui.End()
  end
end
 

coulside

Участник
37
0
[ML] (script) meteoAvtoScrin.lua: Сообщение в диалоге 46 не найдено.
Не выводит сообщение из диалога, в чем ошибка?


Lua:
local sampev = require 'lib.samp.events'

function main()
    if not isSampLoaded() or not isSampfuncsLoaded() then return end
    while not isSampAvailable() do wait(100) end

    while true do
        wait(0)
      
        if isKeyJustPressed(VK_F8) then
            makeScreenshot()
        end
    end
end

function sampev.onShowDialog(id, style, title, button1, button2, dialogText)
    local pattern = "-%s*Метеоролог:%s*Отличная%s*работа,%s*вот%s*твои%s*деньги!%s*Мы%s*немедленно%s*подключим%s*метеозонд%s*к%s*нашей%s*сети%s*и%s*начнем%s*принимать%s*с%s*него%s*данные!%s*"

    if id == 46 and dialogText:match(pattern) then
        -- Сообщение найдено
        print("Сообщение найдено: - Метеоролог: Отличная работа, вот твои деньги! Мы немедленно подключим метеозонд к нашей сети и начнем принимать с него данные!")
    else
        -- Сообщение не найдено
        print("Сообщение в диалоге 46 не найдено.")
    end
end

function makeScreenshot(disable)
    if disable then
        displayHud(false)
        sampSetChatDisplayMode(0)
    end

    require('memory').setuint8(sampGetBase() + 0x119CBC, 1)

    if disable then
        displayHud(true)
        sampSetChatDisplayMode(2)
    end
end

сам диалог:
- Метеоролог: Отличная работа, вот твои деньги! Мы немедленно подключим метеозонд к нашей сети и начнем принимать с него данные!
 

Вложения

  • изображение_2024-11-03_020654369.png
    изображение_2024-11-03_020654369.png
    30.1 KB · Просмотры: 7
  • изображение_2024-11-03_020709298.png
    изображение_2024-11-03_020709298.png
    2.8 KB · Просмотры: 8

Naito

Участник
69
19
How to make the line reach up to 1000 meters or 1500 meters across the entire map?, and not have to look everywhere to detect something

if skinName then
local pos = {getCharCoordinates(ped)}
local x, y, z = pos[1], pos[2], pos[3]
local dist = math.floor(getDistanceBetweenCoords3d(playerX, playerY, playerZ, x, y, z))

local c1, c2 = convert3DCoordsToScreen(playerX, playerY, playerZ)
local o1, o2 = convert3DCoordsToScreen(x, y, z)
local text = '{6400FF}'..skinName..' (ID: '..skin..')\n{C0C0C0}Distancia: '..dist..'m.'

if skinName then
renderDrawLine(c1, c2, o1, o2, 3, 0xFF800080)
renderFontDrawText(font, text, o1, o2, -1)
end
end
end
end
end
end
end
end
 

Дядя Энрик.

Активный
334
80
[ML] (script) meteoAvtoScrin.lua: Сообщение в диалоге 46 не найдено.
Не выводит сообщение из диалога, в чем ошибка?


Lua:
local sampev = require 'lib.samp.events'

function main()
    if not isSampLoaded() or not isSampfuncsLoaded() then return end
    while not isSampAvailable() do wait(100) end

    while true do
        wait(0)
     
        if isKeyJustPressed(VK_F8) then
            makeScreenshot()
        end
    end
end

function sampev.onShowDialog(id, style, title, button1, button2, dialogText)
    local pattern = "-%s*Метеоролог:%s*Отличная%s*работа,%s*вот%s*твои%s*деньги!%s*Мы%s*немедленно%s*подключим%s*метеозонд%s*к%s*нашей%s*сети%s*и%s*начнем%s*принимать%s*с%s*него%s*данные!%s*"

    if id == 46 and dialogText:match(pattern) then
        -- Сообщение найдено
        print("Сообщение найдено: - Метеоролог: Отличная работа, вот твои деньги! Мы немедленно подключим метеозонд к нашей сети и начнем принимать с него данные!")
    else
        -- Сообщение не найдено
        print("Сообщение в диалоге 46 не найдено.")
    end
end

function makeScreenshot(disable)
    if disable then
        displayHud(false)
        sampSetChatDisplayMode(0)
    end

    require('memory').setuint8(sampGetBase() + 0x119CBC, 1)

    if disable then
        displayHud(true)
        sampSetChatDisplayMode(2)
    end
end

сам диалог:
- Метеоролог: Отличная работа, вот твои деньги! Мы немедленно подключим метеозонд к нашей сети и начнем принимать с него данные!
Lua:
require('lib.samp.events').onShowDialog = function(dialogId, style, title, button1, button2, text)
    if dialogId == 46 then
        if text:find('Отличная работа, вот твои деньги! Мы немедленно подключим метеозонд к нашей сети и начнем принимать с него данные!') then
            sampAddChatMessage('done', -1)
        end
    end
end
 
  • Нравится
Реакции: coulside

coulside

Участник
37
0
Lua:
require('lib.samp.events').onShowDialog = function(dialogId, style, title, button1, button2, text)
    if dialogId == 46 then
        if text:find('Отличная работа, вот твои деньги! Мы немедленно подключим метеозонд к нашей сети и начнем принимать с него данные!') then
            sampAddChatMessage('done', -1)
        end
    end
end
cпасибо <3, как задержку правильно добавить? Скриншот делается раньше появления диалога
 

chapo

чопа сребдс // @moujeek
Модератор
8,847
11,510
cпасибо <3, как задержку правильно добавить? Скриншот делается раньше появления диалога
Lua:
require('lib.samp.events').onShowDialog = function(dialogId, style, title, button1, button2, text)
    if dialogId == 46 then
        if text:find('Отличная работа, вот твои деньги! Мы немедленно подключим метеозонд к нашей сети и начнем принимать с него данные!') then
            lua_thread.create(function()
                wait(1000) -- 1 sec
                sampAddChatMessage('done', -1)
            end)
        end
    end
end
 

coulside

Участник
37
0
реализовал по другому, через wait ошибку выдает
Lua:
local sampev = require 'lib.samp.events'
local screenshotPending = false

function main()
    if not isSampLoaded() or not isSampfuncsLoaded() then return end
    while not isSampAvailable() do wait(100) end

    
    while true do
        wait(0)

        if screenshotPending then
            wait(1000)
            makeScreenshot()
            sampAddChatMessage('{ff0000}[Meteo]:{FFFFFF} Скриншот сделан.', -1)
            screenshotPending = false
        end
    end
end

require('lib.samp.events').onShowDialog = function(dialogId, style, title, button1, button2, text)
    if dialogId == 46 then
        if text:find('Отличная работа, вот твои деньги! Мы немедленно подключим метеозонд к нашей сети и начнем принимать с него данные!') then
            sampAddChatMessage('{ff0000}[Meteo]:{FFFFFF} Скриншот выполнен...', -1)
            screenshotPending = true
        end
    end
end

function makeScreenshot(disable)
    if disable then
        displayHud(false)
        sampSetChatDisplayMode(0)
    end

    -- Считываем значение для создания скриншота
    require('memory').setuint8(sampGetBase() + 0x119CBC, 1)

    if disable then
        displayHud(true)
        sampSetChatDisplayMode(2)
    end
end
 

Орк

Известный
178
118
Есть такой код https://github.com/JuniorDjjr/SA-Mi...b4c45658fbaaa9ec7d90/MixSets/ReadIni.cpp#L863
C++:
    if (ReadIniInt(ini, &lg, "Graphics", "CameraPhotoQuality", &i)) {
        G_CameraPhotoQuality = i;
        injector::MakeInline<0x5D04E1, 0x5D04E1 + 7>([](injector::reg_pack& regs)
        {
            *(uint32_t*)(regs.esp + 0x0E8) = regs.edi;
            ((void(__cdecl*)(int, signed int, char))0x5C6FA0)(regs.ecx, G_CameraPhotoQuality, true);
        });
    }
Как его перевести в луа?
1730632959195.png
 

MSIshka

Новичок
7
0
Как реализовать систему авто-мута, если допустим 3 раза упопомянули в течении 3 секунд вводить команду /mute?
Lua:
function sampev.onServerMessage(color, text)
    if act then
        local playerid2 = select(2,sampGetPlayerIdByCharHandle(PLAYER_PED))
        local name = sampGetPlayerNickname(playerid2)
        
        lua_thread.create(function()
        if text:find(u8:decode("@") .. name) or text:find(u8:decode("@") .. name:lower()) then
                if text:find(u8:decode("-")) then
                    sampSendChat(u8:decode('[Авто-ответ] Уже бегу отвечать! Среднее время ожидания: 2 минуты'))
                    wait(500)
                    sampSendChat(u8:decode('[Авто-ответ] Если прошло 5 минут и я не ответил,'))
                    wait(500)
                    sampSendChat(u8:decode('[Авто-ответ] Отправьте ещё раз. Попытка флуда карается МУТОМ!'))
                elseif text:find(u8:decode("%[%+%]")) then
                    sampAddChatMessage(u8:decode('Пропускаю лишний спам'),-1)

                elseif text:find(u8:decode("от%sсаппорта%s(%w+_%w+):")) then
                    local nicka = text:match(u8:decode("от%sсаппорта%s(%w+_%w+):"))
                    local ida = sampGetPlayerIdByNickname(nicka)
                    sampSendChat(u8:decode('/pm ') .. ida .. u8:decode(' [Авто-ответ] Уже бегу отвечать! Среднее время ожидания: 2 минуты'))
                    sampSendChat(u8:decode('/pm ') .. ida .. u8:decode(' [Авто-ответ] Если прошло 5 минут и я не ответил,'))
                    sampSendChat(u8:decode('/pm ') .. ida .. u8:decode(' [Авто-ответ] Отправьте ещё раз. Попытка флуда карается МУТОМ!'))
                    goto end_chat

                elseif text:find(u8:decode("от%sадмина%s(%w+_%w+):")) then
                    local nicka = text:match(u8:decode("от%sадмина%s(%w+_%w+):"))
                    local ida = sampGetPlayerIdByNickname(nicka)
                    sampSendChat(u8:decode('/pm ') .. ida .. u8:decode(' [Авто-ответ] Уже бегу отвечать! Среднее время ожидания: 2 минуты'))
                    sampSendChat(u8:decode('/pm ') .. ida .. u8:decode(' [Авто-ответ] Если прошло 5 минут и я не ответил,'))
                    sampSendChat(u8:decode('/pm ') .. ida .. u8:decode(' [Авто-ответ] Отправьте ещё раз. Попытка флуда карается МУТОМ!'))
                    goto end_chat
                else
                    sampSendChat(u8:decode('/a [Авто-ответ] Уже бегу отвечать! Среднее время ожидания: 2 минуты'))
                    wait(500)
                    sampSendChat(u8:decode('/a [Авто-ответ] Если прошло 5 минут и я не ответил,'))
                    wait(500)
                    sampSendChat(u8:decode('/a [Авто-ответ] Отправьте ещё раз. Попытка флуда карается МУТОМ!'))
                end
            ::end_chat::
            sendTelegramNotification(text)
        end
    end)
 

Дядя Энрик.

Активный
334
80
реализовал по другому, через wait ошибку выдает
Lua:
local sampev = require 'lib.samp.events'
local screenshotPending = false

function main()
    if not isSampLoaded() or not isSampfuncsLoaded() then return end
    while not isSampAvailable() do wait(100) end

   
    while true do
        wait(0)

        if screenshotPending then
            wait(1000)
            makeScreenshot()
            sampAddChatMessage('{ff0000}[Meteo]:{FFFFFF} Скриншот сделан.', -1)
            screenshotPending = false
        end
    end
end

require('lib.samp.events').onShowDialog = function(dialogId, style, title, button1, button2, text)
    if dialogId == 46 then
        if text:find('Отличная работа, вот твои деньги! Мы немедленно подключим метеозонд к нашей сети и начнем принимать с него данные!') then
            sampAddChatMessage('{ff0000}[Meteo]:{FFFFFF} Скриншот выполнен...', -1)
            screenshotPending = true
        end
    end
end

function makeScreenshot(disable)
    if disable then
        displayHud(false)
        sampSetChatDisplayMode(0)
    end

    -- Считываем значение для создания скриншота
    require('memory').setuint8(sampGetBase() + 0x119CBC, 1)

    if disable then
        displayHud(true)
        sampSetChatDisplayMode(2)
    end
end
Lua:
local sampev = require 'lib.samp.events'
local screenshotPending = false

function main()
    if not isSampLoaded() or not isSampfuncsLoaded() then return end
    while not isSampAvailable() do wait(100) end

    
    while true do
        wait(0)

        if screenshotPending then
            makeScreenshot()
            screenshotPending = false
        end
    end
end

require('lib.samp.events').onShowDialog = function(dialogId, style, title, button1, button2, text)
    if dialogId == 46 then
        if text:find('Отличная работа, вот твои деньги! Мы немедленно подключим метеозонд к нашей сети и начнем принимать с него данные!') then
            lua_thread.create(function() wait(1000)
                screenshotPending = true
                sampAddChatMessage('{ff0000}[Meteo]:{FFFFFF} Скриншот выполнен...', -1)
            end)
        end
    end
end

function makeScreenshot(disable)
    if disable then
        displayHud(false)
        sampSetChatDisplayMode(0)
    end

    -- Считываем значение для создания скриншота
    require('memory').setuint8(sampGetBase() + 0x119CBC, 1)

    if disable then
        displayHud(true)
        sampSetChatDisplayMode(2)
    end
end
 

Naito

Участник
69
19
How to send a message to the chat when I collide with the vehicle? That is, when I collide with my vehicle, a message is sent to the chat saying that it crashed.