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

jetrorq

Участник
39
4
И так, я хочу сделать mImguiPie, однако столкнулся с проблемой, что код работает, а само круговое меню не показывается. Я пока что не до конца понял проблему и как ее решить, поэтому обращаюсь сюда. (не обращайте внимания на вызываемые функции в круговом меню. я их потом изменю)

Lua:
imgui.OnFrame(function() end, function()
    if pie_mode[0] then
        imgui.OpenPopup('PieMenu')
    end
    if pie.BeginPiePopup('PieMenu') then
        if pie.PieMenuItem(u8'Открыть/Закрыть') then sampAddChatMessage("/lock",-1) end
        if pie.PieMenuItem(u8'Завести/Заглушить') then sampAddChatMessage("/engine",-1) end
        if pie.PieMenuItem(u8'Вкл/Выкл ТТ') then sampAddChatMessage("/style",-1) end
        if pie.PieMenuItem(u8'Ключи') then sampAddChatMessage("/key",-1) end
    pie.EndPiePopup()
    end
end)
local targetIdPlayer = nil
function main()
    sampRegisterChatCommand('openmenu', function()
        WinState[0] = not WinState[0]
    end)
    while true do
        wait(0)
        if (isKeyDown(18) and isKeyJustPressed(2)) or (isKeyDown(2) and isKeyJustPressed(18)) and not sampIsChatInputActive() and not sampIsDialogActive() then
            local result, i = getCharPlayerIsTargeting()
            if result then
                targetIdPlayer = i
                pie_mode[0] = true
                act = true
                imgui.Process = pie_mode[0]
            end
        end
    end
end
 

ArtyDomino

