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

painw

Известный
116
63
Как нормально проверить соответствует ли текущий гоночный чекпоинт введенным координатам? Есть такой код, но при появлении чекпоинта с которого взяты координаты ничего не происходит:
Lua:
function sampev.onSetRaceCheckpoint(type, position, nextPosition, size)
    local x = position.x
    local y = position.y
    local z = position.z
    sampAddChatMessage('x: '..x..'; y: '..y..'; z: '..z, -1) -- получаю координаты чекпоинта при появлении
    if x == 1196.9349365234 and y == 1196.6458740234 and z == 6.509117603302 then
        sampAddChatMessage('test', -1)
    end
end
 
  • Эм
  • Клоун
Реакции: XRLM и genius.company

0x18d036

Известный
415
113
Как сделать проверку на оружие которое сейчас выбрано? К примеру у меня в руках Desert Eagle, тогда выполнит то что я хочу
 

MLycoris

Режим чтения
Проверенный
1,826
1,867
Не очень понимаю, давно не писал скрипты на LUA.
Lua:
sampRegisterChatCommand('away',function()
        local px,py,pz = getCharCoordinates(1)
        for k,v in pairs(getAllChars()) do
            local cx, cy, cz = getCharCoordinates(v)
            if getDistanceBetweenCoords3d(px,py,pz,cx, cy, cz) <= 150 and v ~= PLAYER_PED then
                sampAddChatMessage('Найден игрок',-1)
                break
            end
        end
    end)
 
  • Нравится
Реакции: sssilvian

sssilvian

Активный
230
25
Lua:
sampRegisterChatCommand('away',function()
        local px,py,pz = getCharCoordinates(1)
        for k,v in pairs(getAllChars()) do
            local cx, cy, cz = getCharCoordinates(v)
            if getDistanceBetweenCoords3d(px,py,pz,cx, cy, cz) <= 150 and v ~= PLAYER_PED then
                sampAddChatMessage('Найден игрок',-1)
                break
            end
        end
    end)
Об этом, как мне сделать так, чтобы он обнаруживал только игроков с определенным цветом имени?
 

YarikVL

Известный
Проверенный
4,798
1,814
  • Нравится
Реакции: sssilvian и MLycoris

MLycoris

Режим чтения
Проверенный
1,826
1,867
Об этом, как мне сделать так, чтобы он обнаруживал только игроков с определенным цветом имени?
Lua:
sampGetPlayerColor(int id)
или можешь можешь в HEX формате проверять
Lua:
local color = string.gsub(string.format("%X", sampGetPlayerColor(ind id)), "..(......)", "FF%1")
 
  • Нравится
Реакции: sssilvian

sssilvian

Активный
230
25
Lua:
sampRegisterChatCommand('away',function()
        local px,py,pz = getCharCoordinates(1)
        for k,v in pairs(getAllChars()) do
            local cx, cy, cz = getCharCoordinates(v)
            if getDistanceBetweenCoords3d(px,py,pz,cx, cy, cz) <= 150 and v ~= PLAYER_PED then
                sampAddChatMessage('Найден игрок',-1)
                break
            end
        end
    end)
Что делать, если в зоне стрима нет игроков?
 

!Sam#0235

Активный
121
39
Can someone give me an example to render my skin in real time using MIMGUI?
What's wrong? This doesn't work | Что не так? Это не работает

Lua:
local imgui = require 'mimgui'
local ffi = require "ffi"
local encoding = require 'encoding'
encoding.default = 'CP1251'
u8 = encoding.UTF8

local MODEL_INFO_ATOMIC = 1
local MODEL_INFO_TIME = 3
local MODEL_INFO_WEAPON = 4
local MODEL_INFO_CLUMP = 5
local MODEL_INFO_VEHICLE = 6
local MODEL_INFO_PED = 7
local MODEL_INFO_LOD = 8

