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

trefa

Известный
Всефорумный модератор
2,097
1,231
Lua:
script_name('MoD-Helper')
script_authors('Xach')
script_description('Ministry of Defence Helper.')
script_version_number(21)
script_version("0.2.1")
script_properties("work-in-pause")
local res = pcall(require, "lib.moonloader")

assert(res, 'Library lib.moonloader not found')
---------------------------------------------------------------
local res, ffi = pcall(require, 'ffi')
assert(res, 'Library ffi not found')
---------------------------------------------------------------
local dlstatus = require('moonloader').download_status
---------------------------------------------------------------
local res = pcall(require, 'lib.sampfuncs')
assert(res, 'Library lib.sampfuncs not found')
---------------------------------------------------------------
local res, sampev = pcall(require, 'lib.samp.events')
assert(res, 'Library SAMP Events not found')
---------------------------------------------------------------
---------------------------------------------------------------
local res, key = pcall(require, "vkeys")
assert(res, 'Library vkeys not found')
---------------------------------------------------------------
local res, imgui = pcall(require, "imgui")
assert(res, 'Library imgui not found')
---------------------------------------------------------------
local res, encoding = pcall(require, "encoding")
assert(res, 'Library encoding not found')
---------------------------------------------------------------
local res, inicfg = pcall(require, "inicfg")
assert(res, 'Library inicfg not found')
---------------------------------------------------------------
local res, memory = pcall(require, "memory")
assert(res, 'Library memory not found')
---------------------------------------------------------------
local res, rkeys = pcall(require, "rkeys")
assert(res, 'Library rkeys not found')
---------------------------------------------------------------
---------------------------------------------------------------
local lanes = require('lanes').configure()
---------------------------------------------------------------

