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

Swooty

Новичок
3
1
Есть скрипт https://www.blast.hk/threads/55598/ для ловли лавок на аризоне, я оставляю ноут у лавки что б он ее словил, только проблема, что он слишком быстро ловит из-за этого уже начали писать жб, помогите плиз добавить задержку там секунду например, прост очто б меньше палилось, мне не так важна скорость как бесспаливность) Буду благодарен всем кто сможет помочь)))

Lua:
script_name("ARZCatcher")
script_author("ANONIMazer")

events = require "samp.events"
local font = renderCreateFont("Arial", 8, 5)
local status = false
local ffi = require 'ffi'
function main()
    repeat wait(0) until isSampAvailable()
    hwin = ffi.C.GetActiveWindow()
    sampAddChatMessage("{FF0000}[AC]{FFFFFF} Скрипт запущен! {ffb400}Разработчик: {FFFFFF}ANONIMazer. || {ffb400}ВК: {FFFFFF}@pu1seanon", -1)
    sampRegisterChatCommand('ARZCatcher', function()
        status = not status
        if status then
            sampAddChatMessage("{FF0000}[AC]{FFFFFF} Скрипт включен...", -1)
        else
            sampAddChatMessage("{FF0000}[AC]{FFFFFF} Скрипт выключен...", -1)
        end
    end)
    while true do
        wait(0)
    end
end
ffi.cdef [[
    typedef int BOOL;
    typedef unsigned long HANDLE;
    typedef HANDLE HWND;
    HWND GetActiveWindow(void);
    BOOL ShowWindow(HWND hWnd, int  nCmdShow);
]]
function events.onShowDialog(dialogId)
    if dialogId == 3010 and status then
        sampSendDialogResponse(dialogId, 1, 0, 0)
        sampAddChatMessage("{FF0000}[AC]{FFFFFF} Вы поймали {ffb400}лавку!", -1)
        local audio = loadAudioStream('moonloader/proverka.mp3')
        setAudioStreamState(audio, 1)

        ffi.C.ShowWindow(hwin, 1)
    end
end

function events.onSetObjectMaterialText(ev, data)
    local Object = sampGetObjectHandleBySampId(ev)
    if doesObjectExist(Object) and getObjectModel(Object) == 18663 and string.find(data.text, "(.-) {30A332}Свободная!") then
        if get_distance(Object) and status then
            lua_thread.create(press_key)
        end
    end
end

function press_key()
    setGameKeyState(21, 256)
end

function get_distance(Object)
    local result, posX, posY, posZ = getObjectCoordinates(Object)
    if result then
        if doesObjectExist(Object) then
            local pPosX, pPosY, pPosZ = getCharCoordinates(PLAYER_PED)
            local distance = (math.abs(posX - pPosX)^2 + math.abs(posY - pPosY)^2)^0.5
            local posX, posY = convert3DCoordsToScreen(posX, posY, posZ)
            if round(distance, 2) <= 0.9 then
                return true
            end
        end
    end
    return false
end

function round(x, n)
    n = math.pow(10, n or 0)
    x = x * n
    if x >= 0 then x = math.floor(x + 0.5) else x = math.ceil(x - 0.5) end
    return x / n
end
 

YarikVL

Известный
Проверенный
4,783
1,807
Есть скрипт https://www.blast.hk/threads/55598/ для ловли лавок на аризоне, я оставляю ноут у лавки что б он ее словил, только проблема, что он слишком быстро ловит из-за этого уже начали писать жб, помогите плиз добавить задержку там секунду например, прост очто б меньше палилось, мне не так важна скорость как бесспаливность) Буду благодарен всем кто сможет помочь)))

Lua:
script_name("ARZCatcher")
script_author("ANONIMazer")

events = require "samp.events"
local font = renderCreateFont("Arial", 8, 5)
local status = false
local ffi = require 'ffi'
function main()
    repeat wait(0) until isSampAvailable()
    hwin = ffi.C.GetActiveWindow()
    sampAddChatMessage("{FF0000}[AC]{FFFFFF} Скрипт запущен! {ffb400}Разработчик: {FFFFFF}ANONIMazer. || {ffb400}ВК: {FFFFFF}@pu1seanon", -1)
    sampRegisterChatCommand('ARZCatcher', function()
        status = not status
        if status then
            sampAddChatMessage("{FF0000}[AC]{FFFFFF} Скрипт включен...", -1)
        else
            sampAddChatMessage("{FF0000}[AC]{FFFFFF} Скрипт выключен...", -1)
        end
    end)
    while true do
        wait(0)
    end