ffi.cdef [[
    typedef unsigned char RwUInt8;
    typedef int RwInt32;
    typedef short RwInt16;

    struct RwRaster {
        struct RwRaster             *parent;
        RwUInt8                     *cpPixels;
        RwUInt8                     *palette;
        RwInt32                     width, height, depth;
        RwInt32                     stride;
        RwInt16                     nOffsetX, nOffsetY;
        RwUInt8                     cType;
        RwUInt8                     cFlags;
        RwUInt8                     privateFlags;
        RwUInt8                     cFormat;
        RwUInt8                     *originalPixels;
        RwInt32                      originalWidth;
        RwInt32                      originalHeight;
        RwInt32                      originalStride;
        void*                       texture_ptr;
    };

    struct RwTexture {
        struct RwRaster* raster;
    };

    struct CBaseModelInfo_vtbl {
        void* destructor;
        void* AsAtomicModelInfoPtr;
        void* AsDamageAtomicModelInfoPtr;
        void* AsLodAtomicModelInfoPtr;
        char(__thiscall* GetModelType)(struct CBaseModelInfo*);
    };

    struct CBaseModelInfo {
        struct CBaseModelInfo_vtbl* vtbl;
    };

    typedef struct RwTexture*(__thiscall* vehicle_render_t)(unsigned long, int, int, float*, float, int, int);
    typedef struct RwTexture*(__thiscall* ped_render_t)(unsigned long, int, int, float*, float);
    typedef struct RwTexture*(__thiscall* others_render_t)(unsigned long, int, int, float*, float);
]]

local RwTextureDestroy = ffi.cast("int(__cdecl*)(struct RwTexture*)", 0x7F3820)
local GetModelInfo = ffi.cast("struct CBaseModelInfo*(__cdecl*)(int)", 0x403DA0)

local textures_from_render = {}

function render_ond3d_lost()
    for i = 1, #textures_from_render do
        RwTextureDestroy(textures_from_render[i])
    end
end