---------------------------------------------------------------
---------------------------------------------------------------
local res, fa = pcall(require, 'faIcons')
assert(res, 'Library faIcons not found')
---------------------------------------------------------------
local key = require 'vkeys'
------
function apply_custom_style() -- дизайн imgui, цветовая схема уникальная в том плане, что ее нет в сети и сделана руками

    local win_state = {}
    win_state['main'] = imgui.ImBool(false)
    win_state['info'] = imgui.ImBool(false)
    win_state['settings'] = imgui.ImBool(false)
    win_state['hotkeys'] = imgui.ImBool(false)
    win_state['leaders'] = imgui.ImBool(false)
    win_state['help'] = imgui.ImBool(false)
    win_state['about'] = imgui.ImBool(false)
    win_state['update'] = imgui.ImBool(false)
    win_state['player'] = imgui.ImBool(false)
    win_state['base'] = imgui.ImBool(false)
    win_state['informer'] = imgui.ImBool(false)
    win_state['regst'] = imgui.ImBool(false)
    win_state['renew'] = imgui.ImBool(false)
    win_state['find'] = imgui.ImBool(false)
    win_state['ass'] = imgui.ImBool(false)
    win_state['leave'] = imgui.ImBool(false)



    imgui.SwitchContext()
    local style = imgui.GetStyle()
    local colors = style.Colors
    local clr = imgui.Col
    local ImVec4 = imgui.ImVec4
    local ImVec2 = imgui.ImVec2

    style.WindowPadding = ImVec2(15, 15)
    style.WindowRounding = 5.0
    style.FramePadding = ImVec2(5, 5)
    style.FrameRounding = 4.0
    style.ItemSpacing = ImVec2(12, 8)
    style.ItemInnerSpacing = ImVec2(8, 6)
    style.IndentSpacing = 25.0
    style.ScrollbarSize = 15.0
    style.ScrollbarRounding = 9.0
    style.GrabMinSize = 5.0
    style.GrabRounding = 3.0
    style.WindowTitleAlign = ImVec2(0.5, 0.5)

    colors[clr.Text] = ImVec4(0.71, 0.94, 0.93, 1.00)
    colors[clr.TextDisabled] = ImVec4(0.24, 0.23, 0.29, 1.00)
    colors[clr.WindowBg] = ImVec4(0.00, 0.06, 0.08, 0.91)
    colors[clr.ChildWindowBg] = ImVec4(0.00, 0.07, 0.07, 0.91)
    colors[clr.PopupBg] = ImVec4(0.02, 0.08, 0.09, 0.94)
    colors[clr.Border] = ImVec4(0.04, 0.60, 0.55, 0.88)
    colors[clr.BorderShadow] = ImVec4(0.92, 0.91, 0.88, 0.00)
    colors[clr.FrameBg] = ImVec4(0.02, 0.60, 0.56, 0.49)
    colors[clr.FrameBgHovered] = ImVec4(0.10, 0.63, 0.69, 0.72)
    colors[clr.FrameBgActive] = ImVec4(0.04, 0.54, 0.60, 1.00)
    colors[clr.TitleBg] = ImVec4(0.00, 0.26, 0.30, 0.94)
    colors[clr.TitleBgActive] = ImVec4(0.00, 0.26, 0.29, 0.94)
    colors[clr.TitleBgCollapsed] = ImVec4(0.01, 0.28, 0.40, 0.66)
    colors[clr.MenuBarBg] = ImVec4(0.00, 0.22, 0.22, 0.73)
    colors[clr.ScrollbarBg] = ImVec4(0.01, 0.44, 0.43, 0.60)
    colors[clr.ScrollbarGrab] = ImVec4(0.00, 0.93, 1.00, 0.31)
    colors[clr.ScrollbarGrabHovered] = ImVec4(0.17, 0.64, 0.79, 1.00)
    colors[clr.ScrollbarGrabActive] = ImVec4(0.01, 0.48, 0.57, 1.00)
    colors[clr.ComboBg] = ImVec4(0.01, 0.51, 0.50, 0.74)
    colors[clr.CheckMark] = ImVec4(0.17, 0.87, 0.85, 0.62)
    colors[clr.SliderGrab] = ImVec4(0.10, 0.84, 0.87, 0.31)
    colors[clr.SliderGrabActive] = ImVec4(0.06, 0.05, 0.07, 1.00)
    colors[clr.Button] = ImVec4(0.09, 0.70, 0.75, 0.48)
    colors[clr.ButtonHovered] = ImVec4(0.15, 0.72, 0.75, 0.69)
    colors[clr.ButtonActive] = ImVec4(0.13, 0.92, 0.98, 0.47)
    colors[clr.Header] = ImVec4(0.09, 0.65, 0.69, 0.47)
    colors[clr.HeaderHovered] = ImVec4(0.07, 0.54, 0.58, 0.47)
    colors[clr.HeaderActive] = ImVec4(0.06, 0.50, 0.53, 0.47)
    colors[clr.Separator] = ImVec4(0.00, 0.20, 0.23, 1.00)
    colors[clr.SeparatorHovered] = ImVec4(0.00, 0.20, 0.23, 1.00)
    colors[clr.SeparatorActive] = ImVec4(0.00, 0.20, 0.23, 1.00)
    colors[clr.ResizeGrip] = ImVec4(0.06, 0.90, 0.78, 0.16)
    colors[clr.ResizeGripHovered] = ImVec4(0.04, 0.54, 0.48, 1.00)
    colors[clr.ResizeGripActive] = ImVec4(0.01, 0.28, 0.41, 1.00)
    colors[clr.CloseButton] = ImVec4(0.00, 0.94, 0.96, 0.25)
    colors[clr.CloseButtonHovered] = ImVec4(0.15, 0.63, 0.61, 0.39)
    colors[clr.CloseButtonActive] = ImVec4(0.15, 0.63, 0.61, 0.39)
    colors[clr.PlotLines] = ImVec4(0.40, 0.39, 0.38, 0.63)
    colors[clr.PlotLinesHovered] = ImVec4(0.25, 1.00, 0.00, 1.00)
    colors[clr.PlotHistogram] = ImVec4(0.40, 0.39, 0.38, 0.63)
    colors[clr.PlotHistogramHovered] = ImVec4(0.25, 1.00, 0.00, 1.00)
    colors[clr.TextSelectedBg] = ImVec4(0.25, 1.00, 0.00, 0.43)
    colors[clr.ModalWindowDarkening] = ImVec4(0.00, 0.00, 0.00, 0.80)

end
apply_custom_style()

function mainmenu() -- функция открытия основного меню скрипта
    if not win_state['player'].v and not win_state['update'].v and not win_state['base'].v and not win_state['regst'].v then
        if win_state['settings'].v then
            win_state['settings'].v = not win_state['settings'].v
        elseif win_state['leaders'].v then
            win_state['leaders'].v = not win_state['leaders'].v
        elseif win_state['about'].v then
            win_state['about'].v = not win_state['about'].v
        elseif win_state['help'].v then
            win_state['help'].v = not win_state['help'].v
        elseif win_state['info'].v then
            win_state['info'].v = not win_state['info'].v
        elseif menu_spur.v then
            menu_spur.v = not menu_spur.v
        end
        win_state['main'].v = not win_state['main'].v
    end
end

