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

Kotovasya

Участник
85
13
сам с этим не особо, жди знающих, а так еще можешь подгружать файлы
Lua:
DxTexture texture = renderLoadTextureFromFile(zstring file)
только тебе прийдется на каждый ИД гана рисовать текстурку и кидать в папку. И да, с этим методом потом лучше чистить память дабы не засрать ее
Рендер иконок из gtaweapon3

Lua:
local ffi = require 'ffi'
local d3dx9_43 = ffi.load('d3dx9_43.dll')
ffi.cdef[[
struct stKillEntry
{
    char                    szKiller[25];
    char                    szVictim[25];
    uint32_t                clKillerColor; // D3DCOLOR
    uint32_t                clVictimColor; // D3DCOLOR
    uint8_t                    byteType;
} __attribute__ ((packed));

struct stKillInfo
{
    int                        iEnabled;
    struct stKillEntry        killEntry[5];
    int                     iLongestNickLength;
      int                     iOffsetX;
      int                     iOffsetY;
    void                    *pD3DFont; // ID3DXFont
    void                    *pWeaponFont1; // ID3DXFont
    void                       *pWeaponFont2; // ID3DXFont
    void                    *pSprite;
    void                    *pD3DDevice;
    int                     iAuxFontInited;
    void                     *pAuxFont1; // ID3DXFont
    void                     *pAuxFont2; // ID3DXFont
} __attribute__ ((packed));
]]

ffi.cdef [[
typedef struct stRECT
{
    int left, top, right, bottom;
} RECT;

typedef struct stID3DXFont
{
    struct ID3DXFont_vtbl* vtbl;
} ID3DXFont;

struct ID3DXFont_vtbl
{
        void* QueryInterface; // STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE;
    void* AddRef; // STDMETHOD_(ULONG, AddRef)(THIS) PURE;
    uint32_t (__stdcall * Release)(ID3DXFont* font); // STDMETHOD_(ULONG, Release)(THIS) PURE;

    // ID3DXFont
    void* GetDevice; // STDMETHOD(GetDevice)(THIS_ LPDIRECT3DDEVICE9 *ppDevice) PURE;
    void* GetDescA; // STDMETHOD(GetDescA)(THIS_ D3DXFONT_DESCA *pDesc) PURE;
    void* GetDescW; // STDMETHOD(GetDescW)(THIS_ D3DXFONT_DESCW *pDesc) PURE;
    void* GetTextMetricsA; // STDMETHOD_(BOOL, GetTextMetricsA)(THIS_ TEXTMETRICA *pTextMetrics) PURE;
    void* GetTextMetricsW; // STDMETHOD_(BOOL, GetTextMetricsW)(THIS_ TEXTMETRICW *pTextMetrics) PURE;

    void* GetDC; // STDMETHOD_(HDC, GetDC)(THIS) PURE;
    void* GetGlyphData; // STDMETHOD(GetGlyphData)(THIS_ UINT Glyph, LPDIRECT3DTEXTURE9 *ppTexture, RECT *pBlackBox, POINT *pCellInc) PURE;

    void* PreloadCharacters; // STDMETHOD(PreloadCharacters)(THIS_ UINT First, UINT Last) PURE;
    void* PreloadGlyphs; // STDMETHOD(PreloadGlyphs)(THIS_ UINT First, UINT Last) PURE;
    void* PreloadTextA; // STDMETHOD(PreloadTextA)(THIS_ LPCSTR pString, INT Count) PURE;
    void* PreloadTextW; // STDMETHOD(PreloadTextW)(THIS_ LPCWSTR pString, INT Count) PURE;

    int (__stdcall * DrawTextA)(ID3DXFont* font, void* pSprite, const char* pString, int Count, RECT* pRect, uint32_t Format, uint32_t Color); // STDMETHOD_(INT, DrawTextA)(THIS_ LPD3DXSPRITE pSprite, LPCSTR pString, INT Count, LPRECT pRect, DWORD Format, D3DCOLOR Color) PURE;
    void* DrawTextW; // STDMETHOD_(INT, DrawTextW)(THIS_ LPD3DXSPRITE pSprite, LPCWSTR pString, INT Count, LPRECT pRect, DWORD Format, D3DCOLOR Color) PURE;

    void (__stdcall * OnLostDevice)(ID3DXFont* font); // STDMETHOD(OnLostDevice)(THIS) PURE;
    void (__stdcall * OnResetDevice)(ID3DXFont* font); // STDMETHOD(OnResetDevice)(THIS) PURE;
};

uint32_t D3DXCreateFontA(void* pDevice, int Height, uint32_t Width, uint32_t Weight, uint32_t MipLevels, bool Italic, uint32_t CharSet, uint32_t OutputPrecision, uint32_t Quality, uint32_t PitchAndFamily, const char* pFaceName, ID3DXFont** ppFont);
]]

