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

XRLM

Известный
2,563
883
Как я понял, проблема в мерцании текста и самого маркера?
У тебя же два раза wait(0) вначале цикла и до removePointMarker()
Если не решит проблему то хз, это единственное, наверно, что вызывает это.
это не из-за этого точно.
 

TheUnity

Известный
107
37
как получить цену после 'VC$' с диалога?
1662040356024.png
 

XRLM

Известный
2,563
883
как получить цену после 'VC$' с диалога?
Посмотреть вложение 166476
onShowDialog
money = text:match('') в скобки пиши содержимое диалога, вместо "320" пиши (%d+), но тебе надо расставить регулярные, поэтому скачай dialog editor, в диалоге напиши /dedit, скопируй содержимое и скинь сюда, сделаем
 

TheUnity

Известный
107
37
onShowDialog
money = text:match('') в скобки пиши содержимое диалога, вместо "320" пиши (%d+), но тебе надо расставить регулярные, поэтому скачай dialog editor, в диалоге напиши /dedit, скопируй содержимое и скинь сюда, сделаем
Код:
[CODE]{FFFFFF}Предмет: {FDCF28}Бронзовая рулетка{FFFFFF}

Можно получить при ежедневных входах в игру,

или купить на центральном рынке.

Используется для получения {FDCF28}рандомного{FFFFFF} товара

из списка доступного в этой рулетке.



{ffffff}Можно хранить в одной ячейке: {cccccc}100 ед. предмета.

{67BE55}

В наличии: 62 шт.

Стоимость: VC$150 за 1 шт. {FFAA60}(Ср. цена не найдена)



{FFFFFF}Введите какое количество вы хотите {555ABE}КУПИТЬ:



{ff0000}Примечание:

{2E9AFE}Ваших денег хватит на 228 ед. товара.
UPD. вроде разобрался, cпасибо
 
Последнее редактирование:

XRLM

Известный
2,563
883
Код:
[CODE]{FFFFFF}Предмет: {FDCF28}Бронзовая рулетка{FFFFFF}

Можно получить при ежедневных входах в игру,

или купить на центральном рынке.

Используется для получения {FDCF28}рандомного{FFFFFF} товара

из списка доступного в этой рулетке.



{ffffff}Можно хранить в одной ячейке: {cccccc}100 ед. предмета.

{67BE55}

В наличии: 62 шт.

Стоимость: VC$150 за 1 шт. {FFAA60}(Ср. цена не найдена)



{FFFFFF}Введите какое количество вы хотите {555ABE}КУПИТЬ:



{ff0000}Примечание:

{2E9AFE}Ваших денег хватит на 228 ед. товара.
UPD. вроде разобрался, cпасибо
Lua:
local ev = require'lib.samp.events'
function ev.onShowDialog(id, style, title, btn1, btn2 , text)
    local price = text:match('Стоимость: VC%$(%d+) за %d+ шт%. {FFAA60}%(.+%)')
    --code
end
 
Последнее редактирование:
  • Нравится
Реакции: TheUnity

Sadow

Известный
1,438
592
У меня есть две проблемы. Начну с первой. Если стереть text_buffer.v и всё связанное с ним, то скрипт будет рабочим. И вот первая проблема. Когда я начинаю вводить символ в цифровой буффер то скрипт умирает. Вторая проблема. Я хочу чтобы в буффере было сразу показано что введено после перезапуска скрипта. Думаю видно как я пробовал сделать в коде. Скрипт и moonloader.log прикрепляю ниже
 

Вложения

  • moonloader.log
    9.7 KB · Просмотры: 12
  • stats-tg.lua
    8.9 KB · Просмотры: 14

NoName_001

Участник
152
21
выключать курсор надо

У тебя много фпс упадет от этого??


Тогда к чему ты доебался? гений..

Посмотреть вложение 166433
1. делать заранее неоптимизированные скрипты круто, чел?
2. код по типу
Lua:
while true do
    a = true
end
вообще не имеет смысла. зачем? каждый раз присваивается одно и то же значение, оно ни разу не изменится? зачем оно в цикле, чел?
3. мне нужен курсор. он багается иногда с другими скриптами на имгуи/мимгуи. зачем мне процесс активный, который не используется для отображения окон? он юзлес, чел

