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

Dmitriy Makarov

25.05.2021
Проверенный
2,500
1,131
Может это поможет.)

он не крашится, просто не работают некоторые функции
У тебя диалоговые окна с полем ввода, а ты делал проверку на list, т.е на строчки, которых там нет, вот и не работало. =)
Проверку на list надо убрать и всё.
Lua:
local result, button, list, input = sampHasDialogRespond(16)
if result then
    if button == 1 then
        sampSendChat("/sellmycar "..tostring(playerid).." "..input)
    end
end

local result, button, list, input = sampHasDialogRespond(17)
if result then
    if button == 1 then
        sampSendChat("/sellmyhome "..tostring(playerid).." "..input)
    end
end

local result, button, list, input = sampHasDialogRespond(18)
if result then
    if button == 1 then
        sampSendChat("/sellmybiz "..tostring(playerid).." "..input)
    end
end

local result, button, list, input = sampHasDialogRespond(19)
if result then
    if button == 1 then
        sampSendChat("/changecar "..tostring(playerid).." "..input)
    end
end

local result, button, list, input = sampHasDialogRespond(20)
if result then
    if button == 1 then
        sampSendChat("/changehome "..tostring(playerid).." "..input)
    end
end

local result, button, list, input = sampHasDialogRespond(21)
if result then
    if button == 1 then
        sampSendChat("/changebiz "..tostring(playerid).." "..input)
    end
end

Теперь работает всё. Ну, по крайней мере у меня. :0
P.S: nil потому что я на локальном сервере тестил.
sa-mp-006.png
 
Последнее редактирование:
  • Нравится
Реакции: abnomegd

salominka

Новичок
14
1
Как можно сделать парсинг визальных строк в чате?(в чате оно есть, а в чат логе нет)
Отпишите в ТГ плиз, если поможете, накину денюжку.
 

#SameLine

Активный
421
38
Возможно ли сделать такое, в окне imgui, если например убовляется текст то размер окна сам настраивается, если что-то добавляется в строку он прибовляется, если текст имеет больше строк сам подбирает ширину, такое стояло автоматом, пока не добавил позицию для окна
up
 

Dmitriy Makarov

25.05.2021
Проверенный
2,500
1,131
Как можно сделать парсинг визальных строк в чате?(в чате оно есть, а в чат логе нет)
Отпишите в ТГ плиз, если поможете, накину денюжку.
Это что за строки такие?) И как они выглядят? Ты про те, что выводятся с помощью другого скрипта?

Как переобразовать string в hex?
Вроде оно. Источник: link
Lua:
function string.tohex(str)
    return (str:gsub('.', function (c)
        return string.format('%02X', string.byte(c))
    end))
end

print(string.tohex("Text"))
-- out: 54657874

Здарова парни, как реализовать такую штуку в имгуи?:

(К примеру)

Слева textbuffer, справа кнопка с какой-либо иконкой.

Если к примеру в буфере что-то введено, и кнопка находится в первоначальном состоянии, то содержимое буфера шифруется, по типу ••••••••••.

А если нажать на кнопку, иконка сменится и содержимое буфера перейдет в нормальное, читабельном состояние.
Вариант без иконок: (Лёгкий, так как не придётся загружать шрифт, библиотеку)

Lua:
local buffer = imgui.ImBuffer(256)
local showpass = true -- Переменная, которая отвечает за показ пароля.
-- True - не показывается, False - показывается

-- OnDrawFrame()
imgui.InputText("##", buffer, showpass and imgui.InputTextFlags.Password or nil)
imgui.SameLine()
if imgui.Button((showpass and "Show" or "Hide").." password") then
    showpass = not showpass
end
Screenshot_3.png

Screenshot_4.png


Вариант с иконкой:
Lua:
local fa = require 'fAwesome5'
local fa_font = nil
local fa_glyph_ranges = imgui.ImGlyphRanges({fa.min_range, fa.max_range})

local buffer = imgui.ImBuffer(256)
local showpass = true

-- https://www.blast.hk/threads/19292/post-335148
function imgui.BeforeDrawFrame()
    if fa_font == nil then
        local font_config = imgui.ImFontConfig()
        font_config.MergeMode = true
        fa_font = imgui.GetIO().Fonts:AddFontFromFileTTF('moonloader/resource/fonts/fa-solid-900.ttf', 13.0, font_config, fa_glyph_ranges)
    end
end

-- OnDrawFrame
imgui.InputText("##", buffer, showpass and imgui.InputTextFlags.Password or nil)
imgui.SameLine()
if imgui.Button((showpass and fa.ICON_FA_EYE or fa.ICON_FA_EYE_SLASH)) then
    showpass = not showpass
end

Screenshot_1.png

Screenshot_2.png
 
Последнее редактирование:
  • Нравится
  • Влюблен
Реакции: Shepi и ARMOR

Shepi

Активный
178
37
Народ, как сделать слева менюшку в имгуи по типу ультрафака?
IMG_20210826_213725.jpg


И что-бы по нажатию на кнопку открывалось отдельное меню

Пж, хелп
 