ID = {
    Unarmed = 0,
    Knuckles = 1,
    Golf = 2,
    Stick = 3,
    Knife = 4,
    Bat = 5,
    Shovel = 6,
    Cue = 7,
    Katana = 8,
    Chainsaw = 9,
    Dildo1 = 10,
    Dildo2 = 11,
    Dildo3 = 12,
    Dildo4 = 13,
    Flowers = 14,
    Cane = 15,
    Grenade = 16,
    Gas = 17,
    Molotov = 18,
    Pistol = 22,
    Slicend = 23,
    Eagle = 24,
    Shotgun = 25,
    Sawnoff = 26,
    Combat = 27,
    Uzi = 28,
    Mp5 = 29,
    Ak47 = 30,
    M4 = 31,
    Tec9 = 32,
    Rifle = 33,
    Sniper = 34,
    RPG = 35,
    Launcher = 36,
    Flame = 37,
    Minigun = 38,
    Sachet = 39,
    Detonator = 40,
    Spray = 41,
    Extinguisher = 42,
    Goggles1 = 44,
    Goggles2 = 45,
    Parachute = 46,
}

--таблица кодов иконок
RenderGun = {
    [ID.Unarmed] = 37,
    [ID.Knuckles] = 66,
    [ID.Golf] = 62,
    [ID.Stick] = 40,
    [ID.Knife] = 67,
    [ID.Bat] = 63,
    [ID.Shovel] = 38,
    [ID.Cue] = 34,
    [ID.Katana] = 33,
    [ID.Chainsaw] = 49,
    [ID.Dildo1] = 69,
    [ID.Dildo2] = 69,
    [ID.Dildo3] = 69,
    [ID.Dildo4] = 69,
    [ID.Flowers] = 36,
    [ID.Cane] = 35,
    [ID.Grenade] = 64,
    [ID.Gas] = 68,
    [ID.Molotov] = 39,
    [ID.Pistol] = 54,
    [ID.Slicend] = 50,
    [ID.Eagle] = 51,
    [ID.Shotgun] = 61,
    [ID.Sawnoff] = 48,
    [ID.Combat] = 43,
    [ID.Uzi] = 73,
    [ID.Mp5] = 56,
    [ID.Ak47] = 72,
    [ID.M4] = 53,
    [ID.Tec9] = 55,
    [ID.Rifle] = 46,
    [ID.Sniper] = 65,
    [ID.RPG] = 52,
    [ID.Launcher] = 41,
    [ID.Flame] = 42,
    [ID.Minigun] = 70,
    [ID.Sachet] = 60,
    [ID.Detonator] = 59,
    [ID.Spray] = 47,
    [ID.Extinguisher] = 44,
    [ID.Goggles1] = 45,
    [ID.Goggles2] = 45,
    [ID.Parachute] = 58
}

function main()
    while not isSampAvailable() do wait(0) end
    -- загружаем шрифт, размер 12, флаг 2
    font_gtaweapon3 = d3dxfont_create('gtaweapon3', 12, 2)
    fonts_loaded = true
    wait(-1)
end