function imgui.OnDrawFrame()
    local tLastKeys = {} -- это у нас для клавиш
    local sw, sh = getScreenResolution() -- получаем разрешение экрана
    local btn_size = imgui.ImVec2(-0.1, 0) -- а это "шаблоны" размеров кнопок
    local btn_size2 = imgui.ImVec2(160, 0)
    local btn_size3 = imgui.ImVec2(140, 0)

    function imgui.OnDrawFrame()
        local tLastKeys = {} -- это у нас для клавиш
        local sw, sh = getScreenResolution() -- получаем разрешение экрана
        local btn_size = imgui.ImVec2(-0.1, 0) -- а это "шаблоны" размеров кнопок
        local btn_size2 = imgui.ImVec2(160, 0)
        local btn_size3 = imgui.ImVec2(140, 0)

        -- тут мы подстраиваем курсор под адекватность
        imgui.ShowCursor = not win_state['informer'].v and not win_state['ass'].v and not win_state['find'].v or win_state['main'].v or win_state['base'].v or win_state['update'].v or win_state['player'].v or win_state['regst'].v or win_state['renew'].v or win_state['leave'].v

        if win_state['main'].v then -- основное окошко

            imgui.SetNextWindowPos(imgui.ImVec2(sw / 2, sh / 2), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
            imgui.SetNextWindowSize(imgui.ImVec2(280, 250), imgui.Cond.FirstUseEver)
            imgui.Begin(u8' MoD-Helper by Adamson', win_state['main'], imgui.WindowFlags.NoResize)

            -- кнопка информации, визуально реализовано частично
            if isPlayerSoldier then if imgui.Button(fa.ICON_STAR..u8' Информация', btn_size) then print("Переход в раздел информации") win_state['info'].v = not win_state['info'].v end end
            -- кнопка настроек, готово
            if imgui.Button(fa.ICON_COGS..u8' Настройки', btn_size) then print("Переход в раздел настроек") win_state['settings'].v = not win_state['settings'].v end
            -- кнопка шпоры, готово
            if imgui.Button(fa.ICON_YELP..u8' Шпаргалки', btn_size) then print("Переход в раздел шпор") menu_spur.v = not menu_spur.v end
            -- лидерский раздел(госки), готово
            if imgui.Button(fa.ICON_CHILD..u8' Лидерам', btn_size) then print("Переход в раздел лидерам") win_state['leaders'].v = not win_state['leaders'].v end
            -- информация по скрипту, готово
            if imgui.Button(fa.ICON_EYE..u8' Помощь', btn_size) then print("Переход в раздел помощи") win_state['help'].v = not win_state['help'].v end
            -- о скрипте, установка обновлений, готово
            if imgui.Button(fa.ICON_COPYRIGHT..u8' О скрипте', btn_size) then print("Переход в раздел о скрипте") win_state['about'].v = not win_state['about'].v end

            imgui.End()
        end
    end
end


function main()
    sampRegisterChatCommand("otstabhne", mainmenu)
  while true do
    wait(0)
  end
end
В чем косяк?
imgui юзаешь не так, ты даже рендер не включил
таблицы тоже не так юзаются.
косяк в том что ты тупо скопировал код.

Как получить значение в диалоге статистике на адванс рп (/mn)
Требуется получить значение в разные переменные пунктов: Имя, уровень, очки опыта(строкой), должность и ранг и законку.
MBktMiR.jpg

Пример скрина диалога.
Получать текст с помошью хука (sampevents в помошь), и потом с помощью регулярок получать значения.
 

NoMatterCode

Известный
110
49
Как поймать серверное сообщение со словами "..Ставка: %число%", и если это %число% == 500, прописывать соответствующую команду?
Как это работает? :thinking:
 

Akionka

akionka.lua
Проверенный
742
500
Как поймать серверное сообщение со словами "..Ставка: %число%", и если это %число% == 500, прописывать соответствующую команду?
Как это работает? :thinking:
Lua:
local    sampev = require 'lib.samp.events'
function sampev.onServerMessage(color, text)
    if(text:match(".*Ставка: (%d+).*") == "500") then sampSendChat("jojo") end
end
 
Последнее редактирование:
  • Нравится
Реакции: TheGood11 и NoMatterCode

Petr_Sergeevich

Известный
Проверенный
707
296
Как поймать серверное сообщение со словами "..Ставка: %число%", и если это %число% == 500, прописывать соответствующую команду?
Как это работает? :thinking:
Lua:
sampev = require 'lib.samp.events'

function sampev.onServerMessage(color, message)
    if message:find("Ставка%: .+") then
        local num = message:match("Ставка%: (%d+)")
        if tonumber(num) == 500 then
            sampSendChat("/cmd")
        end
    end
end
 

Frapsy

Известный
Проверенный
393
226
404. That’s an error.
The requested URL was not found on this server.
Ну так ты на существующий обработчик делай запросы .
В авторе "xach"

Есть ли тут люди, которые работали с VK APİ для Lua?

Если есть - объясните, как это работает вообще, как использовать и т.п.
Получаешь токен и дальше работаешь с методами, т.е. отсылаешь get/post запрос по методам, используя нужные тебе параметры и дальше уже вертишь с ответом что-хочешь.

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