Вопросы по 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,508
1,136
Может это поможет.)

он не крашится, просто не работают некоторые функции
У тебя диалоговые окна с полем ввода, а ты делал проверку на 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
 

ARMOR

Мне кажется, я всё проебал
Модератор
5,020
7,064
Как переобразовать string в hex?
 

Dmitriy Makarov

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

Как переобразовать 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

Известный
700
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 · Просмотры: 21

Fluffy1560

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

[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

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

Sanchez.

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

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

[w0te]

Потрачен
771
493
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
как с помощью кнопки отправить какое то сообщение? например нажимая на 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

q(≧▽≦q)
Всефорумный модератор
2,406
2,107
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,778
как с помощью кнопки отправить какое то сообщение? например нажимая на 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