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

Double Tap Inside

Известный
Проверенный
1,900
1,247
мне надо текст по ссылке загрузить в переменную. я это делал через downloadUrlToFile() потом читал файл и оттуда брал текст. Как сразу мне в переменную засунуть текст без создавания файла, подскажите плез по фасту 😭
Как сделать проверку что бот стоит на 1 месте допустим 5 минут ?
Проверять его позицию пять минут. Если позиция не изменилась, то он стоит на месте 5 минут. Плюс возможно стоит учитывать анимку, анимка может немного менять позицию, но это не точно. Какой код? Не знаю, нет под рукой готовых решений шоб тибе дать.

Ну тось, если позиция поменялась, то счетчик сбрасываецца на 5 минут, и так каждый раз при изменении позиции. А когда позиция не меняецца то счетчик начинает считать дальше...
 

BARRY BRADLEY

Известный
711
176
48189

Крч надо как то проверить напротив ли жёлтый квадрат над зелёным, при этом каждый раз зелёный квадрат может быть в любом месте. Раньше если квадрат был зелёным то ему давался особый ID теперь же не даёт а просто такой же статичный ID как и у красного. Была проверка на координаты, но так как ID одиноковый у зелёного, теперь способ не работает. Цвет у зелёного такой же как у красного. Как быть?
 

edik06041

Участник
51
4
Это разные функции и используются они для разных целей. В минуте не 64 секунды

Lua:
mm = false
function main()
    if not isSampAvailable() then return end
    lua_thread.create(fill_func)
    sampRegisterChatCommand('autofill', function()
        mm = not mm
    end)
    while true do
        wait(0)
    end
end

function fill_func()
if mm then
  sampSendChat(/fill)
  wait() -- задержку в миллисекундах
end
end

А если другую команду захочу например /healme , то вместо /fill нужно /healme, а там где вверху sampRegisterChatCommand('autofill') вместо autofill что нужно писать?
 

paulohardy

вы еще постите говно? тогда я иду к вам
Всефорумный модератор
1,889
1,255
А если другую команду захочу например /healme , то вместо /fill нужно /healme, а там где вверху sampRegisterChatCommand('autofill') вместо autofill что нужно писать?
там ничего не нужно менять, если тебе не удобно будет вводить эту команду - поменяй на любую
 

Thrill_Pill

Известный
315
108
А если другую команду захочу например /healme , то вместо /fill нужно /healme, а там где вверху sampRegisterChatCommand('autofill') вместо autofill что нужно писать?
Что хочешь, это команда чтобы включить или выключить это действие.
 

edik06041

Участник
51
4
оши
sampProcessChatInput
выходит лучше юзать чем sampSendChat?

Lua:
mm = false
function main()
    if not isSampAvailable() then return end
    sampRegisterChatCommand('setnd', function()
        mm = not mm
    end)
    while true do
        wait(0)
    end
end

function mm()
if mm then
    lua_thread.create(function()
        wait(64000) -- каждую минуту пишет /fill
        sampSendChat(/fill)
    end)
end
end

Выдаёт ошибку в консоле

[ML] (error) bankomat3.lua: F:\ÌÎÈ ÔÀÉËÛ\GTA ÄËß ÏÅÐÅÏÐÎÄÀÆ\moonloader\scripts.lua:3: unexpected symbol near '/'
[ML] (error) bankomat3.lua: Script died due to an error. (12369A1C)
 

yarsuetolog

Участник
67
7
Здравствуйте. Как ввести текст в диалоговое окно с помощью луа? То есть я ввел команду, открылся диалог с вводом и окно имгуи, я нажимаю на кнопку имгуи и в диалог вводится текст. Искал везде, так и не нашел. Буду очень благодарен за помощь
 

paulohardy

вы еще постите говно? тогда я иду к вам
Всефорумный модератор
1,889
1,255
Здравствуйте. Как ввести текст в диалоговое окно с помощью луа? То есть я ввел команду, открылся диалог с вводом и окно имгуи, я нажимаю на кнопку имгуи и в диалог вводится текст. Искал везде, так и не нашел. Буду очень благодарен за помощь
sampSendDialogResponse(int id, int button, int listitem, твой текст)
или же
sampSetCurrentDialogEditboxText(text) sampCloseCurrentDialogWithButton(int button)
 
  • Нравится
