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

Pashyka

Участник
220
17
Приветствую, уважаемые скриптеры)
Такая вот проблема, я хочу реализовать скрипт, который ищет капс в чате и считает все буквы капсом, чтобы легче было выдавать муты игрокам.
Я сделал данный скрипт, но он работает не точно, дело в том, что скрипт хоть и ищет заглавные буквы, например, игрок написал слово "ПРИВЕТ", скрипт посчитал в этом слове 6 букв заглавных. Далее, если игрок напишет слово ПРИВЕЕЕЕТ, то он все равно посчитает 6 букв заглавных, вместо 9-ти. Код приложу ниже.

Кодик:
local sampev = require 'samp.events'
require 'lib.moonloader'
local keys = require "vkeys"

local bykv = {"А","Б","В","Г","Д","Е","Ж","З","И","Й","К","Л","М","Н","О","П","Р","С","Т","У","Ф","Х","Ц","Ч","Ш","Щ","Ъ","Ы","Ь","Э","Ю","Я"}

local rabota = false
local bykvi = 0
time = 30
statustime = false

function main()
    while not isSampAvailable() do wait(100) end
    sampRegisterChatCommand("mut", function()
        rabota = not rabota
        sampAddChatMessage(rabota and "{00FF44}Скрипт включен" or "{FF0000}Скрипт выключен",-1)
    end)
    sampRegisterChatCommand("gg", function()
        sampAddChatMessage("Букв в переменной - " .. bykvi, -1)
    end)
    sampRegisterChatCommand("stime", function()
        statustime = not statustime
        if statustime == false then
            sampAddChatMessage("Мут на 30 минут установлен", -1)
            time = 30
        else
            sampAddChatMessage("Мут на 100 минут установлен", -1)
            time = 100
        end
    end)
    sampAddChatMessage("{00E8E8} Скрипт активирован", -1)
    while true do
        wait(0)
        if wasKeyPressed(VK_XBUTTON2) and not sampIsChatInputActive() and bykvi >= 10 then
            sampSetChatInputEnabled(true)
            sampSetChatInputText("/mute " .. id .. " " .. time .. " капс")
            bykvi = 0
        end
    end
end

function sampev.onServerMessage(color, text)
    if rabota then
        if text:find("%{F345FC%}%[PREMIUM%] %{FFFFFF%}(%a+_%a+)%[(%d+)%]: (.+)") and bykvi < 10 then
            nick, id, textik = text:match("%{F345FC%}%[PREMIUM%] %{FFFFFF%}(%a+_%a+)%[(%d+)%]: (.+)")
            for i, v in pairs(bykv) do
                if string.find(textik, v) then
                    bykvi = bykvi + 1
                end
            end
            if bykvi >= 10 then
                sampAddChatMessage("{FF0077}[WARNING] " .. bykvi.." букв капсом, игрок: "..nick.."["..id.."]", -1)
            end
            elseif bykvi < 10 then
            bykvi = 0
        end
        if text:find("%{6495ED%}%[VIP%] %{FFFFFF%}(%a+_%a+)%[(%d+)%]: (.+)") and bykvi < 10 then
            nick, id, textik = text:match("%{6495ED%}%[VIP%] %{FFFFFF%}(%a+_%a+)%[(%d+)%]: (.+)")
            for i, v in pairs(bykv) do
                if string.find(textik, v) then
                    bykvi = bykvi + 1
                end
            end
            if bykvi >= 10 then
                sampAddChatMessage("{FF0077}[WARNING] " .. bykvi.." букв капсом, игрок: "..nick.."["..id.."]", -1)
            end
            elseif bykvi < 10 then
            bykvi = 0
        end
    end
end

В коде много мусора, так как надо проверять переменные, чтобы не было ошибок. Помогите пожалуйста, что-то не сильно понимаю, как можно это исправить
 

Rei