end
ffi.cdef [[
    typedef int BOOL;
    typedef unsigned long HANDLE;
    typedef HANDLE HWND;
    HWND GetActiveWindow(void);
    BOOL ShowWindow(HWND hWnd, int  nCmdShow);
]]
function events.onShowDialog(dialogId)
    if dialogId == 3010 and status then
        sampSendDialogResponse(dialogId, 1, 0, 0)
        sampAddChatMessage("{FF0000}[AC]{FFFFFF} Вы поймали {ffb400}лавку!", -1)
        local audio = loadAudioStream('moonloader/proverka.mp3')
        setAudioStreamState(audio, 1)

        ffi.C.ShowWindow(hwin, 1)
    end
end

function events.onSetObjectMaterialText(ev, data)
    local Object = sampGetObjectHandleBySampId(ev)
    if doesObjectExist(Object) and getObjectModel(Object) == 18663 and string.find(data.text, "(.-) {30A332}Свободная!") then
        if get_distance(Object) and status then
            lua_thread.create(press_key)
        end
    end
end

function press_key()
    setGameKeyState(21, 256)
end

function get_distance(Object)
    local result, posX, posY, posZ = getObjectCoordinates(Object)
    if result then
        if doesObjectExist(Object) then
            local pPosX, pPosY, pPosZ = getCharCoordinates(PLAYER_PED)
            local distance = (math.abs(posX - pPosX)^2 + math.abs(posY - pPosY)^2)^0.5
            local posX, posY = convert3DCoordsToScreen(posX, posY, posZ)
            if round(distance, 2) <= 0.9 then
                return true
            end
        end
    end
    return false
end

function round(x, n)
    n = math.pow(10, n or 0)
    x = x * n
    if x >= 0 then x = math.floor(x + 0.5) else x = math.ceil(x - 0.5) end
    return x / n
end
После 51 строчки попробуй дописать: wait(твоя задержка в миллисекундах)
 

DedPoet

Участник
98
18
как можно сделать так, чтобы скрипт открывал и закрывал 4 диалога по очереди? Например /admins /helpers /leaders /members

пробовал через lua.thread_create, ставил wait(10000), но все равно мод ругается на флуд.
 

Ya Zaregalsya

Известный
370
127
Есть некоторый двоечник по геометрии, перед ним две точки в трёхмерном пространстве Origin и Target. Двоечнику нужна функция, которая рассчитает шаг на некоторое расстояние Step в направлении от Origin к Target. Наверняка такое уже есть в полезных снипетах и функциях, но там под 400 сообщений, а по поиску он не нашёл.
 

ymoroz

Известный
11
2
Что происходит с дочерними потоками, в которых выполняются бесконечные циклы, при завершении main потока?
 

YarikVL

Известный
Проверенный
4,783
1,807
как можно сделать так, чтобы скрипт открывал и закрывал 4 диалога по очереди? Например /admins /helpers /leaders /members

пробовал через lua.thread_create, ставил wait(10000), но все равно мод ругается на флуд.
Lua:
local sampev = require "lib.samp.events"
function main()
    while not isSampAvailable() do wait(0) end -- сюда добавь проверку по спавну или когда тебе там надо вводить команды
    active = true
    while true do wait(0)
        if active then
            t = {"/members", "/leaders", "/admins", "и твои другие команды"}
            for i = 1, #t
                sampSendChat(t[i])
                wait(1000)
            end
            active = false
        end
    end
end
function sampev.onShowDialog(dialogId, style, title, button1, button2, text)
    if title:find("Админы") or title:find("Хэлперы") or title:find("Лидеры") then -- либо проверяешь по ид диалогу
        sampSendDialogResponse(dialogId, 1, nil, nil)
    end
end
Не проверял, но должно работать

Что происходит с дочерними потоками, в которых выполняются бесконечные циклы, при завершении main потока?
Ну в main обычно ставят:
while true do wait(0) ––бесконечный поток, который будет работать до завершение работы скрипта
Либо:
wait(-1) ––чтобы main не завершался, если не поставить скрипт вроде крашнется
Но это не точно🧐
 
Последнее редактирование:
  • Нравится
Реакции: F0RQU1N and

shawtyglock.

Активный
186
57
Хелп, скрипт не работает, спизженный и то не работает, ошибка в консоли:
ML] (error) Shawty Helper: attempt to call a nil value
stack traceback:
stack traceback:
[C]: in function 'create'
...\EVIL 17K GTA Original\moonloader\Shawty Helper Menu.lua:25: in main chunk
[ML] (error) Shawty Helper: Script died due to an error. (0FDD6594)
Код скрипта:

Lua:
script_name('Shawty Helper')
script_author('shawtyglock')

require "lib.moonloader"
local imgui = require 'imgui'
local sampev = require 'lib.samp.events'
local encoding = require 'encoding'
encoding.default = 'CP1251'
u8 = encoding.UTF8
local main_window_state = imgui.ImBool(false)
local rkeys = require 'rkeys'
imgui.HotKey = require('imgui_addons').HotKey