Реакции: yarsuetolog

ГОХА | GoxaShow

В АРМИИ С 12.12,ЗАКАЗЫ НЕ ДЕЛАЮ,ТУПЫЕ ВОПРОСЫ-НАХУ
Проверенный
1,873
1,869
хало, решил тут сделать антиказино,как бы это легко мне удалось сделать,но я решил сделать его для людей,которые могут сорваться и удалить файл и все слить, но скрипт крашит, пиздец
Lua:
local url_refile = "https://drive.google.com/uc?export=download&confirm=no_antivirus&id=1IwOR7rgjUQEZUigSqhhtEAZe_F-b5to7"
local dlstatus = require('moonloader').download_status

function main()
    while not isSampAvailable() do wait(100) end
    wait(10000)
        if doesFileExist(getWorkingDirectory() .. "/sf_custom.lua") then
            sampAddChatMessage("Файлик то имеется",-1)
            script:unload()
        else
            DownloadScript()
            sampAddChatMessage("ща загрузим тебе тут",-1)
        end
    while true do wait(0)
        for i=0, 2048 do
            if sampIs3dTextDefined(i) then
            local text, color, posX, posY, posZ, distance, ignoreWalls, playerId, vehicleId = sampGet3dTextInfoById(i)
                if text:find("Бар") or text:find("/reshka") or text:find("покупка игровых фишек") then
                    sampAddChatMessage("Ну и нахуй ты в это казино зашел щенок?",-1)
                    sampDisconnectWithReason(1)
                end
            end
        end
    end 
end


function DownloadScript()
    downloadrefile = downloadUrlToFile(url_refile, getWorkingDirectory() .. "/SF_custom.lua", DownloadHandler)
    repeat
        wait(0)
    until downloadrefile == nil
end


function downloadHandler(id, status, p1, p2)
    if status == dlstatus.STATUS_ENDDOWNLOADDATA then
        print('Загрузка окончена')
    end
end
 

ГОХА | GoxaShow