У меня есть две проблемы. Начну с первой. Если стереть text_buffer.v и всё связанное с ним, то скрипт будет рабочим. И вот первая проблема. Когда я начинаю вводить символ в цифровой буффер то скрипт умирает. Вторая проблема. Я хочу чтобы в буффере было сразу показано что введено после перезапуска скрипта. Думаю видно как я пробовал сделать в коде. Скрипт и moonloader.log прикрепляю ниже
Lua:
imgui.ImBuffer(144)
почему 144


Lua:
local text_buffer_one = imgui.ImBuffer(144)
local text_buffer_two = imgui.ImBuffer(144)
local text_buffer_three = imgui.ImBuffer(144)
text_buffer_one.v = mainIni.config.Token
text_buffer_two.v = mainIni.config.Chat_Id
text_buffer_three.v = mainIni.config.MaxMoney
это можно написать компактее(просто совет)


Lua:
    if imgui.InputText(u8'Токен', text_buffer_one) then
        text_buffer_one.v = mainIni.config.Token
        inicfg.save(mainIni, directIni)
    end
разве это должно работать так, а не так:
Lua:
    if imgui.InputText(u8'Токен', text_buffer_one) then
        mainIni.config.Token = text_buffer_one.v
        inicfg.save(mainIni, directIni)
    end
ты же сохраняешь в файл.ini из переменной
а не переменную из файла
попробуй их местами поменять :D
пробуй работоспособность без ini(принтуй, дебагай :D)
обратись еще раз, если что-то не получится

а еще в логе нашел, что у тебя библиотеки какой-то не хватает (MoonBot_DEMO)

Lua:
    no file 'D:\Games\morty summer low\moonloader\lib\MoonBot_DEMO.lua'
    no file 'D:\Games\morty summer low\moonloader\lib\MoonBot_DEMO\init.lua'
    no file 'D:\Games\morty summer low\moonloader\MoonBot_DEMO.lua'
    no file 'D:\Games\morty summer low\moonloader\MoonBot_DEMO\init.lua'
    no file '.\MoonBot_DEMO.lua'
    no file 'D:\Games\morty summer low\moonloader\lib\MoonBot_DEMO.luac'
    no file 'D:\Games\morty summer low\moonloader\lib\MoonBot_DEMO\init.luac'
    no file 'D:\Games\morty summer low\moonloader\MoonBot_DEMO.luac'
    no file 'D:\Games\morty summer low\moonloader\MoonBot_DEMO\init.luac'

а еще судя по этим строкам
проблема в библиотеке imgui-notification
уведомления в общем

Lua:
[21:43:30.296165] (error)    lib_imgui_notf.lua: cannot resume non-suspended coroutine
stack traceback:
    [C]: in function 'SetMouseCursor'
    D:\Games\morty summer low\moonloader\lib_imgui_notf.lua:103: in function <D:\Games\morty summer low\moonloader\lib_imgui_notf.lua:99>
 
Последнее редактирование:

bab0n

Известный
95
10
не проигрывается звук в свёрнутом режиме (работу в свернётом юзаю из Connection Tools)
Если игра в окнном режиме и свёрнута, то тоже не проигрывается
Код функции (пробовал и не с 3д аудио, вопрос не решался)
Cделал тест без сборщика, не помогло
addOneOffSound() - работает в свёрнутом режиме


Lua:
local audio = load3dAudioStream('moonloader/notify.mp3')
function Notify()
    local x, y, z = getCharCoordinates(PLAYER_PED)
    setPlay3dAudioStreamAtCoordinates(audio, x, y, z)
    --setPlay3dAudioStreamAtChar(audio, PLAYER_PED)
    setAudioStreamVolume(audio, settings.notify_valume)
    setAudioStreamState(audio, 1)
    lua_thread.create(function()
        while getAudioStreamState(audio) == 1 do wait(50) end
        collectgarbage()
    end)
end
 
Последнее редактирование:

Smeruxa

Известный
1,307
686
1. делать заранее неоптимизированные скрипты круто, чел?
Вопросом на вопрос не отвечай, зачем доебался?
3. мне нужен курсор. он багается иногда с другими скриптами на имгуи/мимгуи. зачем мне процесс активный, который не используется для отображения окон? он юзлес, чел
че ты несешь? Если он багается - то это твоя вина, причем тут imgui.Process = true?????????????????????????????????????????????????????????????????????????????????
вообще не имеет смысла. зачем? каждый раз присваивается одно и то же значение, оно ни разу не изменится? зачем оно в цикле, чел?
Первоначально так делал, привычка закрепилась, но все тот же вопрос, че за херню ты несешь? Как минимум, чем тебе это помешает? Это линейная сложность, здесь ничего не поменяется от этого, ммде. Тем более что этот метод бесполезный говорить - полная тупость.

