Вопросы по 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
Как сделать что бы линия рендерилась, даже если нету точек их начала/конца (их координаты статичны) на экране? То есть на втором скрине должна быть предо мной та же линия, что и с 1 скрина
Посмотреть вложение 27738 Посмотреть вложение 27739
Актуально
 

Bananious

Известный
238
17
Почему бот не ставится на паузу когда видит строку в чате, и не продолжает когда видит другую строку в чате?
Lua:
require 'lib.moonloader'
require 'lib.vkeys'
local mem = require 'memory'
local sampev = require 'lib.samp.events'


local main_color = "{3C64AF}"
local gray_color = "{949494}"
local active_color = "{109E2B}"
local deactive_color = "{B91C0E}"
local white_color = "{FFFFFF}"
local yellow_color = "{FFC800}"

function main()
        if not isSampLoaded() or not isSampfuncsLoaded() then return end
        while not isSampAvailable() do wait(100) end
        box = 0
        gym = 0
        one = 0
        two = 0

        sampRegisterChatCommand("box", box_cmd)
        sampRegisterChatCommand("gym", gym_cmd)
        sampRegisterChatCommand("1", one_cmd)
        sampRegisterChatCommand("2", two_cmd)
        sampAddChatMessage(main_color .. "[GymBot]: " .. gray_color .. "загружен...", main_color)

        while true do
            wait(0)

            if box == 1 then
                    setGameKeyState(17, 0xFF)
                     wait(20)
                end

            if gym == 1 then
                setGameKeyState(16, 0xFF)
                wait(20)
                end

    end
end

        function box_cmd(args)
            if box == 0 then
                box = 1
                sampAddChatMessage(main_color .. "[BoxBot]: " .. gray_color .. "скрипт " .. active_color .. "активирован", main_color)
            else
                box = 0
                sampAddChatMessage(main_color .. "[BoxBot]: " .. gray_color .. "скрипт " .. deactive_color .. "деактивирован", main_color)
            end
        end

        function gym_cmd(args)
            if gym == 0 then
                gym = 1
                sampAddChatMessage(main_color .. "[GymBot]: " .. gray_color .. "скрипт " .. active_color .. "активирован", main_color)
            else
                gym = 0
                sampAddChatMessage(main_color .. "[GymBot]: " .. gray_color .. "скрипт " .. deactive_color .. "деактивирован", main_color)
            end
        end

        function one_cmd(args)
            if one == 0 then
                one = 1
                sampAddChatMessage(white_color .."• " .. yellow_color .. "[Подсказка] " .. white_color .. "Вы устали, отдохните некоторое время", FFFFFF)
            else
                one = 0
                sampAddChatMessage(white_color .. "• " .. yellow_color .. "[Подсказка] " .. white_color .. "Вы устали, отдохните некоторое время", FFFFFF)
            end
        end

        function two_cmd(args)
            if two == 0 then
            two = 1
            sampAddChatMessage(white_color .. "• " .. yellow_color .. "[Подсказка] " .. white_color .. "Вы полностью отдохнули от тренировок", FFFFFF)
        else
            two = 0
            sampAddChatMessage(white_color .. "• " .. yellow_color .. "[Подсказка] " .. white_color .. "Вы полностью отдохнули от тренировок", FFFFFF)
        end
    end

    function sampev.onServerMessage(color, msg) -- хоть куда
    if msg:find('• {FFC800}[Подсказка] {ffffff}Вы устали, отдохните некоторое время') then
        gym = 0
                sampAddChatMessage(main_color .. "[GymBot]: " .. gray_color .. "остановка...", main_color)
                if msg:find('• {FFC800}[Подсказка] {ffffff}Вы полностью отдохнули от тренировок') then
                    gym = 1
                    sampAddChatMessage(main_color .. "[GymBot]: " .. gray_color .. "продолжение...", main_color)
    end
end
end
 

Di3

Участник
432
20
У кого есть массив с причинами убийств? (killlist)
Типо 0 кулак,24 дигл итд,это понятно,но есть же еще ДБ верталетом,Машиной ,взорвался итд
 

Di3

Участник
432
20
Рендер иконок из 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
Не работает o_O
 

tlwsn

Известный
537
85
Задумал сделать сделать замену киллисту, но столкнулся с проблемой: Вместо иконок оружий показывается его ID,
Пробовал так, но не работает
Lua:
gunfont = renderCreateFont(getGameDirectory()..'\\gtaweap3.ttf', 8, 4)
 

Kotovasya

Участник
85
13
Задумал сделать сделать замену киллисту, но столкнулся с проблемой: Вместо иконок оружий показывается его ID,
Пробовал так, но не работает
Lua:
gunfont = renderCreateFont(getGameDirectory()..'\\gtaweap3.ttf', 8, 4)
Выше пост