Известный
Друг
1,633
1,704
Приветствую, уважаемые скриптеры)
Такая вот проблема, я хочу реализовать скрипт, который ищет капс в чате и считает все буквы капсом, чтобы легче было выдавать муты игрокам.
Я сделал данный скрипт, но он работает не точно, дело в том, что скрипт хоть и ищет заглавные буквы, например, игрок написал слово "ПРИВЕТ", скрипт посчитал в этом слове 6 букв заглавных. Далее, если игрок напишет слово ПРИВЕЕЕЕТ, то он все равно посчитает 6 букв заглавных, вместо 9-ти. Код приложу ниже.

Кодик:
local sampev = require 'samp.events'
require 'lib.moonloader'
local keys = require "vkeys"

local bykv = {"А","Б","В","Г","Д","Е","Ж","З","И","Й","К","Л","М","Н","О","П","Р","С","Т","У","Ф","Х","Ц","Ч","Ш","Щ","Ъ","Ы","Ь","Э","Ю","Я"}

local rabota = false
local bykvi = 0
time = 30
statustime = false

function main()
    while not isSampAvailable() do wait(100) end
    sampRegisterChatCommand("mut", function()
        rabota = not rabota
        sampAddChatMessage(rabota and "{00FF44}Скрипт включен" or "{FF0000}Скрипт выключен",-1)
    end)
    sampRegisterChatCommand("gg", function()
        sampAddChatMessage("Букв в переменной - " .. bykvi, -1)
    end)
    sampRegisterChatCommand("stime", function()
        statustime = not statustime
        if statustime == false then
            sampAddChatMessage("Мут на 30 минут установлен", -1)
            time = 30
        else
            sampAddChatMessage("Мут на 100 минут установлен", -1)
            time = 100
        end
    end)
    sampAddChatMessage("{00E8E8} Скрипт активирован", -1)
    while true do
        wait(0)
        if wasKeyPressed(VK_XBUTTON2) and not sampIsChatInputActive() and bykvi >= 10 then
            sampSetChatInputEnabled(true)
            sampSetChatInputText("/mute " .. id .. " " .. time .. " капс")
            bykvi = 0
        end
    end
end

function sampev.onServerMessage(color, text)
    if rabota then
        if text:find("%{F345FC%}%[PREMIUM%] %{FFFFFF%}(%a+_%a+)%[(%d+)%]: (.+)") and bykvi < 10 then
            nick, id, textik = text:match("%{F345FC%}%[PREMIUM%] %{FFFFFF%}(%a+_%a+)%[(%d+)%]: (.+)")
            for i, v in pairs(bykv) do
                if string.find(textik, v) then
                    bykvi = bykvi + 1
                end
            end
            if bykvi >= 10 then
                sampAddChatMessage("{FF0077}[WARNING] " .. bykvi.." букв капсом, игрок: "..nick.."["..id.."]", -1)
            end
            elseif bykvi < 10 then
            bykvi = 0
        end
        if text:find("%{6495ED%}%[VIP%] %{FFFFFF%}(%a+_%a+)%[(%d+)%]: (.+)") and bykvi < 10 then
            nick, id, textik = text:match("%{6495ED%}%[VIP%] %{FFFFFF%}(%a+_%a+)%[(%d+)%]: (.+)")
            for i, v in pairs(bykv) do
                if string.find(textik, v) then
                    bykvi = bykvi + 1
                end
            end
            if bykvi >= 10 then
                sampAddChatMessage("{FF0077}[WARNING] " .. bykvi.." букв капсом, игрок: "..nick.."["..id.."]", -1)
            end
            elseif bykvi < 10 then
            bykvi = 0
        end
    end
end

В коде много мусора, так как надо проверять переменные, чтобы не было ошибок. Помогите пожалуйста, что-то не сильно понимаю, как можно это исправить
Гугли что-то типа lua loop through string и прикручивай
 

morti.