делать заранее неоптимизированные скрипты круто, чел?
У тебя даже 1 фпс не упадет

не проигрывается звук в свёрнутом режиме (работу в свернётом юзаю из Connection Tools)
Если игра в окнном режиме и свёрнута, то тоже не проигрывается
Код функции (пробовал и не с 3д аудио, вопрос не решался)


Lua:
local audio = load3dAudioStream('moonloader/notify.mp3')
function Notify()
    local x, y, z = getCharCoordinates(PLAYER_PED)
    setPlay3dAudioStreamAtCoordinates(audio, x, y, z)
    --setPlay3dAudioStreamAtChar(audio, PLAYER_PED)
    setAudioStreamVolume(audio, settings.notify_valume)
    setAudioStreamState(audio, 1)
    lua_thread.create(function()
        while getAudioStreamState(audio) == 1 do wait(50) end
        collectgarbage()
    end)
end
Звук проигрывается в игре, попробуй анти афк, МОЖЕТ БЫТЬ поможет

что за переменная elements? её нет, поэтому крашит скрипт
Для тебя исправлю
fonts.clickWarp измени на свой шрифт
Lua:
function clickWarp()
    lua_thread.create(function()
        while true do
            if cursorEnabled then
                local mode = sampGetCursorMode()
                if mode == 0 then
                    showCursor(true)
                end
                local sx, sy = getCursorPos()
                local scx, scy = getScreenResolution()
                local sw, sh = scx, scy
                local color = join_argb(255, 255, 255, 255)
                if sx >= 0 and sy >= 0 and sx < sw and sy < sh then
                    local posX, posY, posZ = convertScreenCoordsToWorld3D(sx, sy, 700.0)
                    local camX, camY, camZ = getActiveCameraCoordinates()
                    local result, colpoint = processLineOfSight(camX, camY, camZ, posX, posY, posZ, true, true, false, true, false, false, false)
                    if result and colpoint.entity ~= 0 then
                        local normal = colpoint.normal
                        local pos = Vector3D(colpoint.pos[1], colpoint.pos[2], colpoint.pos[3]) - (Vector3D(normal[1], normal[2], normal[3]) * 0.1)
                        local zOffset = 300
                        if normal[3] >= 0.5 then zOffset = 1 end
                        local result, colpoint2 = processLineOfSight(pos.x, pos.y, pos.z + zOffset, pos.x, pos.y, pos.z - 0.3, true, true, false, true, false, false, false)
                        if result then
                            pos = Vector3D(colpoint2.pos[1], colpoint2.pos[2], colpoint2.pos[3] + 1)
                            local curX, curY, curZ  = getCharCoordinates(playerPed)
                            local dist              = getDistanceBetweenCoords3d(curX, curY, curZ, pos.x, pos.y, pos.z)
                            local hoffs             = renderGetFontDrawHeight(fonts.clickWarp)
                            sy = sy - 2
                            sx = sx - 2
                            renderFontDrawText(fonts.clickWarp, string.format("%0.2fm", dist), sx, sy - hoffs, color)
                            local tpIntoCar = nil
                            if colpoint.entityType == 2 then
                                local car = getVehiclePointerHandle(colpoint.entity)
                                if doesVehicleExist(car) and (not isCharInAnyCar(playerPed) or storeCarCharIsInNoSave(playerPed) ~= car) then
                                    displayVehicleName(sx, sy - hoffs * 2, getNameOfVehicleModel(getCarModel(car)))
                                    if isKeyDown(VK_RBUTTON) then
                                        tpIntoCar = car
                                    end
                                    renderFontDrawText(fonts.clickWarp, "Hold right mouse button to teleport into the car", sx, sy - hoffs * 3, color)
                                end
                            end
                            createPointMarker(pos.x, pos.y, pos.z)
                            if isKeyDown(VK_LBUTTON) then
                                if tpIntoCar then
                                    if not jumpIntoCar(tpIntoCar) then
                                        teleportPlayer(pos.x, pos.y, pos.z)
                                        local veh = storeCarCharIsInNoSave(playerPed)
                                        local cordsVeh = {getCarCoordinates(veh)}
                                        setCarCoordinates(veh, cordsVeh[1], cordsVeh[2], cordsVeh[3])
                                        cursorEnabled = false
                                        showCursor(false)
                                        removePointMarker()
                                        break
                                    end
                                else
                                    if isCharInAnyCar(playerPed) then
                                        local norm = Vector3D(colpoint.normal[1], colpoint.normal[2], 0)
                                        local norm2 = Vector3D(colpoint2.normal[1], colpoint2.normal[2], colpoint2.normal[3])
                                        rotateCarAroundUpAxis(storeCarCharIsInNoSave(playerPed), norm2)
                                        pos = pos - norm * 1.8
                                        pos.z = pos.z - 1.1
                                    end
                                    teleportPlayer(pos.x, pos.y, pos.z)
                                    cursorEnabled = false
                                    showCursor(false)
                                    removePointMarker()
                                    break
                                end
                                while isKeyDown(VK_LBUTTON) do wait(0) end
                                cursorEnabled = false
                                showCursor(false)
                                removePointMarker()
                                break
                            end
                        end
                    end
                end
            end
            wait(0)
            removePointMarker()
        end
        cursorEnabled = false
        showCursor(false)
        removePointMarker()
    end)