Andrinall

Известный
702
518
Итак, начну с того, что нужна помощь в адаптации этого замечательного говнокода под все разрешения экрана, а именно для аргументов функции RenderFilledCircle.
У меня уже просто мозг закипел от количества перепробованных способов реализации, но что-то всё в пустую.
Надо было лучше учить матешу в школе, видимо.

Кратко о роли этого кода:
Это некое подобие фастмапа, но в оболочке имгуи и на луа.

"Почему просто не использовать фастмап?" -
Во-первых, он конфликтует с собейтом, по крайней мере у меня в сборке.
Во-вторых, в фастмап не сунешь кастомную карту(больше стандартной по отрисовке, например рисовать что-то за пределами дефолт карты).

С отображением самой карты на разных разрешениях я разобрался.
Lua:
imgui.SetCursorPos( imgui.ImVec2( -sw/2 + sw/2, -sh/3 ) )
imgui.Image( map_image, imgui.ImVec2( sw, sh*1.6 ) )
А вот с позицией кружка(игрока) на этой карте у меня большие проблемы.
Уже даже костылить пробовал через if else ( что видно в приложенном в коде ), но даже так всё пошло по одному месту.

На всякий случай приложу png к сообщению. Вдруг кто-то захочет помочь.
Заранее благодарен.