Участник
63
3
Если в игре в команде /afind прописываю например аргумент 346, то ничего не происходит, помогите.
Lua:
 function cmd_afind(arg)
         if #arg == 0 then
             sampAddChatMessage(red .. '[mini commands] ' .. yellow .. 'Введите ' .. white .. '/afind ' .. green .. '[ID]', blue1)
         if #arg ~= nil then
             sampSendChat('/autofind' .. arg)
         end
     end
     end
 

Pelmeska

Известный
934
229
Если в игре в команде /afind прописываю например аргумент 346, то ничего не происходит, помогите.
Lua:
 function cmd_afind(arg)
         if #arg == 0 then
             sampAddChatMessage(red .. '[mini commands] ' .. yellow .. 'Введите ' .. white .. '/afind ' .. green .. '[ID]', blue1)
         if #arg ~= nil then
             sampSendChat('/autofind' .. arg)
         end
     end
     end
Lua:
 function cmd_afind(arg)
         if #arg == 0 then
             sampAddChatMessage(red .. '[mini commands] ' .. yellow .. 'Введите ' .. white .. '/afind ' .. green .. '[ID]', blue1)
         else
             sampSendChat('/autofind' .. arg)
         end
     end
 

morti.

Участник
63
3
Lua:
 function cmd_afind(arg)
         if #arg == 0 then
             sampAddChatMessage(red .. '[mini commands] ' .. yellow .. 'Введите ' .. white .. '/afind ' .. green .. '[ID]', blue1)
         else
             sampSendChat('/autofind' .. arg)
         end
     end
Не работает, в игре при вводе аргумента пишет что команды такой нету, но она на самом деле есть
 

Pelmeska

Известный
934
229
Не работает, в игре при вводе аргумента пишет что команды такой нету, но она на самом деле есть
пробел после /autofind нужно поставить чтоб твой аргумент прописывался нормально, без пробела он слитно команду и аргумент пишет
Lua:
 function cmd_afind(arg)
         if #arg == 0 then
             sampAddChatMessage(red .. '[mini commands] ' .. yellow .. 'Введите ' .. white .. '/afind ' .. green .. '[ID]', blue1)
         else
             sampSendChat('/autofind ' .. arg)
         end
     end
 

saspepir

Участник
64
2
крашит когда беру статус потока, можете помочь?
получаю статус и крашит:
lua_thread.create(function()
    strr = lua_thread:status()
end)
 

Corrygаn

Участник
225
6
Lua:
local imgui = require('imgui')
local encoding = require 'encoding'
encoding.default = 'CP1251'
u8 = encoding.UTF8
local ffi = require "ffi"
local getBonePosition = ffi.cast("int (__thiscall*)(void*, float*, int, bool)", 0x5E4280)

local skeletal_wh = imgui.ImBool(false)
local window = imgui.ImBool(false)

function main()
    while not isSampAvailable() do wait(200) end
    imgui.Process = false
    window.v = true  --show window
    while true do
        wait(0)
        imgui.Process = window.v
        if skeletal_wh.v then boneWh() end
    end
end

function imgui.OnDrawFrame()
    if window.v then
        imgui.SetNextWindowPos(imgui.ImVec2(350.0, 250.0), imgui.Cond.FirstUseEver)
        imgui.SetNextWindowSize(imgui.ImVec2(280.0, 70.0), imgui.Cond.FirstUseEver)
        imgui.Begin('Window Title', window)

        imgui.Checkbox('wh', skeletal_wh)

        imgui.End()
    end
end