end

3. мне нужен курсор. он багается иногда с другими скриптами на имгуи/мимгуи. зачем мне процесс активный, который не используется для отображения окон? он юзлес, чел
Если прям ОООООООООООЧЕНЬ хочешь то делай так:
Lua:
if not window.v and not window2.v and not window3.v and not window4.v then
    imgui.Process = false
else
    imgui.Process = true
end
Как думаешь, в этом примере какой вариант лучше?
Как вариант еще можно при команде определенной запускать, задать процесс, все делать дважды. Ну делай как хочешь раз таки

почему нет?

это можно написать компактее(просто совет)
можно демонстрацию? mb так?
Lua:
local text_buffer_one = imgui.ImBuffer(tostring(mainIni.config.Token), 144)
Дал человеку совет ничего не объяснив. лучший.
 
Последнее редактирование:
  • Эм
Реакции: bab0n

NoName_001

Участник
152
21
Вопросом на вопрос не отвечай, зачем доебался?
прекрати браниться
чего такой злой
че ты несешь? Если он багается - то это твоя вина, причем тут imgui.Process = true?????????????????????????????????????????????????????????????????????????????????
код других скриптов(от других авторов) (особенно старых версий moon) и мой код могут конфликтовать, я просто это упомянул, чего такая реакция дикая
Первоначально так делал, привычка закрепилась, но все тот же вопрос, че за херню ты несешь? Как минимум, чем тебе это помешает? Это линейная сложность, здесь ничего не поменяется от этого, ммде. Тем более что этот метод бесполезный говорить - полная тупость.
Lua:
function main()
    -- code
    imgui.process = true
    while true do wait(0)
        -- code
    end
end
-- ИЛИ
function main()
    -- code
    while true do wait(0)
        imgui.process = true
    end
end
объясни, зачем каждый кадр присваивать значение true переменной, если оно не меняется? (пример №2)
Как думаешь, в этом примере какой вариант лучше?
Как вариант еще можно при команде определенной запускать, задать процесс, все делать дважды. Ну делай как хочешь раз таки
это рофельный код?
Lua:
while true do wait(0)
    -- code
    imgui.process = window.v or window2.v or windowN.v
end
поинтересовался, почему именно 144
чо не так?
можно демонстрацию? mb так?
так
Дал человеку совет ничего не объяснив. лучший.
прочитать документацию к ImBuffer 3 минуты
я не нянька, чтобы все на блюдечке

прекращай свои попытки самоутвердиться ни на чем, ты мне не особо интересен
(работу в свернётом юзаю из Connection Tools)
подробнее пожалуйста
и фулл код бы не помешал
 

artie

Участник
70
20
Как можно при онлайне на сервере больше определённого числа выполнить блок кода?
Может через sampGetPlayerCount как-то можно? А то я пока что умею только просто его количество выводить
 

XRLM

Известный
2,563
883
Как можно при онлайне на сервере больше определённого числа выполнить блок кода?
Может через sampGetPlayerCount как-то можно? А то я пока что умею только просто его количество выводить
Lua:
local players = sampGetPlayerCount(false)
if players == "сюда свое количество игроков пиши без скобок" then
--code
end
я с такой функцией не сталкивался, поэтому может не работать, проверь
 
  • Влюблен
Реакции: artie