Lua:
local map_win = imgui.ImBool( false )
local pos = Vector( 0,0,0 )  -- позиция игрока. Обновляется в while true do (Думаю можно было бы и в имгуи это пихнуть,
-- но с этим проблем нет, обновляется адекватно
local curpos = { x = 0, y = 0 }
local map_image
local points_offset = 3 -- при смещении на это число по одной из 2х осей (x или y) будет обновляться позиция игрока pos

function main()
    while not isSampfuncsLoaded() do wait( 100 ) end
    repeat wait( 100 ) until isSampAvailable()
    
    map_image = imgui.CreateTextureFromFile( getWorkingDirectory().."\\resource\\map.png" )
   
    while true do wait( 0 )
        if isKeyDown( VK_M ) and checked() then -- checked() - вынесенная в отдельную функцию проверка на открытый чат и т.д.
            map_win.v = true
            
            if isCharInAnyCar( PLAYER_PED ) then
                local buf_pos = Vector( getCarCoordinates( storeCarCharIsInNoSave( PLAYER_PED ) ) )
                if buf_pos.x > pos.x + points_offset or buf_pos.x < pos.x - points_offset or
                   buf_pos.y > pos.y + points_offset or buf_pos.y < pos.y - points_offset then
                    
                    pos = buf_pos
                end
            else
                local buf_pos = Vector( getCharCoordinates( PLAYER_PED ) )
                if buf_pos.x > pos.x + points_offset or buf_pos.x < pos.x - points_offset or
                   buf_pos.y > pos.y + points_offset or buf_pos.y < pos.y - points_offset then
                    
                    pos = buf_pos
                end
            end
        elseif wasKeyReleased( VK_M ) then
            map_win.v = false
        end
        
        imgui.Process = map_win.v
    end
end

function imgui.OnDrawFrame()
    sw, sh = getScreenResolution()
    sx, sy = ( sw + 1 )/640, ( sh + 2 )/448
    -- pos.x = 0; pos.y = 0 -- это просто тестовая строка, которой я выравнивал центр карты приблизительно на нулевые координаты.
    
    local p = imgui.GetCursorScreenPos()
    local mapCenter = {
        x = ( -sw/2 + sw/2 ) + ( sw/2 ) - ( sx*( sx^1.35 ) ),
        y = ( -sh/3 ) + ( ( sh*1.6 )/2 ) - ( sy*( sx^2.05 ) )
    }
    
    if not map_image or not player_circle then error('Image not found') end -- если нет какого-то изображения - выдаём ошибку
    
    imgui.ShowCursor = false

    imgui.GetStyle().Colors[imgui.Col.WindowBg] = imgui.ImVec4(0.1, 0.1, 0.1, 0.6) -- по непонятным причинам у меня не работает pushstyle
    -- в простом imgui, только в mimgui
    imgui.GetStyle().WindowRounding = 0.0

    imgui.SetNextWindowPos(imgui.ImVec2(0, 0))
    imgui.SetNextWindowSize(imgui.ImVec2(sw, sh))
    
    imgui.Begin("##map", map_win, imgui.WindowFlags.NoCollapse + imgui.WindowFlags.NoResize + imgui.WindowFlags.NoTitleBar + imgui.WindowFlags.NoMove + imgui.WindowFlags.NoScrollbar)
        
    imgui.SetCursorPos( imgui.ImVec2( -sw/2 + sw/2, -sh/3 ) )
    imgui.Image( map_image, imgui.ImVec2( sw, sh*1.6 ) ) -- карта отображается нормально, тут всё ок.
        
    if pos.x < 0 then
        curpos.x = mapCenter.x + ( pos.x / ( p.x/( sx*2.2 ) ) )
    else
        curpos.x = mapCenter.x + ( pos.x / ( p.x/( sx*2.77 ) ) )
    end
    
    if pos.y > 0 then
        curpos.y = mapCenter.y - ( pos.y / ( p.y/( sy*3.7 ) ) )
    else
        curpos.y = mapCenter.y - ( pos.y / ( p.y/( sy*3.95 ) ) ) + 2
    end
    
    imgui.RenderFilledCircle( curpos.x, curpos.y, 6.5 ) -- а вот это как раз метка игрока ( красный круг ), и именно с ним у меня
    -- проблема, а вернее с его позицией.

    -- Мне нужно, чтобы он чётко следовал по дорогам на любом разрешении.
    -- Конечно, если можно, чтобы его размер так же соответствовал разрешению экрана.
    -- Функция для отрисовки ниже в коде.
        
    imgui.End()
end

function imgui.RenderFilledCircle( x, y, size, color, borderColor )
    local dl = imgui.GetWindowDrawList()
    local size = size or 9
    local sz = size+0.5
    local col32  = imgui.GetColorU32( color or imgui.ImVec4( 1.0, 0.0, 0.0, 1.0 ) )
    local bcol32 = imgui.GetColorU32( borderColor or imgui.ImVec4( 0.0, 0.0, 0.0, 1.0 ) )

    dl:AddCircleFilled(imgui.ImVec2( x + size*0.5, y + size*0.5 ), size*0.5, col32, 32 )
    dl:AddCircle( imgui.ImVec2( x + sz*0.475, y + sz*0.475 ), sz*0.525, bcol32, 32 )
end

function checked()
    if not sampIsChatInputActive() and not sampIsDialogActive() and not isSampfuncsConsoleActive() and not sampIsCursorActive() then
        return true
    else return false end
end
 

Вложения

  • map.png
    map.png
    374.3 KB · Просмотры: 19

Fluffy1560

Активный
278
34
Почему может не работать?
Сервер присылает такакой текст

[18:11:51] [СЕРВЕР] * Вы успешно устроились на работу грузчика.
[18:11:51] [СЕРВЕР] * Ваша задача доставлять ящики на этажи стройки.

Lua:
function onServerMessage(msg)
if msg:find("* Вы успешно устроились на работу грузчика.") then
     printLog("Ep!")
     defcall = defCallAdd(5000, true, function()
       id = 1
       local x = getCheckx()
       local y = getChecky()
       local z = getCheckz()
       coordMasterStart(x, y, z)
       function onCoordMasterComplete()
        function onTextDrawSetString(textid, text)
        if textid == 2191 then
        local payment = text:match("PAYMENT:_~Y~$(.+)")
        payment = tonumber(payment)
        printLog("PAYMENT: $"..payment)
        if payment >= numbe then
         defCallDelete(defcall)
          printLog("Done!")
      end
       end
      end
     end
end)
end
end
 

trapdoy

Участник
65
8
как с помощью кнопки отправить какое то сообщение? например нажимая на x , у тебя меняется с лаунча на тт
 

Sanchez.

Известный
706
188
как с помощью кнопки отправить какое то сообщение? например нажимая на x , у тебя меняется с лаунча на тт
Lua:
if isKeyJustPressed(VK_X) then
   sampSendChat("/style")
end
Это надо поместить в беск цикл (while true do)

P.s не забудь подключить либу vkeys
 
Последнее редактирование:
  • Bug
Реакции: [w0te]

[w0te]

Потрачен
771
492
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
как с помощью кнопки отправить какое то сообщение? например нажимая на x , у тебя меняется с лаунча на тт
minecraft:
require 'lib.moonloader'

function main()
    repeat wait (0) until isSampAvailable()
    wait(2000)
    --code
    while true do
        wait(0)
        ----------------------
        if wasKeyPressed(0x58)
          sampSendChat("text")
       end
        ----------------------
    end
end
если ты чайник - так лучше будет, чем чел сказал выше
 
Последнее редактирование:
  • Bug
Реакции: PanSeek и Sanchez.

kizn

\ 0 _ 0 /
Всефорумный модератор
2,407
2,090
minecraft:
require 'lib.moonloader'

function main()
    repeat wait (0) until isSampAvailable()
    wait(2000)
    --code
    while true do
        wait(0)
        ----------------------
        if wasKeyPressed(0x58)
          sampSendChat("text")
       end
        ----------------------
    end
end
если ты чайник - так лучше будет, чем чел сказал выше
смысл людям помогать, если ты сам чайник?
 
  • Грустно
Реакции: [w0te]

PanSeek

t.me/dailypanseek
Всефорумный модератор
908
1,775
как с помощью кнопки отправить какое то сообщение? например нажимая на x , у тебя меняется с лаунча на тт
Lua:
local wm = require 'lib.windows.message'
local vkeys = require 'vkeys'

function onWindowMessage(msg, wparam, lparam)
    if msg == wm.WM_KEYUP and wparam == vkeys.VK_X --[[or another key]] then
        sampSendChat('/style'--[[your command]])
    end
end
 
  • Влюблен
  • Нравится
Реакции: James Saula и trapdoy