Новичок
4
9
Делал скриптик по гайдовому шаблону, и хотел сделать так, чтобы когда я нажимаю на кнопку (строка 15), выводился самый обыкновенный текст (строка 16). Все методы, что мне известны на данный момент, перепробовал - ничего не помогает. Подскажите, плиз :(



Lua-скрипт с владками, кнопками и прочей залупой:
local imgui = require 'mimgui' -- помогает с созданием "оконных" скриптов
local encoding = require 'encoding'
encoding.default = 'CP1251'
local u8 = encoding.UTF8 -- помогает с расшифровкой текста на русском

local WinState = imgui.new.bool()

imgui.OnFrame(function() return WinState[0] end, function(player)
    imgui.SetNextWindowPos(imgui.ImVec2(500, 500), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
    imgui.SetNextWindowSize(imgui.ImVec2(360, 300), imgui.Cond.Always)
    imgui.Begin(u8'Дневник Эймуса Зенна v0.1 by Saturn Comics', WinState, imgui.WindowFlags.NoResize)
    if imgui.BeginTabBar('Tabs') then
        if imgui.BeginTabItem(u8'Персонажи') then -- задаём название первой вкладки
            -- далее идёт содержимое вкладки
            if imgui.Button(u8'Эймус Зенн [#000]') then
                imgui.Text(u8'я насрааал');
            end
            -- конец содержимого вкладки
            imgui.EndTabItem()
        end
        if imgui.BeginTabItem(u8'Вселенные') then -- задаём название второй вкладки
            -- далее идёт содержимое вкладки
            if imgui.Button('Test') then
                sampAddChatMessage('Вы нажали кнопку во второй вкладке',-1)
            end
            -- конец содержимого вкладки
            imgui.EndTabItem()
        end
        if imgui.BeginTabItem(u8'Локации') then -- задаём название первой вкладки
            -- далее идёт содержимое вкладки
            imgui.Text(u8'Сейчас открыта первая вкладка')
            -- конец содержимого вкладки
            imgui.EndTabItem()
        end
        imgui.EndTabBar()
    end
    imgui.End()
end)

function main()
    sampRegisterChatCommand('diary', function() WinState[0] = not WinState[0] end)
    wait(-1)
end
 

Неадекватная сова

Известный
Проверенный
290
234
Делал скриптик по гайдовому шаблону, и хотел сделать так, чтобы когда я нажимаю на кнопку (строка 15), выводился самый обыкновенный текст (строка 16). Все методы, что мне известны на данный момент, перепробовал - ничего не помогает. Подскажите, плиз :(



Lua-скрипт с владками, кнопками и прочей залупой:
local imgui = require 'mimgui' -- помогает с созданием "оконных" скриптов
local encoding = require 'encoding'
encoding.default = 'CP1251'
local u8 = encoding.UTF8 -- помогает с расшифровкой текста на русском

local WinState = imgui.new.bool()

imgui.OnFrame(function() return WinState[0] end, function(player)
    imgui.SetNextWindowPos(imgui.ImVec2(500, 500), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
    imgui.SetNextWindowSize(imgui.ImVec2(360, 300), imgui.Cond.Always)
    imgui.Begin(u8'Дневник Эймуса Зенна v0.1 by Saturn Comics', WinState, imgui.WindowFlags.NoResize)
    if imgui.BeginTabBar('Tabs') then
        if imgui.BeginTabItem(u8'Персонажи') then -- задаём название первой вкладки
            -- далее идёт содержимое вкладки
            if imgui.Button(u8'Эймус Зенн [#000]') then
                imgui.Text(u8'я насрааал');
            end
            -- конец содержимого вкладки
            imgui.EndTabItem()
        end
        if imgui.BeginTabItem(u8'Вселенные') then -- задаём название второй вкладки
            -- далее идёт содержимое вкладки
            if imgui.Button('Test') then
                sampAddChatMessage('Вы нажали кнопку во второй вкладке',-1)
            end
            -- конец содержимого вкладки
            imgui.EndTabItem()
        end
        if imgui.BeginTabItem(u8'Локации') then -- задаём название первой вкладки
            -- далее идёт содержимое вкладки
            imgui.Text(u8'Сейчас открыта первая вкладка')
            -- конец содержимого вкладки
            imgui.EndTabItem()
        end
        imgui.EndTabBar()
    end
    imgui.End()
end)

function main()
    sampRegisterChatCommand('diary', function() WinState[0] = not WinState[0] end)
    wait(-1)
end
У тебя imgui.Text отображается буквально на 1 кадр потому что ивент срабатывает 1 раз при нажатии
Lua:
local isTextVisible = false -- Где то вне OnFrame

if imgui.BeginTabItem(u8'Персонажи') then
    if imgui.Button(u8'Эймус Зенн [#000]') then
        isTextVisible = not isTextVisible
    end
    if isTextVisible then
        imgui.Text(u8'я насрааал')
    end
    imgui.EndTabItem()
end
 
  • Нравится
Реакции: ArtyDomino

ArtyDomino

Новичок
4
9
У тебя imgui.Text отображается буквально на 1 кадр потому что ивент срабатывает 1 раз при нажатии
Lua:
local isTextVisible = false -- Где то вне OnFrame

if imgui.BeginTabItem(u8'Персонажи') then
    if imgui.Button(u8'Эймус Зенн [#000]') then
        isTextVisible = not isTextVisible
    end
    if isTextVisible then
        imgui.Text(u8'я насрааал')
    end
    imgui.EndTabItem()
end

Спасибо огромное, рил помогло)
Нейронка мне что-то похожее предлагала, но там как обычно всё сикось/накось было
 

ragermann

Новичок
7
1
1745458139900.png
Как мне найти цвет текстдрава и куда можно его вставить чтобы заработало все адекватно.
 

copypaste_scripter

Известный
1,380
276
Посмотреть вложение 268506
как сделать чтобы при нахождении
Lua:
Баннер {73B461}№.+{ffffff}    {cccccc}-    {73B461}-    {cccccc}.+ м
нажимал на него

пробовал вот так через нейринки но нихуя не нажимает
Lua:
    if text:find("Баннер {73B461}№.+{ffffff}%s+{cccccc}-%s+{73B461}-%s+{cccccc}.+ м") then
        local lines = {}
        for line in text:gmatch("[^\r\n]+") do
            table.insert(lines, line)
        end

        local targetText = "Баннер {73B461}№.+{ffffff}    {cccccc}-    {73B461}-    {cccccc}.+ м"
        for i, item in ipairs(lines) do
            if item == targetText then
                sampSendDialogResponse(id, 1, i - 1, 0)
                return false
            end
        end
    end
пж помогите
 

Oki_Bern

Участник
282
6
Как воспроизвести анимацию, чтобы в ней можно было двигаться, не визуально
 
Последнее редактирование:

Нейросеть

Участник
62
38
Посмотреть вложение 268575Как мне найти цвет текстдрава и куда можно его вставить чтобы заработало все адекватно.
Думаю разберешься, делал для покраски текстдрава по его ID, просто под свои потребности перепишешь.
Lua:
script_author("Нейросеть")
require "lib.moonloader"
local sampev = require "lib.samp.events"
local colors = {
    red = 0xFFFF0000,
    green = 0xFF00FF00,
    blue = 0xFF0000FF,
    yellow = 0xFFFFFF00,
    purple = 0xFFFF00FF,
    cyan = 0xFF00FFFF,
    white = 0xFFFFFFFF,
    black = 0xFF000000,
    orange = 0xFFFF8000,
    pink = 0xFFFF80FF
}
function changeTextColor(textdrawId, newColor)
    if not sampTextdrawIsExists(textdrawId) then return false end
    
    local sizeX, sizeY = sampTextdrawGetLetterSizeAndColor(textdrawId)
    sampTextdrawSetLetterSizeAndColor(textdrawId, sizeX, sizeY, newColor)
    return true
end
function changeBoxColor(textdrawId, newColor)
    if not sampTextdrawIsExists(textdrawId) then return false end
    
    local isBoxEnabled, _, boxWidth, boxHeight = sampTextdrawGetBoxEnabledColorAndSize(textdrawId)
    sampTextdrawSetBoxColorAndSize(textdrawId, isBoxEnabled, newColor, boxWidth, boxHeight)
    return true
end
function changeOutlineColor(textdrawId, newColor)
    if not sampTextdrawIsExists(textdrawId) then return false end
    
    local outlineSize = sampTextdrawGetOutlineColor(textdrawId)
    sampTextdrawSetOutlineColor(textdrawId, outlineSize, newColor)
    return true
end
function cmd_cras(params)
    local args = {}
    for word in params:gmatch("%S+") do
        table.insert(args, word)
    end
    
    local textdrawId = tonumber(args[1])
    if not textdrawId then
        sampAddChatMessage("[TextDraw Colorizer] Ошибка: ID должен быть числом!", 0xFF5555)
        return
    end
    
    if not sampTextdrawIsExists(textdrawId) then
        sampAddChatMessage("[TextDraw Colorizer] Ошибка: TextDraw с ID " .. textdrawId .. " не существует!", 0xFF5555)
        return
    end
    
    local colorName = args[2] and string.lower(args[2]) or "red"
    local selectedColor = colors[colorName] or 0xFFFF0000
    
    if not colors[colorName] then
        sampAddChatMessage("[TextDraw Colorizer] Внимание: Цвет '" .. colorName .. "' не найден, используется красный", 0xFFAA00)
    end
    
    local elementType = args[3] and string.lower(args[3]) or "text"
    local success = false
    
    if elementType == "text" then
        success = changeTextColor(textdrawId, selectedColor)
    elseif elementType == "box" then
        success = changeBoxColor(textdrawId, selectedColor)
    elseif elementType == "outline" then
        success = changeOutlineColor(textdrawId, selectedColor)
    else
        sampAddChatMessage("[TextDraw Colorizer] Внимание: Неизвестный тип '" .. elementType .. "', используется 'text'", 0xFFAA00)
        success = changeTextColor(textdrawId, selectedColor)
    end
    
    if success then
        sampAddChatMessage("[TextDraw Colorizer] Успешно: TextDraw " .. textdrawId .. " теперь " .. colorName, 0x55FF55)
    else
        sampAddChatMessage("[TextDraw Colorizer] Ошибка: Не удалось изменить цвет TextDraw " .. textdrawId, 0xFF5555)
    end
end
function main()
    while not isSampAvailable() do wait(100) end
    
    sampRegisterChatCommand("cras", cmd_cras)
    sampAddChatMessage("[TextDraw Colorizer] Загружен! Используйте /cras для изменения цвета TextDraw", 0x6495ED)
    
    while true do
        wait(0)
    end
end
 

chromiusj

fullstack eblan
Модератор
5,749
4,059
как мне отправить пакет "ЬsortingGame.correctMove | 220, 18, 23, 0, 115, 111, 114, 116, 105, 110, 103, 71, 97, 109, 101, 46, 99, 111, 114, 114, 101, 99, 116, 77, 111, 118, 101, 0, 0, 0, 0" я честно пытался разобраться по этой теме, но вообще ничего не понял. чат гпт тоже хуйню пишет
еще в этом скрипте есть кнопка "воспроизвести пакет", но она не работает почему то и ничего не меняется
сама менюшка выглядит так
Посмотреть вложение 268659
ну если после отправки этого пакета ничего не происходит значит нужно отправить дополнительные
 

Joce

Участник
51
17
Подскажите что не так со скриптом, не могу понять

Код:
local ffi = require("ffi")
local hook_t = require("hooks")
local MULTIPLY = 6

local WEAPON_IDS = {
    [26] = true,
    [28] = true,
    [31] = true
}

ffi.cdef[[
    typedef struct CWeapon {
        unsigned int nType;
        unsigned int nState;
        unsigned int nAmmoInClip;
        unsigned int nTotalAmmo;
        unsigned int nTimeForNextShot;
        char field_15;
        char field_16;
        char field_17;
        void *pFxSystem;
    } CWeapon;
]]

local function multi_clip_ammo(p_weapon)
    if WEAPON_IDS[p_weapon.nType] then
        local without_clip_ammo = p_weapon.nTotalAmmo - p_weapon.nAmmoInClip
        local multi_clip_ammo = p_weapon.nAmmoInClip * MULTIPLY
        if p_weapon.nTotalAmmo < multi_clip_ammo then
            p_weapon.nAmmoInClip = p_weapon.nAmmoInClip + without_clip_ammo
        elseif p_weapon.nAmmoInClip < without_clip_ammo then
            p_weapon.nAmmoInClip = multi_clip_ammo
        end
    end
end

local function isValidPointer(ptr)
    return ptr ~= nil and ptr ~= 0
end

local CWeapon_Reload, CWeapon_Reload_Hook
function CWeapon_Reload(this, ped)
    CWeapon_Reload_Hook(this, ped)
    if isValidPointer(ped) and ped == getCharPointer(PLAYER_PED) then
        multi_clip_ammo(this)
    end
end
CWeapon_Reload_Hook = hook_t.jmp.new("void(__thiscall*)(CWeapon* this, uintptr_t owner)")(CWeapon_Reload, 0x73AF80)

local CPed_SetCurrentWeapon, CPed_SetCurrentWeapon_Hook
function CPed_SetCurrentWeapon(this, slot)
    CPed_SetCurrentWeapon_Hook(this, slot)
    if isValidPointer(this) and this == getCharPointer(PLAYER_PED) then
        multi_clip_ammo(ffi.cast("CWeapon*", this + 0x5A0 + slot * 0x1C))
    end
end
CPed_SetCurrentWeapon_Hook = hook_t.jmp.new("void(__thiscall*)(uintptr_t this, int slot)")(CPed_SetCurrentWeapon, 0x5F6150)

local CPlayerPed_MakeChangesForNewWeapon, CPlayerPed_MakeChangesForNewWeapon_Hook
function CPlayerPed_MakeChangesForNewWeapon(this, weapon)
    CPlayerPed_MakeChangesForNewWeapon_Hook(this, weapon)
    if isValidPointer(this) and this == getCharPointer(PLAYER_PED) then
        multi_clip_ammo(ffi.cast("CWeapon*", this + 0x5A0 + getWeaponTypeSlot(weapon) * 0x1C))
    end
end
CPlayerPed_MakeChangesForNewWeapon_Hook = hook_t.jmp.new("void(__thiscall*)(uintptr_t this, int slot)")(CPlayerPed_MakeChangesForNewWeapon, 0x608460)
 

JokerEnergy

Новичок
2
0
Всем привет, можете пожалуйста дать легкий скрипт что бы при появлении определенного текста в чате скрипт нажимал клавишу Z ?
 

Oki_Bern

Участник
282
6
Всем привет, можете пожалуйста дать легкий скрипт что бы при появлении определенного текста в чате скрипт нажимал клавишу Z ?
Lua:
require "lib.moonloader"

local sampev = require('samp.events')

function sampev.onServerMessage(color, message)
    if message:find("Текст") then
        setVirtualKeyDown(VK_Z, true)
        wait(100)
        setVirtualKeyDown(VK_Z, false)
    end
end