--функция постоянного рендера
function onD3DPresent()
    if fonts_loaded then
    local sw, sh = getScreenResolution()
        d3dxfont_draw(font_gtaweapon3, string.char(RenderGun[24]), {X, Y, sw, sh}, 0xFFFFFFFF, 0x10)
        -- рисуем дигл, цвет иконки белый
    end
end

function onExitScript()
    if fonts_loaded then
        font_gtaweapon3.vtbl.Release(font_gtaweapon3)
    end
end

function d3dxfont_create(name, height, charset)
    charset = charset or 1
    local d3ddev = ffi.cast('void*', getD3DDevicePtr())
    local pfont = ffi.new('ID3DXFont*[1]', {nil})
    if tonumber(d3dx9_43.D3DXCreateFontA(d3ddev, height, 0, 600, 1, false, charset, 0, 4, 0, name, pfont)) < 0 then
        return nil
    end
    return pfont[0]
end

function d3dxfont_draw(font, text, rect, color, format)
    local prect = ffi.new('RECT[1]', {{rect[1], rect[2], rect[3], rect[4]}})
    return font.vtbl.DrawTextA(font, nil, text, -1, prect, format, color)
end

function onD3DDeviceLost()
    if fonts_loaded then
        font_gtaweapon3.vtbl.OnLostDevice(font_gtaweapon3)
    end
end

function onD3DDeviceReset()
    if fonts_loaded then
        font_gtaweapon3.vtbl.OnResetDevice(font_gtaweapon3)
    end
end
 
  • Нравится
Реакции: Musaigen

S-Sirius

Известный
351
21
Как испоьлзуется string.match? Например в функции sampSendChat("/jail "..var0.." "..var1.."Cheat")
 

dhhh

Известный
51
1
Что не так?
Lua:
if imgui.Button(u8"Добавить") then
            imgui.OpenPopup("Action")
        end
if imgui.BeginPopup("Action") then
        imgui.InputText(u8"Текст", nik[1])
        imgui.EndPopup()
        end
 

SaMartinell

Новичок
10
0
Lua:
if imgui.Button(u8"Попросить документы") then
  lua_thread.create(function ()
  sampSendChat("text")
  wait(задержка в мс)
  sampSendChat("text")
  end)
end
Спасибо большое. У меня появился ещё один вопрос: как сделать рандомные сообщения? Например у меня есть код
Lua:
if imgui.Button(u8'text') then
            sampSendChat('text 1')
        end
но я хочу добавить туда ещё рандомное сообщение(предварительно заданное), например чтобы у меня случайно писалось text1, text2 или text3
 

sdfaw

Активный
717
150
Что не так?
Lua:
if imgui.Button(u8"Добавить") then
            imgui.OpenPopup("Action")
        end
if imgui.BeginPopup("Action") then
        imgui.InputText(u8"Текст", nik[1])
        imgui.EndPopup()
        end
Код:
if imgui.Button(u8"Добавить") then
  imgui.OpenPopup("Action")
end
if imgui.BeginPopup("Action") then
imgui.InputText(u8"Текст", nik[1])
end
imgui.EndPopup()
 

Kotovasya

Участник
85
13
Почему мне тогда возвращает число десятичной системы счисления а не шеснадцатиричной? Или я че то не понимаю
Если тебе в HEX нужно перевести

Lua:
rgb = {255, 255, 255}
Color = rgbToHex(rgb)

function rgbToHex(rgb)
    local hexadecimal = '0X'
    for key, value in pairs(rgb) do
        local hex = ''
        while(value > 0)do
            local index = math.fmod(value, 16) + 1
            value = math.floor(value / 16)
            hex = string.sub('0123456789ABCDEF', index, index) .. hex          
        end
        if(string.len(hex) == 0)then
            hex = '00'
        elseif(string.len(hex) == 1)then
            hex = '0' .. hex
        end
        hexadecimal = hexadecimal .. hex
    end
    return hexadecimal
end
 

Quasper

Известный
835
354
Спасибо большое. У меня появился ещё один вопрос: как сделать рандомные сообщения? Например у меня есть код
Lua:
if imgui.Button(u8'text') then
            sampSendChat('text 1')
        end