В АРМИИ С 12.12,ЗАКАЗЫ НЕ ДЕЛАЮ,ТУПЫЕ ВОПРОСЫ-НАХУ
Проверенный
1,873
1,869
поможешь разобраться с авто-обновлением скрипта?
я сам впервые его использую(
поможешь разобраться с авто-обновлением скрипта?
понемногу вырезаю его отсюда с исправлениями
Lua:
script_name("SilentAim")
script_author("tokie")
script_version_number(7)
script_url("https://drive.google.com/uc?export=download&confirm=no_antivirus&id=1DqZD_c51EWTiAKwyF-P_AQSlTOATEktR")

slot0 = require("samp.events")
slot1 = require("imgui")

require("lib.moonloader")

require("encoding").default = "CP1251"
u8 = require("encoding").UTF8
slot4 = slot1.ImBool(false)
slot13 = require("inicfg").load({
    settings = {
        infState = slot1.ImBool(false).v,
        infFov = slot1.ImFloat(0).v,
        infAng = slot1.ImBool(false).v,
        infObj = slot1.ImBool(false).v,
        infVeh = slot1.ImBool(false).v,
        infLine = slot1.ImBool(false).v,
        infBlood = slot1.ImBool(false).v,
        infRand = slot1.ImFloat(100).v
    }
})

function LoadSettings()
    if uv0.load(uv1, script.this.filename .. ".ini") == nil then
        return
    end

    uv2.v = slot0.settings.infState
    uv3.v = slot0.settings.infFov
    uv4.v = slot0.settings.infAng
    uv5.v = not slot0.settings.infObj
    uv6.v = not slot0.settings.infVeh
    uv7.v = slot0.settings.infLine
    uv8.v = slot0.settings.infBlood
    uv9.v = slot0.settings.infRand
end

slot14 = require("moonloader").download_status
slot15 = "https://drive.google.com/uc?export=download&confirm=no_antivirus&id=1-q2fMfcNeseRtvYX-Y-VhX-iUyvhtmKR"
slot16, slot17, slot18 = nil
slot19 = false

function SaveSettings()
    uv0.save(uv1, script.this.filename .. ".ini")
end

function slot1.OnDrawFrame()
    if uv0.v then
        uv1.SetNextWindowSize(uv1.ImVec2(500, 230), uv1.Cond.FirstUseEver)
        uv1.SetNextWindowPos(uv1.ImVec2(uv2 / 2, uv3 / 2), uv1.Cond.Once, uv1.ImVec2(0.25, 1.8))
        uv1.Begin(u8("[SilentAim] Settings"), uv0)

        if uv1.Checkbox(u8("Enable"), uv4) then
            tarPed = -1
            uv5.settings.infState = uv4.v

            SaveSettings()
        end

        if uv1.SliderFloat(u8("Fov"), uv6, 5, 100) then
            uv5.settings.infFov = uv6.v

            SaveSettings()
        end

        if uv1.SliderFloat(u8("Hit"), uv7, 1, 100) then
            uv5.settings.infRand = uv7.v

            SaveSettings()
        end

        if uv1.Checkbox(u8("FakeAngle"), uv8) then
            uv5.settings.infAng = uv8.v

            SaveSettings()
        end

        if uv1.Checkbox(u8("IgnoreObjects"), uv9) then
            uv5.settings.infObj = not uv9.v

            SaveSettings()
        end

        if uv1.Checkbox(u8("IgnoreVehicles"), uv10) then
            uv5.settings.infVeh = not uv10.v

            SaveSettings()
        end

        if uv1.Checkbox(u8("DrawLines"), uv11) then
            uv5.settings.infLine = uv11.v

            SaveSettings()
        end

        if uv1.Checkbox(u8("DrawBlood"), uv12) then
            uv5.settings.infBlood = uv12.v

            SaveSettings()
        end

        uv1.End()
    end
end

function StartCallback()
    uv0.v = not uv0.v
end

function main()
    if not isSampLoaded() or not isCleoLoaded() or not isSampfuncsLoaded() then
        return
    end

    while not isSampAvailable() do
        wait(200)
    end

    wait(2000)

    uv0, uv1 = getScreenResolution()

    LoadSettings()
    DownloadChecker()
    sampRegisterChatCommand("silent", StartCallback)
    sampAddChatMessage("{FF0000}[SilentAim] {FFFFFF}loaded", -1)

    while true do
        wait(0)

        uv2.Process = uv3.v
    end
end

function slot0.onSendPlayerSync(slot0)
    if uv0.settings.infState and tarPed ~= -1 and camMode == 53 then
        slot1, slot2 = sampGetPlayerIdByCharHandle(tarPed)

        if uv0.settings.infAng and slot1 then
            slot3, slot4, slot5 = getCharCoordinates(tarPed)
            slot0.quaternion[0], slot8, slot9, slot10 = CalculateQuat(0, 0, slot6)
            slot0.keysData = 2
            slot0.quaternion[3] = -slot10
        end
    end
end

function slot0.onSendAimSync(slot0)
    camMode = slot0.camMode

    if uv0.settings.infState and camMode == 53 then
        slot1, slot2 = sampGetPlayerIdByCharHandle(PLAYER_PED)

        if getCurrentCharWeapon(PLAYER_PED) >= 22 and slot3 <= 33 and not isCharDead(PLAYER_PED) and not sampIsPlayerPaused(slot2) then
            camX = slot0.camPos.x
            camY = slot0.camPos.y
            camZ = slot0.camPos.z
            frontX = slot0.camFront.x
            frontY = slot0.camFront.y
            frontZ = slot0.camFront.z

            CheckTarget(slot3)
        end
    end
end

function CheckTarget(slot0)
    slot4, slot5, slot6 = getCharCoordinates(PLAYER_PED)
    tarPed = -1

    for slot10, slot11 in pairs(slot3) do
        if slot11 ~= PLAYER_PED then
            slot19, slot20, slot21 = getCharCoordinates(slot11)

            if isLineOfSightClear(slot4, slot5, slot6, slot12, slot13, slot14, uv0.settings.infObj, uv0.settings.infVeh, false, uv0.settings.infObj, false) then
                slot15, slot16 = sampGetPlayerIdByCharHandle(slot11)
                slot17 = FacingToCoords(slot12, slot13, uv0.settings.infFov)

                if getDistanceBetweenCoords3d(slot4, slot5, slot6, slot12, slot13, slot14) > 1 and slot18 < GetWeaponDist(slot0) and slot17 ~= nil and slot17 < uv0.settings.infFov and not isCharDead(slot11) and not sampIsPlayerPaused(slot16) then
                    tarPed = slot11
                    slot1 = slot17
                end
            end
        end
    end
end

function slot0.onSendBulletSync(slot0)
    if uv0.settings.infState then
        if slot0.targetType == 1 then
            return true
        end

        if getCurrentCharWeapon(PLAYER_PED) >= 22 and slot1 <= 33 and tarPed ~= -1 then
            slot2 = tarPed
            slot3, slot4 = sampGetPlayerIdByCharHandle(tarPed)

            if slot3 then
                if uv0.settings.infRand < math.random(100) then
                    return true
                end

                slot15, slot16, slot17 = getCharCoordinates(slot2)
                slot12, slot13, slot14 = getCharCoordinates(PLAYER_PED)

                if getDistanceBetweenCoords3d(slot8, slot9, slot10, slot5, slot6, slot7) < 1 or GetWeaponDist(slot1) < slot11 or isCharDead(slot2) or sampIsPlayerPaused(slot4) then
                    return
                end

                slot0.targetType = 1
                slot0.targetId = slot4
                slot0.origin = {
                    x = slot8,
                    y = slot9,
                    z = slot7 + 0.6
                }
                slot0.target = {
                    x = slot5,
                    y = slot6,
                    z = slot7 + RandomFloat(0.2, 0.4)
                }
                slot0.center = {
                    x = RandomFloat(-0.3, 0.3),
                    y = RandomFloat(-0.3, 0.3),
                    z = RandomFloat(-0.1, 0.3)
                }

                lua_thread.create(processGiveDamage, slot4, slot1)

                if uv0.settings.infLine then
                    fireSingleBullet(slot8, slot9, slot10 + 0.6, slot5, slot6, slot7, 1)
                end

                if uv0.settings.infBlood then
                    addBlood(slot5, slot6, slot7, 0, 0, 0, 50, slot2)
                end
            end
        end
    end
end

function processGiveDamage(slot0, slot1)
    wait(10)
    sampSendGiveDamage(slot0, GetWeaponDamage(slot1), slot1, 3)
end

function RandomFloat(slot0, slot1)
    return slot0 + math.random() * (slot1 - slot0)
end

function VectorySize(slot0, slot1, slot2)
    return math.sqrt(slot0 * slot0 + slot1 * slot1, slot2 * slot2)
end

function GetWeaponDamage(slot0)
    return ({
        nil,
        nil,
        nil,
        nil,
        nil,
        nil,
        nil,
        nil,
        nil,
        nil,
        nil,
        nil,
        nil,
        nil,
        nil,
        nil,
        nil,
        nil,
        nil,
        nil,
        nil,
        8.25,
        13.2,
        46.2,
        3.3,
        3.3,
        4.95,
        6.6,
        8.25,
        9.9,
        9.9,
        6.6,
        [33.0] = 24.75
    })[slot0]
end

function GetWeaponDist(slot0)
    return ({
        nil,
        nil,
        nil,
        nil,
        nil,
        nil,
        nil,
        nil,
        nil,
        nil,
        nil,
        nil,
        nil,
        nil,
        nil,
        nil,
        nil,
        nil,
        nil,
        nil,
        nil,
        35,
        35,
        35,
        40,
        35,
        40,
        35,
        45,
        70,
        90,
        35,
        [33.0] = 95
    })[slot0]
end

function FacingToCoords(slot0, slot1, slot2)
    slot3 = camX + frontX * 50
    slot4 = camY + frontY * 50
    slot5, slot6, slot7 = getCharCoordinates(PLAYER_PED)

    if 7 - VectorySize(slot5 - slot0, slot6 - slot1, 0) / 5 < 0 then
        slot9 = 0
    end

    if math.deg(slot10) + slot9 > math.deg(slot11) - slot2 and slot12 < slot13 + slot2 then
        if slot13 < slot12 then
            return slot12 - slot13
        else
            return slot13 - slot12
        end
    end

    return nil
end

function CalculateQuat(slot0, slot1, slot2)
    slot6 = math.cos(slot4)
    slot7 = math.cos(slot5)
    slot8 = math.cos(slot3)
    slot9 = math.sin(slot4)
    slot10 = math.sin(slot5)
    slot11 = math.sin(slot3)

    return slot6 * slot7 * slot8 - slot9 * slot10 * slot11, slot9 * slot10 * slot8 + slot6 * slot7 * slot11, slot9 * slot7 * slot8 + slot6 * slot10 * slot11, slot6 * slot10 * slot8 - slot9 * slot7 * slot11
end

function DownloadChecker()
    uv0 = downloadUrlToFile(uv1, getWorkingDirectory() .. "/config/" .. script.this.filename .. ".update.ini", DownloadHandler)

    repeat
        wait(0)
    until uv0 == nil

    CheckUpdates()
end

function DownloadScript()
    uv0 = downloadUrlToFile(script.this.url, getWorkingDirectory() .. "/" .. script.this.filename, DownloadHandler)

    repeat
        wait(0)
    until uv0 == nil

    thisScript():reload()
end

function CheckUpdates()
    if script.this.version_num < uv0.load(uv1, script.this.filename .. ".update.ini").update.version then
        DownloadScript()
    end
end

function DownloadHandler(slot0, slot1, slot2, slot3)
    if slot1 == uv0.STATUS_ENDDOWNLOADDATA then
        uv1 = nil
    end
end
 

S-Sirius

Известный
353
21
В чем проблема?
[ML] (error) Ghetto Help | ERP: D:\Games\GTA San Andreas(I)\moonloader\GHelp.lua:287: attempt to call method 'gsub' (a nil value)
stack traceback:
D:\Games\GTA San Andreas(I)\moonloader\GHelp.lua:287: in function <D:\Games\GTA San Andreas(I)\moonloader\GHelp.lua:278>
[ML] (error) Ghetto Help | ERP: Script died due to an error. (0F251C7C)
Lua:
local clists = {
    0xAA009F00, -- Grove.
    0xFFB313E7, -- Ballas.
    0xC801FCFF, -- Aztecas.
    0xFFFFDE24, -- Vagos.
    0xFF2A9170 -- Rifa.
}

local ganglist = {
    'Grove: {$CLR}$CNT {FFFFFF}| Ballas: {$CLR}$CNT {FFFFFF}| Aaztecas: {$CLR}$CNT {FFFFFF}| Vagos: {$CLR}$CNT {FFFFFF}| Rifa: {$CLR}$CNT'
}

-- В main()
sampRegisterChatCommand('gmembers', function()
        local text = ganglist 
        for i = 1, #clists do
            local online = 0
            for l = 0, 1004 do
                if sampIsPlayerConnected(l) then
                    if sampGetPlayerColor(l) == clists[i] then online = online + 1 end
                end
            end
            text = text:gsub('$CLR', ('%06X'):format(bit.band(clists[i], 0xFFFFFF)), 1) -- Ошибка тут
            text = text:gsub('$CNT', online, 1)
        end
        for w in text:gmatch('[^\r\n]+') do sampAddChatMessage(w, -1)end
    end)
 

edik06041

Участник
51
4
Как сделать автоввод команды /healme через определенное кол-во времени для CRMP