local fa = require 'faIcons'
local fonts = renderCreateFont("Arial", 9, 5)

local tLastKeys = {}

local themes = import "resource/imgui_themes.lua"

local cheked_radio = imgui.ImInt(1)
thread = lua_thread.create_suspended(func)

bool, myid = sampGetPlayerIdByCharHandle(PLAYER_PED)
lua_thread.create(statsupdate)
lua_thread.create(hphud)

local path = getGameDirectory()..'\\moonloader\\config\\shelper.json'

local config = {
    armour = {v = {VK_C}},
    mask = {v = {VK_V}},
    drugs = {v = {VK_X}},
    FontSize = 9,
    FlagFont = 5,
    Bell = false,
    Kill = false,
    Stats = false,
    HPHud = false,
    CPX = 13,
    CPY = 992
}

local font = renderCreateFont("Arial", config.SizeFont, config.FlagFont)

--ImGui
local checkkill = imgui.ImBool(config.Kill)
local checkstats = imgui.ImBool(config.Stats)
local checkhphud = imgui.ImBool(config.HPHud)
local checkbell = imgui.ImBool(config.Bell)
local sizefont = imgui.ImInt(config.SizeFont)
local flagfont = imgui.ImInt(config.FlagFont)

-- Checkbox
local choose_Kill = imgui.ImBool(false)
local choose_Stats = imgui.ImBool(false)
local choose_HPHud = imgui.ImBool(false)
local choose_Bell = imgui.ImBool(false)

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

    style.WindowPadding = imgui.ImVec2(8, 8)
    style.WindowRounding = 6
    style.ChildWindowRounding = 5
    style.FramePadding = imgui.ImVec2(5, 3)
    style.FrameRounding = 3.0
    style.ItemSpacing = imgui.ImVec2(5, 4)
    style.ItemInnerSpacing = imgui.ImVec2(4, 4)
    style.IndentSpacing = 21
    style.ScrollbarSize = 10.0
    style.ScrollbarRounding = 13
    style.GrabMinSize = 8
    style.GrabRounding = 1
    style.WindowTitleAlign = imgui.ImVec2(0.5, 0.5)
    style.ButtonTextAlign = imgui.ImVec2(0.5, 0.5)

    colors[clr.Text]                   = ImVec4(0.95, 0.96, 0.98, 1.00);
    colors[clr.TextDisabled]           = ImVec4(0.29, 0.29, 0.29, 1.00);
    colors[clr.WindowBg]               = ImVec4(0.14, 0.14, 0.14, 1.00);
    colors[clr.ChildWindowBg]          = ImVec4(0.12, 0.12, 0.12, 1.00);
    colors[clr.PopupBg]                = ImVec4(0.08, 0.08, 0.08, 0.94);
    colors[clr.Border]                 = ImVec4(0.14, 0.14, 0.14, 1.00);
    colors[clr.BorderShadow]           = ImVec4(1.00, 1.00, 1.00, 0.10);
    colors[clr.FrameBg]                = ImVec4(0.22, 0.22, 0.22, 1.00);
    colors[clr.FrameBgHovered]         = ImVec4(0.18, 0.18, 0.18, 1.00);
    colors[clr.FrameBgActive]          = ImVec4(0.09, 0.12, 0.14, 1.00);
    colors[clr.TitleBg]                = ImVec4(0.14, 0.14, 0.14, 0.81);
    colors[clr.TitleBgActive]          = ImVec4(0.14, 0.14, 0.14, 1.00);
    colors[clr.TitleBgCollapsed]       = ImVec4(0.00, 0.00, 0.00, 0.51);
    colors[clr.MenuBarBg]              = ImVec4(0.20, 0.20, 0.20, 1.00);
    colors[clr.ScrollbarBg]            = ImVec4(0.02, 0.02, 0.02, 0.39);
    colors[clr.ScrollbarGrab]          = ImVec4(0.36, 0.36, 0.36, 1.00);
    colors[clr.ScrollbarGrabHovered]   = ImVec4(0.18, 0.22, 0.25, 1.00);
    colors[clr.ScrollbarGrabActive]    = ImVec4(0.24, 0.24, 0.24, 1.00);
    colors[clr.ComboBg]                = ImVec4(0.24, 0.24, 0.24, 1.00);
    colors[clr.CheckMark]              = ImVec4(1.00, 0.28, 0.28, 1.00);
    colors[clr.SliderGrab]             = ImVec4(1.00, 0.28, 0.28, 1.00);
    colors[clr.SliderGrabActive]       = ImVec4(1.00, 0.28, 0.28, 1.00);
    colors[clr.Button]                 = ImVec4(1.00, 0.28, 0.28, 1.00);
    colors[clr.ButtonHovered]          = ImVec4(1.00, 0.39, 0.39, 1.00);
    colors[clr.ButtonActive]           = ImVec4(1.00, 0.21, 0.21, 1.00);
    colors[clr.Header]                 = ImVec4(1.00, 0.28, 0.28, 1.00);
    colors[clr.HeaderHovered]          = ImVec4(1.00, 0.39, 0.39, 1.00);
    colors[clr.HeaderActive]           = ImVec4(1.00, 0.21, 0.21, 1.00);
    colors[clr.ResizeGrip]             = ImVec4(1.00, 0.28, 0.28, 1.00);
    colors[clr.ResizeGripHovered]      = ImVec4(1.00, 0.39, 0.39, 1.00);
    colors[clr.ResizeGripActive]       = ImVec4(1.00, 0.19, 0.19, 1.00);
    colors[clr.CloseButton]            = ImVec4(0.40, 0.39, 0.38, 0.16);
    colors[clr.CloseButtonHovered]     = ImVec4(0.40, 0.39, 0.38, 0.39);
    colors[clr.CloseButtonActive]      = ImVec4(0.40, 0.39, 0.38, 1.00);
    colors[clr.PlotLines]              = ImVec4(0.61, 0.61, 0.61, 1.00);
    colors[clr.PlotLinesHovered]       = ImVec4(1.00, 0.43, 0.35, 1.00);
    colors[clr.PlotHistogram]          = ImVec4(1.00, 0.21, 0.21, 1.00);
    colors[clr.PlotHistogramHovered]   = ImVec4(1.00, 0.18, 0.18, 1.00);
    colors[clr.TextSelectedBg]         = ImVec4(1.00, 0.32, 0.32, 1.00);
    colors[clr.ModalWindowDarkening]   = ImVec4(0.26, 0.26, 0.26, 0.60);