но я хочу добавить туда ещё рандомное сообщение(предварительно заданное), например чтобы у меня случайно писалось text1, text2 или text3
Lua:
randomText = {
[1] = "text1",
[2] = "text2",
[3] = "text3"
}
if imgui.Button(u8'text') then 
sampSendChat('text 1')
rText = math.random(1, #randomText)
sampSendChat(randomText[rText])
end
как то так
 
  • Нравится
Реакции: SaMartinell

r11x

Новичок
33
2
Почему ломается и как починить?
сф:
Код:
[ML] (error) mark.lua: opcode '00AB' call caused an unhandled exception
stack traceback:
    [C]: in function 'setCarCoordinates'
    F:\games\GTASA\GTA San Andreas\moonloader\mark.lua:17: in function <F:\games\GTASA\GTA San Andreas\moonloader\mark.lua:11>
[ML] (error) mark.lua: Script died due to an error. (0BD74D9C)
код:
Lua:
require "lib.moonloader"
sampev = require 'lib.samp.events'

function main()
    if not isSampLoaded() or not isSampfuncsLoaded() then return end
    while not isSampAvailable() do wait(100) end
    sampRegisterChatCommand('aptp', cmd_aptp)
        wait(0)
end

function cmd_aptp()
        local x=-2713.14
        local y=-158.20
        local z=4.04
    if isCharInAnyCar(PLAYER_PED) then
      local _, carId = sampGetVehicleIdByCarHandle(storeCarCharIsInNoSave(PLAYER_PED))
    setCarCoordinates(carId,x,y,z)
  end
end
 

dhhh

Известный
51
1
Почему ошибка появляется и крашится гта?
Lua:
Gar = imgui.ImBuffer(256)
if imgui.Button(u8"Добавить") then
            imgui.OpenPopup("Action")
        end
if imgui.BeginPopup("Action") then
        imgui.InputText(u8"Текст", Gar)

        end
        imgui.EndPopup()
 

ImPasha

Software Developer & System Administrator
Друг
1,789
2,141
Почему ломается и как починить?
сф:
Код:
[ML] (error) mark.lua: opcode '00AB' call caused an unhandled exception
stack traceback:
    [C]: in function 'setCarCoordinates'
    F:\games\GTASA\GTA San Andreas\moonloader\mark.lua:17: in function <F:\games\GTASA\GTA San Andreas\moonloader\mark.lua:11>
[ML] (error) mark.lua: Script died due to an error. (0BD74D9C)
код:
Lua:
require "lib.moonloader"
sampev = require 'lib.samp.events'

function main()
    if not isSampLoaded() or not isSampfuncsLoaded() then return end
    while not isSampAvailable() do wait(100) end
    sampRegisterChatCommand('aptp', cmd_aptp)
        wait(0)
end

function cmd_aptp()
        local x=-2713.14
        local y=-158.20
        local z=4.04
    if isCharInAnyCar(PLAYER_PED) then
      local _, carId = sampGetVehicleIdByCarHandle(storeCarCharIsInNoSave(PLAYER_PED))
    setCarCoordinates(carId,x,y,z)
  end
end
Нужен Handle, а не ID

Почему ошибка появляется и крашится гта?
Lua:
Gar = imgui.ImBuffer(256)
if imgui.Button(u8"Добавить") then
            imgui.OpenPopup("Action")
        end
if imgui.BeginPopup("Action") then
        imgui.InputText(u8"Текст", Gar)

        end
        imgui.EndPopup()
EndPopup в условие, а переменную в начало скрипта вне onDrawFrame.
 

lorgon

Известный
656
271
Как это сделать? upload_2019-3-28_22-53-37.png
 

Di3

Участник
432
20
Lua:
for i,k in pairs(listen) do
    if imgui.Button(u8(k),imgui.ImVec2(350,20)) then
  -- code 
    end
end
У меня есть большой список кнопок,как можно сделать поиск , чтобы при вводе в InputText начало фразы в окне появлялась только похожая кнопка с текстом