function join_argb(a, r, g, b)
    local argb = b  -- b
    argb = bit.bor(argb, bit.lshift(g, 8))  -- g
    argb = bit.bor(argb, bit.lshift(r, 16)) -- r
    argb = bit.bor(argb, bit.lshift(a, 24)) -- a
    return argb
  end

  function explode_argb(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

function bonewh()
    lua_thread.create(function()
        for k, i in ipairs(getAllChars()) do
            pedX, pedY, pedZ = getCharCoordinates(i)
            myX, myY, myZ = getCharCoordinates(PLAYER_PED)
            ance = getDistanceBetweenCoords3d(pedX, pedY, pedZ, myX, myY, myZ)
           
            oesCharExist(i) and isCharOnScreen(i) and i ~= PLAYER_PED then
            _, id = sampGetPlayerIdByCharHandle(i)
            local color = sampGetPlayerColor(id)
            local aa, rr, gg, bb = explode_argb(color)
            local color = join_argb(255, rr, gg, bb)
   
            thickness = 3 --толщина
           
            pos1X, pos1Y, pos1Z = getBodyPartCoordinates(6, i)
            pos2X, pos2Y, pos2Z = getBodyPartCoordinates(7, i)
           
            pos1, pos2 = convert3DCoordsToScreen(pos1X, pos1Y, pos1Z)
            pos3, pos4 = convert3DCoordsToScreen(pos2X, pos2Y, pos2Z)
            renderDrawLine(pos1, pos2, pos3, pos4, thickness, color)
   
            pos1X, pos1Y, pos1Z = getBodyPartCoordinates(7, i)
            pos2X, pos2Y, pos2Z = getBodyPartCoordinates(8, i)
           
            pos1, pos2 = convert3DCoordsToScreen(pos1X, pos1Y, pos1Z)
            pos3, pos4 = convert3DCoordsToScreen(pos2X, pos2Y, pos2Z)
            renderDrawLine(pos1, pos2, pos3, pos4, thickness, color)
   
            pos1X, pos1Y, pos1Z = getBodyPartCoordinates(8, i)
            pos2X, pos2Y, pos2Z = getBodyPartCoordinates(6, i)
           
            pos1, pos2 = convert3DCoordsToScreen(pos1X, pos1Y, pos1Z)
            pos3, pos4 = convert3DCoordsToScreen(pos2X, pos2Y, pos2Z)
            renderDrawLine(pos1, pos2, pos3, pos4, thickness, color)
           
           
           
            pos1X, pos1Y, pos1Z = getBodyPartCoordinates(1, i)
            pos2X, pos2Y, pos2Z = getBodyPartCoordinates(4, i)
           
            pos1, pos2 = convert3DCoordsToScreen(pos1X, pos1Y, pos1Z)
            pos3, pos4 = convert3DCoordsToScreen(pos2X, pos2Y, pos2Z)
            renderDrawLine(pos1, pos2, pos3, pos4, thickness, color)
   
            pos1X, pos1Y, pos1Z = getBodyPartCoordinates(4, i)
            pos2X, pos2Y, pos2Z = getBodyPartCoordinates(8, i)
           
            pos1, pos2 = convert3DCoordsToScreen(pos1X, pos1Y, pos1Z)
            pos3, pos4 = convert3DCoordsToScreen(pos2X, pos2Y, pos2Z)
            renderDrawLine(pos1, pos2, pos3, pos4, thickness, color)
           
   
           
            pos1X, pos1Y, pos1Z = getBodyPartCoordinates(21, i)
            pos2X, pos2Y, pos2Z = getBodyPartCoordinates(22, i)
           
            pos1, pos2 = convert3DCoordsToScreen(pos1X, pos1Y, pos1Z)
            pos3, pos4 = convert3DCoordsToScreen(pos2X, pos2Y, pos2Z)
            renderDrawLine(pos1, pos2, pos3, pos4, thickness, color)
   
            pos1X, pos1Y, pos1Z = getBodyPartCoordinates(22, i)
            pos2X, pos2Y, pos2Z = getBodyPartCoordinates(23, i)
           
            pos1, pos2 = convert3DCoordsToScreen(pos1X, pos1Y, pos1Z)
            pos3, pos4 = convert3DCoordsToScreen(pos2X, pos2Y, pos2Z)
            renderDrawLine(pos1, pos2, pos3, pos4, thickness, color)
   
            pos1X, pos1Y, pos1Z = getBodyPartCoordinates(23, i)
            pos2X, pos2Y, pos2Z = getBodyPartCoordinates(24, i)
           
            pos1, pos2 = convert3DCoordsToScreen(pos1X, pos1Y, pos1Z)
            pos3, pos4 = convert3DCoordsToScreen(pos2X, pos2Y, pos2Z)
            renderDrawLine(pos1, pos2, pos3, pos4, thickness, color)
   
            pos1X, pos1Y, pos1Z = getBodyPartCoordinates(24, i)
            pos2X, pos2Y, pos2Z = getBodyPartCoordinates(25, i)
           
            pos1, pos2 = convert3DCoordsToScreen(pos1X, pos1Y, pos1Z)
            pos3, pos4 = convert3DCoordsToScreen(pos2X, pos2Y, pos2Z)
            renderDrawLine(pos1, pos2, pos3, pos4, thickness, color)
           
   
           
            pos1X, pos1Y, pos1Z = getBodyPartCoordinates(31, i)
            pos2X, pos2Y, pos2Z = getBodyPartCoordinates(32, i)
           
            pos1, pos2 = convert3DCoordsToScreen(pos1X, pos1Y, pos1Z)
            pos3, pos4 = convert3DCoordsToScreen(pos2X, pos2Y, pos2Z)
            renderDrawLine(pos1, pos2, pos3, pos4, thickness, color)
   
            pos1X, pos1Y, pos1Z = getBodyPartCoordinates(32, i)
            pos2X, pos2Y, pos2Z = getBodyPartCoordinates(33, i)
           
            pos1, pos2 = convert3DCoordsToScreen(pos1X, pos1Y, pos1Z)
            pos3, pos4 = convert3DCoordsToScreen(pos2X, pos2Y, pos2Z)
            renderDrawLine(pos1, pos2, pos3, pos4, thickness, color)
   
            pos1X, pos1Y, pos1Z = getBodyPartCoordinates(33, i)
            pos2X, pos2Y, pos2Z = getBodyPartCoordinates(34, i)
           
            pos1, pos2 = convert3DCoordsToScreen(pos1X, pos1Y, pos1Z)
            pos3, pos4 = convert3DCoordsToScreen(pos2X, pos2Y, pos2Z)
            renderDrawLine(pos1, pos2, pos3, pos4, thickness, color)
   
            pos1X, pos1Y, pos1Z = getBodyPartCoordinates(34, i)
            pos2X, pos2Y, pos2Z = getBodyPartCoordinates(35, i)
           
            pos1, pos2 = convert3DCoordsToScreen(pos1X, pos1Y, pos1Z)
            pos3, pos4 = convert3DCoordsToScreen(pos2X, pos2Y, pos2Z)
            renderDrawLine(pos1, pos2, pos3, pos4, thickness, color)
           
   
           
            pos1X, pos1Y, pos1Z = getBodyPartCoordinates(1, i)
            pos2X, pos2Y, pos2Z = getBodyPartCoordinates(51, i)
           
            pos1, pos2 = convert3DCoordsToScreen(pos1X, pos1Y, pos1Z)
            pos3, pos4 = convert3DCoordsToScreen(pos2X, pos2Y, pos2Z)
            renderDrawLine(pos1, pos2, pos3, pos4, thickness, color)
            pos1X, pos1Y, pos1Z = getBodyPartCoordinates(51, i)
            pos2X, pos2Y, pos2Z = getBodyPartCoordinates(52, i)
           
            pos1, pos2 = convert3DCoordsToScreen(pos1X, pos1Y, pos1Z)
            pos3, pos4 = convert3DCoordsToScreen(pos2X, pos2Y, pos2Z)
            renderDrawLine(pos1, pos2, pos3, pos4, thickness, color)
   
            pos1X, pos1Y, pos1Z = getBodyPartCoordinates(52, i)
            pos2X, pos2Y, pos2Z = getBodyPartCoordinates(53, i)
           
            pos1, pos2 = convert3DCoordsToScreen(pos1X, pos1Y, pos1Z)
            pos3, pos4 = convert3DCoordsToScreen(pos2X, pos2Y, pos2Z)
            renderDrawLine(pos1, pos2, pos3, pos4, thickness, color)
   
            pos1X, pos1Y, pos1Z = getBodyPartCoordinates(53, i)
            pos2X, pos2Y, pos2Z = getBodyPartCoordinates(54, i)
           
            pos1, pos2 = convert3DCoordsToScreen(pos1X, pos1Y, pos1Z)
            pos3, pos4 = convert3DCoordsToScreen(pos2X, pos2Y, pos2Z)
            renderDrawLine(pos1, pos2, pos3, pos4, thickness, color)
           
   
           
            pos1X, pos1Y, pos1Z = getBodyPartCoordinates(1, i)
            pos2X, pos2Y, pos2Z = getBodyPartCoordinates(41, i)
           
            pos1, pos2 = convert3DCoordsToScreen(pos1X, pos1Y, pos1Z)
            pos3, pos4 = convert3DCoordsToScreen(pos2X, pos2Y, pos2Z)
            renderDrawLine(pos1, pos2, pos3, pos4, thickness, color)
   
            pos1X, pos1Y, pos1Z = getBodyPartCoordinates(41, i)
            pos2X, pos2Y, pos2Z = getBodyPartCoordinates(42, i)
           
            pos1, pos2 = convert3DCoordsToScreen(pos1X, pos1Y, pos1Z)
            pos3, pos4 = convert3DCoordsToScreen(pos2X, pos2Y, pos2Z)
            renderDrawLine(pos1, pos2, pos3, pos4, thickness, color)
   
            pos1X, pos1Y, pos1Z = getBodyPartCoordinates(42, i)
            pos2X, pos2Y, pos2Z = getBodyPartCoordinates(43, i)
           
            pos1, pos2 = convert3DCoordsToScreen(pos1X, pos1Y, pos1Z)
            pos3, pos4 = convert3DCoordsToScreen(pos2X, pos2Y, pos2Z)
            renderDrawLine(pos1, pos2, pos3, pos4, thickness, color)
   
            pos1X, pos1Y, pos1Z = getBodyPartCoordinates(43, i)
            pos2X, pos2Y, pos2Z = getBodyPartCoordinates(44, i)
           
            pos1, pos2 = convert3DCoordsToScreen(pos1X, pos1Y, pos1Z)
            pos3, pos4 = convert3DCoordsToScreen(pos2X, pos2Y, pos2Z)
            renderDrawLine(pos1, pos2, pos3, pos4, thickness, color)

            pos2X, pos2Y, pos2Z = getBodyPartCoordinates(44, i)
            pos3, pos4 = convert3DCoordsToScreen(pos2X, pos2Y, pos2Z)
            renderDrawPolygon(pos3, pos4, thickness, thickness, 100, 0, color)  
            end  
        end
    end)
end

function getBodyPartCoordinates(id, handle)
    if doesCharExist(handle) then
        local pedptr = getCharPointer(handle)
        local vec = ffi.new("float[3]")
        getBonePosition(ffi.cast("void*", pedptr), vec, id, true)
        return vec[0], vec[1], vec[2]
    end
end
D:\ARIZONA GAMES\bin\Arizona\moonloader\MVD Helper.lua:186: unexpected symbol near 'and'

oesCharExist(i) and isCharOnScreen(i) and i ~= PLAYER_PED then
 

ewin

Известный
672
376
пытаюсь хукнуть эту строку из чата:
Alan_Butler[666] - [60 lvl] -{FFFFFF} [AFK: 0]{FFFFFF} - Репутация: 1111

вот таким кодом:
(%s+)%[(%d+)%] - %[(%d+) lvl%] (.+) - Репутация: (%d+)

но работать не хочет, в чем проблема?