function render_model(model_id, params)
    if 0 > model_id or model_id >= 20000 then return nil end

    local backcolor = params["background_color"]
    local zoom = params["zoom"]
    local rot = params["rotation"]
    local rotation = ffi.new("float [3]")
    rotation[0] = rot.x
    rotation[1] = rot.y
    rotation[2] = rot.z

    local offsets = {
        ["vehicle"]   = { ["R1"] = 0x2EE4E5, ["R3"] = 0x6BC50 },
        ["ped"]       = { ["R1"] = 0x2F522D, ["R3"] = 0x6B9D0 },
        ["others"]    = { ["R1"] = 0x2BE702, ["R3"] = 0x6C240 },
        ["sampst"]    = { ["R1"] = 0x21A108, ["R3"] = 0x26E8F0 }
    }
    local vSAMP = getGameGlobal(707) <= 21 and "R1" or "R3"

    local model_info = GetModelInfo(model_id);
    if model_info ~= ffi.NULL then
        local model_type = model_info.vtbl.GetModelType(model_info);
        local sampst = ffi.cast("unsigned long*", sampGetBase() + offsets["sampst"][vSAMP])[0]

        local result = ffi.NULL
        if model_type == MODEL_INFO_VEHICLE then
            local func_addr = sampGetBase() + offsets["vehicle"][vSAMP]
            result = ffi.cast("vehicle_render_t", func_addr)(sampst, model_id, backcolor,  rotation, zoom, params["carc_1"], params["carc_2"])
        elseif model_type == MODEL_INFO_PED then
            local func_addr = sampGetBase() + offsets["ped"][vSAMP]
            result = ffi.cast("ped_render_t", func_addr)(sampst, model_id, backcolor,  rotation, zoom)
        elseif model_type == MODEL_INFO_WEAPON or model_type == MODEL_INFO_ATOMIC or model_type == MODEL_INFO_CLUMP then
            local func_addr = sampGetBase() + offsets["others"][vSAMP]
            result = ffi.cast("others_render_t", func_addr)(sampst, model_id, backcolor,  rotation, zoom)
        else
            return nil
        end
        if result ~= ffi.NULL and result.raster ~= ffi.NULL and result.raster.texture_ptr ~= ffi.NULL then
            textures_from_render[#textures_from_render + 1] = result
            return result.raster.texture_ptr
        end
        return nil
    end
end

local renderWindow = imgui.new.bool(true)

imgui.OnInitialize(function()
    imgui.GetIO().IniFilename = nil
end)

local texture = nil

local newFrame = imgui.OnFrame(
    function() return renderWindow[0] end,
    function(player)
        local resX, resY = getScreenResolution()
        local sizeX, sizeY = 300, 300
        imgui.SetNextWindowPos(imgui.ImVec2(resX / 2, resY / 2), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
        imgui.SetNextWindowSize(imgui.ImVec2(sizeX, sizeY), imgui.Cond.FirstUseEver)
        imgui.Begin('Main Window', renderWindow)
            local playerSkin = getCharModel(PLAYER_PED)
            if playerSkin >= 0 then
                texture = render_model(playerSkin, {
                    ["background_color"] = 0x00000000,
                    ["zoom"] = 1,
                    ["rotation"] = { ["x"] = 0, ["y"] = 0, ["z"] = 320 },
                    ["carc_1"] = 0,
                    ["carc_2"] = 1
                })
            end

        if texture then
            imgui.Image(texture, imgui.ImVec2(256, 256))
        end
    imgui.End()
end)

function onD3DDeviceLost()
    render_ond3d_lost()
    texture = nil
end

function main()
    while not isSampAvailable() do wait(0) end
    sampRegisterChatCommand('test', function()
        renderWindow[0] = not renderWindow[0]
    end)
    while true do
        wait(0)

    end
end
 

sssilvian

Активный
230
25
Как заставить команду /pp выполнять "/pickpocked ID" на игроках, которые находятся в 2 метрах от меня?
 

#Northn

Police Helper «Reborn» — уже ШЕСТЬ лет!
Всефорумный модератор
2,635
2,485
Как нормально проверить соответствует ли текущий гоночный чекпоинт введенным координатам? Есть такой код, но при появлении чекпоинта с которого взяты координаты ничего не происходит:
Lua:
function sampev.onSetRaceCheckpoint(type, position, nextPosition, size)
    local x = position.x
    local y = position.y
    local z = position.z
    sampAddChatMessage('x: '..x..'; y: '..y..'; z: '..z, -1) -- получаю координаты чекпоинта при появлении
    if x == 1196.9349365234 and y == 1196.6458740234 and z == 6.509117603302 then
        sampAddChatMessage('test', -1)
    end
end
Lua:
function sampev.onSetRaceCheckpoint(type, position, nextPosition, size)
    local x = position.x
    local y = position.y
    local z = position.z
    sampAddChatMessage('x: '..x..'; y: '..y..'; z: '..z, -1) -- получаю координаты чекпоинта при появлении
    if getDistanceBetweenCoords3d(x, y, z, 1196.9349365234, 1196.6458740234, 6.509117603302) <= 1 then
        sampAddChatMessage('test', -1)
    end
end
 
  • Нравится
  • Клоун
Реакции: Fott и painw

MLycoris

Режим чтения
Проверенный
1,826
1,867
Как заставить команду /pp выполнять "/pickpocked ID" на игроках, которые находятся в 2 метрах от меня?
Lua:
sampRegisterChatCommand('pp',function()
    local px,py,pz = getCharCoordinates(1)
    lua_thread.create(function()
        for k,v in pairs(getAllChars()) do
            local cx, cy, cz = getCharCoordinates(v)
            if getDistanceBetweenCoords3d(px,py,pz,cx, cy, cz) <= 2 and v ~= PLAYER_PED then
                sampAddChatMessage('/pickpocked '..select(2, sampGetPlayerIdByCharHandle(v)),-1)
                wait(500)
            end
        end
    end)
end)
 
Последнее редактирование:

Julimba

Участник
108
10
Lua:
require 'lib.moonloader'
local keys = require 'vkeys'
local ip, port = sampGetCurrentServerAddress()
local ips = '185.169.134.67'

function main()
    if ip == ips then
        sampAddChatMessage('Sobaka', -1)
    end
end
qq, скрипт рабочий, только вот при первом запуске игры выдает ошибку, если дальше перезагрузить, то без вопросов работает, в чем беда?
Ошибка ниже:

[ML] (error) huina.lua: opcode '0B39' call caused an unhandled exception
stack traceback:
[C]: in function 'sampGetCurrentServerAddress'
C:\Users\User\Desktop\kichiro\moonloader\huina.lua:3: in main chunk
 

Sam_Monroe

Известный
58
2
Может у кого-то есть простой скрипт с диалоговым окном, где при нажатии на пункт, будет прописываться команда? Мне просто легче разбирать готовые макеты, чем с нуля пытаться написать