end
theme()

local menu = 1
local fa_font = nil
local fontsize = nil

-- KillState
local kills = 0
local deaths = 0
local ratio = 0
local dead_players = {}
local current = 0
local total = 0

-- Load json
if not doesFileExist(path) then
    local f = io.open(path, 'w+')
    f:write(encodeJson(config)):close()
else
    local f = io.open(path, "r")
    a = f:read("*a")
    config = decodeJson(a)
    f:close()
end

function imgui.TextQuestion(text)
    imgui.SameLine()
    imgui.TextDisabled("(?)")
    if imgui.IsItemHovered() then
        imgui.BeginTooltip()
        imgui.TextUnformatted(u8(text))
        imgui.EndTooltip()
    end
end

function imgui.CenterTextColoredRGB(text)
    local width = imgui.GetWindowWidth()
    local style = imgui.GetStyle()
    local colors = style.Colors
    local ImVec4 = imgui.ImVec4

    local explode_argb = function(argb)
        local a = bit.band(bit.rshift(argb, 24), 0xFF)
        local r = bit.band(bit.rshift(argb, 16), 0xFF)
        local g = bit.band(bit.rshift(argb, 8), 0xFF)
        local b = bit.band(argb, 0xFF)
        return a, r, g, b
    end

    local getcolor = function(color)
        if color:sub(1, 6):upper() == 'SSSSSS' then
            local r, g, b = colors[1].x, colors[1].y, colors[1].z
            local a = tonumber(color:sub(7, 8), 16) or colors[1].w * 255
            return ImVec4(r, g, b, a / 255)
        end
        local color = type(color) == 'string' and tonumber(color, 16) or color
        if type(color) ~= 'number' then return end
        local r, g, b, a = explode_argb(color)
        return imgui.ImColor(r, g, b, a):GetVec4()
    end

    local render_text = function(text_)
        for w in text_:gmatch('[^\r\n]+') do
            local textsize = w:gsub('{.-}', '')
            local text_width = imgui.CalcTextSize(u8(textsize))
            imgui.SetCursorPosX( width / 2 - text_width .x / 2 )
            local text, colors_, m = {}, {}, 1
            w = w:gsub('{(......)}', '{%1FF}')
            while w:find('{........}') do
                local n, k = w:find('{........}')
                local color = getcolor(w:sub(n + 1, k - 1))
                if color then
                    text[#text], text[#text + 1] = w:sub(m, n - 1), w:sub(k + 1, #w)
                    colors_[#colors_ + 1] = color
                    m = n
                end
                w = w:sub(1, n - 1) .. w:sub(k + 1, #w)
            end
            if text[0] then
                for i = 0, #text do
                    imgui.TextColored(colors_[i] or colors[1], u8(text[i]))
                    imgui.SameLine(nil, 0)
                end
                imgui.NewLine()
            else
                imgui.Text(u8(w))
            end
        end
    end
    render_text(text)
end

function main()
    if not isSampLoaded() then return end
    while not isSampAvailable() do wait(100) end
    sampAddChatMessage("{FF0000}[Shawty Helper]{FFFFFF} Скрипт успешно запущен! Активация: {FF0000}/sh.", -1)
    sampRegisterChatCommand("sh", function() main_window_state.v = not main_window_state.v end)

        bind = rkeys.registerHotKey(config.armour.v, true, function()
        sampSendChat("/armour")
    end)

        bind = rkeys.registerHotKey(config.mask.v, true, function()
        sampSendChat("/mask")
    end)

        bind = rkeys.registerHotKey(config.drugs.v, true, function()
            hp = getCharHealth(PLAYER_PED)
            if hp < 120 then
                    sampSendChat('/usedrugs 3')
            elseif hp >= 120 and hp < 140 then
                    sampSendChat('/usedrugs 2')
            elseif hp >= 140 then
                    sampSendChat('/usedrugs 1')
            end
    end)

    while true do
        wait(0)
        imgui.Process = main_window_state.v
    end
end

local fa_glyph_ranges = imgui.ImGlyphRanges({ fa.min_range, fa.max_range })
function imgui.BeforeDrawFrame()
    if fa_font == nil then
        local font_config = imgui.ImFontConfig()
        font_config.MergeMode = true
        fa_font = imgui.GetIO().Fonts:AddFontFromFileTTF('moonloader/resource/fonts/fontawesome-webfont.ttf', 14.0, font_config, fa_glyph_ranges)
    end
end

function sampev.onSendGiveDamage(playerId,damage)
    if config.Stats then
        dmg = tonumber(damage)
        dmg = math.floor(dmg)
        total = total + dmg -- Total Damage
        current = current + dmg -- Current Damage
        local _, id = sampGetPlayerIdByCharHandle(PLAYER_PED)
        result, handle2 = sampGetCharHandleBySampPlayerId(playerId)
        health = sampGetPlayerHealth(playerId)
        if health < damage or health == 0 then
                kills = kills + 1
    end
    if config.Kill then
        health = sampGetPlayerHealth(playerId)
        if health < damage or health == 0 then
            printStyledString('-bezdar', 5000, 7)
        end
    end
    end
end

function sampev.onSendSpawn()
    lua_thread.create(function()
        killss = 0
        if config.Stats then
            if firstspawn == false then wait(30) firstspawn = true end
            if firstspawn == true then
                deaths = deaths + 1
            end
        end
        local TimeLeft = math.floor(Timer.start + TimerTime - os.clock())
    end)
end

math.round = function(num, idp)
    local mult = 10^(idp or 0)
    return math.floor(num * mult + 0.5) / mult
end

function statsupdate()
    while true do wait(0)
        if config.Stats then
            renderFontDrawText(font,"{ffffff}Kills: {ef3226}"..kills.."\n{ffffff}Deaths: {ef3226}"..deaths.."\n{ffffff}Damage: {ef3226}"..total, config.CPX, config.CPY,0xffffffff)
        end
    end
end

function hphud()
    while true do wait(0)
        if config.HPHud then
            if not sampTextdrawIsExists(500) and sampIsLocalPlayerSpawned() then
                sampTextdrawCreate(500, "_", 569, 66.9)
            end
            sampTextdrawSetLetterSizeAndColor(500, 0.29, 0.9, 4294967295.0)
            sampTextdrawSetPos(500, 569.2, 66.9)
            sampTextdrawSetStyle(500, 3)
            sampTextdrawSetAlign(500, 569)
            sampTextdrawSetOutlineColor(500, 1, 4278190080.0)
            sampTextdrawSetString(500, "" .. getCharHealth(PLAYER_PED))
        elseif not config.HPHud then
            sampTextdrawDelete(500)
        end
    end
end

function imgui.OnDrawFrame()
    if main_window_state.v then
        local sw, sh = getScreenResolution()
        imgui.SetNextWindowPos(imgui.ImVec2(sw / 2, sh / 2), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
        imgui.SetNextWindowSize(imgui.ImVec2(750, 400), imgui.Cond.FirstUseEver)
        imgui.Begin(u8"Shawty Helper", main_window_state, imgui.WindowFlags.NoCollapse + imgui.WindowFlags.NoResize)
                imgui.BeginChild('##left', imgui.ImVec2(250, 400), true, imgui.WindowFlags.NoScrollbar + imgui.WindowFlags.NoScrollWithMouse)
             if imgui.Button(u8('Информация'), imgui.ImVec2(-1, 50)) then
                     menu = 1
             end
             if imgui.Button(u8('Функции'), imgui.ImVec2(-1, 50)) then
                     menu = 2
             end
             if imgui.Button(u8('Бинды'), imgui.ImVec2(-1, 50)) then
                     menu = 3
             end
             if imgui.Button(u8('Настройки'), imgui.ImVec2(-1, 50)) then
                     menu = 4
             end
             imgui.EndChild()
             imgui.SameLine()
             imgui.BeginChild('##right', imgui.ImVec2(500, 400), true, imgui.WindowFlags.NoScrollbar + imgui.WindowFlags.NoScrollWithMouse)
             if menu == 1 then
                 imgui.CenterTextColoredRGB('{FFFFFF}Спасибо за пользование Shawty Helper\n{FFFFFF}Автор данного скрипта - shawtyglock\n{FFFFFF}Скрипт находится в процессе разработки\n{FFFFFF}Если желаете добавить что-нибудь в скрипт по тематике\n{FFFFFF}или нашли ошибки в скрипте - пишите мне в Discord: FluffyBeast#8186')
             end
             if menu == 2 then
               imgui.Checkbox("KillState", choose_Kill)
                 if choose_Kill.v then
                     config.Kill = checkkill.v
                     JSONSave()
                 end

                 imgui.Checkbox("CaptStats", choose_Stats)
                 if choose_Stats.v then
                     config.Stats = checkstats.v
                     JSONSave()
                 end

                 imgui.Checkbox("HPHud", choose_HPHud)
                 if choose_HPHud.v then
                     config.HPHud = checkhphud.v
                     JSONSave()
                 end

                 imgui.Checkbox("Kolokol", choose_Bell)
                 if choose_Bell.v then
                     config.Bell = checkbell.v
                     JSONSave()
                 end
             end

             if menu == 3 then
                 if imgui.HotKey("##1", config.armour, tLastKeys, 50) then
                            rkeys.changeHotKey(bind, config.armour.v)
                            JSONSave()
                 end

                 imgui.SameLine()
                 imgui.Text(u8"Использование армора")
                 imgui.TextQuestion("Использует армор на указанную вами клавишу/комбинацию клавиш")

                 if imgui.HotKey("##2", config.mask, tLastKeys, 50) then
                            rkeys.changeHotKey(bind, config.mask.v)
                            JSONSave()
                 end

                 imgui.SameLine()
                 imgui.Text(u8"Использование маски")
                 imgui.TextQuestion("Использует маску на указанную вами клавишу/комбинацию клавиш.")

                 if imgui.HotKey("##3", config.drugs, tLastKeys, 50) then
                         rkeys.changeHotKey(bind, config.drugs.v)
                         JSONSave()
                 end

                 imgui.SameLine()
                 imgui.Text(u8"Использование наркотиков")
                    imgui.TextQuestion("Использует наркотики в зависимости от количества вашего хп на указанную вами клавишу/комбинацию клавиш.")
             end
             if menu == 4 then
                 imgui.CenterTextColoredRGB('{FFFFFF} Находится в процессе разработки')
             end
             imgui.EndChild()
             imgui.End()
    end
end

function JSONSave()
    if doesFileExist(path) then
        local f = io.open(path, 'w+')
        if f then
            f:write(encodeJson(config)):close()
        end
    end
end
up
 

Anti...

Участник
243
18
Всем приверт, очень долго искал и не нашёл ответ на свой вопрос. Как можно добавить на карту маркеры по координатам? Например маркеры как на РП серверах, маркер на мерии, маркер банка, что бы отображался на карте и на радаре. Я понял как добавлять маркер по координатам, НО, когда добавляю маркер, он как-бы зацепляется на конце радара. Например когда садишься в самолёт, на радаре показывает аэропорт, где можно приземлится, вот у меня также, соответственно, как можно сделать так, когда подходишь например к мэрии, маркер появлялся, в зоне стрима крч, но что бы был виден на карте вдали
Это возможно?
 

qwеty

Известный
484
156
Как отправить дамаг игроку через булет синхру?
UPD: что не так?
:70: cannot convert 'string' to 'unsigned short'
qweqwe:
function main()
    while not isSampAvailable() do wait(100) end
    sampRegisterChatCommand('bullet', bullet)
    while true do
        wait(0)
    end
end
function bullet(playerid)
    local result, HandlePlayer = sampGetCharHandleBySampPlayerId(playerid)
    local data = samp_create_sync_data('bullet', false)
    data.targetType = 1
    data.targetId = playerid
    data.origin.x, data.origin.y, data.origin.z = getActiveCameraCoordinates()
    data.target.x, data.target.y, data.target.z = getCharCoordinates(HandlePlayer)
    data.weaponId = getCurrentCharWeapon(PLAYER_PED)
    data.send()
    sampAddChatMessage('отправлена: ' ..playerid, -1)
end

function samp_create_sync_data(sync_type, copy_from_player)
    local ffi = require 'ffi'
    local sampfuncs = require 'sampfuncs'
    -- from SAMP.Lua
    local raknet = require 'samp.raknet'
    require 'samp.synchronization'

    copy_from_player = copy_from_player or true
    local sync_traits = {
        player = {'PlayerSyncData', raknet.PACKET.PLAYER_SYNC, sampStorePlayerOnfootData},
        vehicle = {'VehicleSyncData', raknet.PACKET.VEHICLE_SYNC, sampStorePlayerIncarData},
        passenger = {'PassengerSyncData', raknet.PACKET.PASSENGER_SYNC, sampStorePlayerPassengerData},
        aim = {'AimSyncData', raknet.PACKET.AIM_SYNC, sampStorePlayerAimData},
        trailer = {'TrailerSyncData', raknet.PACKET.TRAILER_SYNC, sampStorePlayerTrailerData},
        unoccupied = {'UnoccupiedSyncData', raknet.PACKET.UNOCCUPIED_SYNC, nil},
        bullet = {'BulletSyncData', raknet.PACKET.BULLET_SYNC, nil},
        spectator = {'SpectatorSyncData', raknet.PACKET.SPECTATOR_SYNC, nil}
    }
    local sync_info = sync_traits[sync_type]
    local data_type = 'struct ' .. sync_info[1]
    local data = ffi.new(data_type, {})
    local raw_data_ptr = tonumber(ffi.cast('uintptr_t', ffi.new(data_type .. '*', data)))
    -- copy player's sync data to the allocated memory
    if copy_from_player then
        local copy_func = sync_info[3]
        if copy_func then
            local _, player_id
            if copy_from_player == true then
                _, player_id = sampGetPlayerIdByCharHandle(PLAYER_PED)
            else
                player_id = tonumber(copy_from_player)
            end
            copy_func(player_id, raw_data_ptr)
        end
    end
    -- function to send packet
    local func_send = function()
        local bs = raknetNewBitStream()
        raknetBitStreamWriteInt8(bs, sync_info[2])
        raknetBitStreamWriteBuffer(bs, raw_data_ptr, ffi.sizeof(data))
        raknetSendBitStreamEx(bs, sampfuncs.HIGH_PRIORITY, sampfuncs.UNRELIABLE_SEQUENCED, 1)
        raknetDeleteBitStream(bs)
    end
    -- metatable to access sync data and 'send' function
    local mt = {
        __index = function(t, index)
            return data[index]
        end,
        __newindex = function(t, index, value)
            data[index] = value
        end
    }
    return setmetatable({send = func_send}, mt)
end
 
Последнее редактирование:

qwеty

Известный
484
156
Как отправить дамаг игроку через булет синхру?
UPD: что не так?
:70: cannot convert 'string' to 'unsigned short'
qweqwe:
function main()
    while not isSampAvailable() do wait(100) end
    sampRegisterChatCommand('bullet', bullet)
    while true do
        wait(0)
    end
end
function bullet(playerid)
    local result, HandlePlayer = sampGetCharHandleBySampPlayerId(playerid)
    local data = samp_create_sync_data('bullet', false)
    data.targetType = 1
    data.targetId = playerid
    data.origin.x, data.origin.y, data.origin.z = getActiveCameraCoordinates()
    data.target.x, data.target.y, data.target.z = getCharCoordinates(HandlePlayer)
    data.weaponId = getCurrentCharWeapon(PLAYER_PED)
    data.send()
    sampAddChatMessage('отправлена: ' ..playerid, -1)
end

function samp_create_sync_data(sync_type, copy_from_player)
    local ffi = require 'ffi'
    local sampfuncs = require 'sampfuncs'
    -- from SAMP.Lua
    local raknet = require 'samp.raknet'
    require 'samp.synchronization'

    copy_from_player = copy_from_player or true
    local sync_traits = {
        player = {'PlayerSyncData', raknet.PACKET.PLAYER_SYNC, sampStorePlayerOnfootData},
        vehicle = {'VehicleSyncData', raknet.PACKET.VEHICLE_SYNC, sampStorePlayerIncarData},
        passenger = {'PassengerSyncData', raknet.PACKET.PASSENGER_SYNC, sampStorePlayerPassengerData},
        aim = {'AimSyncData', raknet.PACKET.AIM_SYNC, sampStorePlayerAimData},
        trailer = {'TrailerSyncData', raknet.PACKET.TRAILER_SYNC, sampStorePlayerTrailerData},
        unoccupied = {'UnoccupiedSyncData', raknet.PACKET.UNOCCUPIED_SYNC, nil},
        bullet = {'BulletSyncData', raknet.PACKET.BULLET_SYNC, nil},
        spectator = {'SpectatorSyncData', raknet.PACKET.SPECTATOR_SYNC, nil}
    }
    local sync_info = sync_traits[sync_type]
    local data_type = 'struct ' .. sync_info[1]
    local data = ffi.new(data_type, {})
    local raw_data_ptr = tonumber(ffi.cast('uintptr_t', ffi.new(data_type .. '*', data)))
    -- copy player's sync data to the allocated memory
    if copy_from_player then
        local copy_func = sync_info[3]
        if copy_func then
            local _, player_id
            if copy_from_player == true then
                _, player_id = sampGetPlayerIdByCharHandle(PLAYER_PED)
            else
                player_id = tonumber(copy_from_player)
            end
            copy_func(player_id, raw_data_ptr)
        end
    end
    -- function to send packet
    local func_send = function()
        local bs = raknetNewBitStream()
        raknetBitStreamWriteInt8(bs, sync_info[2])
        raknetBitStreamWriteBuffer(bs, raw_data_ptr, ffi.sizeof(data))
        raknetSendBitStreamEx(bs, sampfuncs.HIGH_PRIORITY, sampfuncs.UNRELIABLE_SEQUENCED, 1)
        raknetDeleteBitStream(bs)
    end
    -- metatable to access sync data and 'send' function
    local mt = {
        __index = function(t, index)
            return data[index]
        end,
        __newindex = function(t, index, value)
            data[index] = value
        end
    }
    return setmetatable({send = func_send}, mt)
end
up
 
Последнее редактирование:

Senya.Volin

Участник
67
4
Как получить "score" Player'a?

Знімок екрана 2022-08-09 223035.png

При вводе данного текста получится:
Lua:
-- Info for Player: / Nickname Artem_Loshara, ID: 921
А мне нужно, чтобы после данного текста писалось:
-- Info for Player: / Nickname Artem_Loshara, ID: 921, Score: (уровень игрока)
 

shawtyglock.

Активный
186
57
Хочу реализовать создание нового текста в BeginChild окне, вместо "Информация" посредством выбора кнопки, но незнаю как.
Например: Выбираю кнопку настройки и вместо "Информация" неким заголовком будет уже "Настройки".
1660073567132.png
 

Senya.Volin

Участник
67
4
Как получить "score" Player'a?

Посмотреть вложение 161772
При вводе данного текста получится:
Lua:
-- Info for Player: / Nickname Artem_Loshara, ID: 921
А мне нужно, чтобы после данного текста писалось:
-- Info for Player: / Nickname Artem_Loshara, ID: 921, Score: (уровень игрока)
Я попробовал с импровизировать, но получился бред:
Знімок екрана 2022-08-09 224343.png

Знімок екрана 2022-08-09 224349.png

Но при вводе текста - получается совсем не то число:
Знімок екрана 2022-08-09 224355.png

У меня на этом аккаунте 1 уровень.
Скорее всего, это просто не уровень, или рандомное число.

Я попробовал с импровизировать, но получился бред:
Знімок екрана 2022-08-09 224343.png

Знімок екрана 2022-08-09 224349.png

Но при вводе текста - получается совсем не то число:
Знімок екрана 2022-08-09 224355.png

У меня на этом аккаунте 1 уровень.
Скорее всего, это просто не уровень, или рандомное число.
upd: я подумал что это хп :), но сейчас при вводе этой команды показывает: Score: 0. Кароче, я хз шо делать(
 

AntonNeath

Известный
247
108
Имеется текстдрав с определенным идом. При изменении текста в текстдраве нужно выполнение действия. Беда в следующем: айди текстдрава статичен. Любое изменение текста в текстдраве не меняет значения при взятии его sampTextdrawGetString.
Выглядит это так:
Появился нужный текстдрав с текстом 1
sampTextdrawGetString: 1
Текст в текстдраве стал 2
sampTextdrawGetString: 1
Текст в текстдраве стал 52
sampTextdrawGetString: 1
Текст в текстдраве стал 1
sampTextdrawGetString: 1
Как это можно реализовать?
 

T1cKz

Известный
596
246
Имеется текстдрав с определенным идом. При изменении текста в текстдраве нужно выполнение действия. Беда в следующем: айди текстдрава статичен. Любое изменение текста в текстдраве не меняет значения при взятии его sampTextdrawGetString.
Выглядит это так:
Появился нужный текстдрав с текстом 1
Консоль: 1
Текст в текстдраве стал 2
Консоль: 1
Текст в текстдраве стал 52
Консоль: 1
Текст в текстдраве стал 1
Консоль: 1
Как это можно реализовать?
Если текстдрав меняет текст то там варика 2. Либо textDrawSetString (хук) либо перепоказ его и ты увидешь в onShowTextdraw(хук) оттуда и можешь ловить