SC23 Lua sphere.lua

Fretsi_Rewy

Участник
33
1
fzjNwSO.png


SPHERE.LUA

Скрипт позволяет создавать до 10-ти сфер в любой точке карты и отслеживать события, которые происходят внутри них.

Доступные события:
1. Вход/выход из сферы
2. Текст над головой
3. Кто-то достал/спрятал оружие

Все события записываются в лог, если активен соответствующий чекбокс.
(Функция записи в лог немного кривая: если в логе ~50+ строк, то скрипт начинает очень сильно кушать ФПС.)

Также в отдельном mimgui-окне можно просмотреть информацию о игроках, которые сейчас находятся внутри сферы.

Скриншоты:
ggIJJBv.png

lsBzd9u.png

9SQtkCH.png

QN9k7ER.png

RoGz022.png

Зависимости:
CJson
mimgui
fAwesome5
SAMP.lua
lfs

Активация:
/sphere
При заходе в игру откривается и незакривается доработай пожалуста а так скрипт хороший.
 

Tak

Известный
177
70
Вот это да, недавно только о таком думал. Прям из головы считал. И меню хорошо выглядит 👍
 

chromiusj

Kommando-Leiteinheit Bioresonanztechnik-Replika
Модератор
5,514
3,842
Почему-то от сферы у меня осталось какое-то желание докончить дело до конца,и попробовать создать свою не на рендерах что так жрут фпс,а на дравлистах(которые жрут фпс в х2 размере)
Lua:
-- radius - радиус сферы
-- heighSegments - количество сегментов для создания псевдосферы(да,именно псевдосферы)
function imgui.DrawSphereAtPlayer(radius, heightSegments) -- создает сферу на персонаже
    local sphere_data = {
        longitude_segments = 32,
        latitude_segments = heightSegments or 16,
    }

    local pos = { getBodyPartCoordinates(1, PLAYER_PED) }
    local offset = radius

    local dl = imgui.GetBackgroundDrawList()

    -- Draw lines around the sphere
    for i = 0, sphere_data.longitude_segments - 1 do
        local theta1 = i * (2 * math.pi) / sphere_data.longitude_segments
        local theta2 = (i + 1) * (2 * math.pi) / sphere_data.longitude_segments

        local x1 = math.cos(theta1) * radius
        local y1 = math.sin(theta1) * radius
        local z1 = 0

        local x2 = math.cos(theta2) * radius
        local y2 = math.sin(theta2) * radius
        local z2 = 0

        local startX1, startY1 = convert3DCoordsToScreen(x1 + pos[1], y1 + pos[2], z1 + pos[3])
        local startX2, startY2 = convert3DCoordsToScreen(x2 + pos[1], y2 + pos[2], z2 + pos[3])

        dl:AddLine(imgui.ImVec2(startX1 + offset, startY1 + offset), imgui.ImVec2(startX2 + offset, startY2 + offset), 0xFF0000FF, 1.0)
    end

    for i = 1, sphere_data.latitude_segments - 1 do
        local phi = i * math.pi / sphere_data.latitude_segments
        local cos_phi = math.cos(phi)
        local sin_phi = math.sin(phi)

        for j = 0, sphere_data.longitude_segments - 1 do
            local theta = j * (2 * math.pi) / sphere_data.longitude_segments
            local x = cos_phi * math.cos(theta) * radius
            local y = cos_phi * math.sin(theta) * radius
            local z = sin_phi * radius

            local startX, startY = convert3DCoordsToScreen(x + pos[1], y + pos[2], z + pos[3])
            local endX, endY = convert3DCoordsToScreen(x + pos[1], y + pos[2], -z + pos[3])

            dl:AddLine(imgui.ImVec2(startX + offset, startY + offset), imgui.ImVec2(endX + offset, endY + offset), 0xFF0000FF, 1.0)
        end
    end
end
1703459290355.png
1703459498942.png

надеюсь найдутся умные люди,которые напишут 3д сферу и объяснят не шарящим в геометрии
либо же я доведу это дело до логичного конца
упд:
можете стереть первый цикл,чтобы не рисовать эту линию вокруг персонажа
 
  • Нравится
Реакции: MLycoris

Andrinall

Известный
702
518
Почему-то от сферы у меня осталось какое-то желание докончить дело до конца,и попробовать создать свою не на рендерах что так жрут фпс,а на дравлистах(которые жрут фпс в х2 размере)
Lua:
-- radius - радиус сферы
-- heighSegments - количество сегментов для создания псевдосферы(да,именно псевдосферы)
function imgui.DrawSphereAtPlayer(radius, heightSegments) -- создает сферу на персонаже
    local sphere_data = {
        longitude_segments = 32,
        latitude_segments = heightSegments or 16,
    }

    local pos = { getBodyPartCoordinates(1, PLAYER_PED) }
    local offset = radius

    local dl = imgui.GetBackgroundDrawList()

    -- Draw lines around the sphere
    for i = 0, sphere_data.longitude_segments - 1 do
        local theta1 = i * (2 * math.pi) / sphere_data.longitude_segments
        local theta2 = (i + 1) * (2 * math.pi) / sphere_data.longitude_segments

        local x1 = math.cos(theta1) * radius
        local y1 = math.sin(theta1) * radius
        local z1 = 0

        local x2 = math.cos(theta2) * radius
        local y2 = math.sin(theta2) * radius
        local z2 = 0

        local startX1, startY1 = convert3DCoordsToScreen(x1 + pos[1], y1 + pos[2], z1 + pos[3])
        local startX2, startY2 = convert3DCoordsToScreen(x2 + pos[1], y2 + pos[2], z2 + pos[3])

        dl:AddLine(imgui.ImVec2(startX1 + offset, startY1 + offset), imgui.ImVec2(startX2 + offset, startY2 + offset), 0xFF0000FF, 1.0)
    end

    for i = 1, sphere_data.latitude_segments - 1 do
        local phi = i * math.pi / sphere_data.latitude_segments
        local cos_phi = math.cos(phi)
        local sin_phi = math.sin(phi)

        for j = 0, sphere_data.longitude_segments - 1 do
            local theta = j * (2 * math.pi) / sphere_data.longitude_segments
            local x = cos_phi * math.cos(theta) * radius
            local y = cos_phi * math.sin(theta) * radius
            local z = sin_phi * radius

            local startX, startY = convert3DCoordsToScreen(x + pos[1], y + pos[2], z + pos[3])
            local endX, endY = convert3DCoordsToScreen(x + pos[1], y + pos[2], -z + pos[3])

            dl:AddLine(imgui.ImVec2(startX + offset, startY + offset), imgui.ImVec2(endX + offset, endY + offset), 0xFF0000FF, 1.0)
        end
    end
end
Посмотреть вложение 225887Посмотреть вложение 225888
надеюсь найдутся умные люди,которые напишут 3д сферу и объяснят не шарящим в геометрии
либо же я доведу это дело до логичного конца
упд:
можете стереть первый цикл,чтобы не рисовать эту линию вокруг персонажа
Есть такой вот прототип для рисования секционной сферы по этому примеру

1703482414524.png


Но я пока не допёр как её заполнить(PathFillConvex не подходит)
Lua:
function drawCircle3D(pos, step)
    local dl = imgui.GetBackgroundDrawList()
    for i = 0, 360, 6 do
        local a = getPointOnCurve(math.rad(0), math.rad(i), 2, 64, 64)
        local x1, y1 = convert3DCoordsToScreen(pos.x + a.x, pos.y + a.y, pos.z)
        local x2, y2 = convert3DCoordsToScreen(pos.x + a.x, pos.y, pos.z + a.y)
        local x3, y3 = convert3DCoordsToScreen(pos.x, pos.y + a.x, pos.z + a.y)
        dl:PathLineTo(imgui.ImVec2(step == 1 and x1 or step == 2 and x2 or x3, step == 1 and y1 or step == 2 and y2 or y3))
    end
    dl:PathStroke(0xAAFFFFFF, false, 1)
end

imgui.OnFrame(function() return true end, function()
    local pos = Vector3D(10, 10, 5)
    drawCircle3D(pos, 1)
    drawCircle3D(pos, 2)
    drawCircle3D(pos, 3)
end).HideCursor = true

function getPointOnCurve(cstart, cend, cradius, point, max_points)
    local a = cstart + (point / max_points) * (cend - cstart)
    return imgui.ImVec2(math.cos(a) * cradius, math.sin(a) * cradius)
end
1703482380832.png


UPD:

Такой вот клубочек тебе сойдёт?)
segments = 1
1703488390359.png

segments = 2
1703488371071.png

segments = 3
1703488404449.png
Lua:
---@param pos > Vector3D
---@param radius > number
---@param segments > number ( 1 - 3 )
---@param color > number ( hex )
---@param linesStem > number ( 1 - 90 ) лучше не указывать вообще, а то ещё игру положишь
function drawSphere3D(pos, radius, segments, color, linesStep)
    local dl = imgui.GetBackgroundDrawList()
    local function drawCircle3D(segment)
        for line = 0, 360, linesStep and linesStep * 4 or 40 do
            for i = 0, 360, linesStep or 10 do
                local a = getPointOnCurve(math.rad(i), math.rad(i), radius, 64, 64)
                local x, y, z
                if segment == 1 then
                    x, y, z =
                        pos.x + a.x,
                        pos.y + a.y * math.sin(math.rad(line)),
                        pos.z + a.y * math.cos(math.rad(line))
                elseif segment == 2 then
                    x, y, z =
                        pos.x + a.x * math.cos(math.rad(line)),
                        pos.y + a.x * math.sin(math.rad(line)),
                        pos.z + a.y
                elseif segment == 3 then
                    x, y, z =
                        pos.x + a.x * math.sin(math.rad(line)),
                        pos.y + a.y,
                        pos.z + a.x * math.cos(math.rad(line))
                end

                if isPointOnScreen(x, y, z, 0) then
                    dl:PathLineTo(imgui.ImVec2(convert3DCoordsToScreen(x, y, z)))
                end
            end
        end
        dl:PathStroke(color, false, 1)
    end

    for segment = 1, (segments and segments <= 3) and segments or 1 do
        drawCircle3D(segment)
    end
end

imgui.OnFrame(function() return true end, function()
    local pos = Vector3D(10, 10, 5)
    drawSphere3D(pos, 5, 3, 0xFFFFFFFF)
end).HideCursor = true

function getPointOnCurve(cstart, cend, cradius, point, max_points)
    local a = cstart + (point / max_points) * (cend - cstart)
    return imgui.ImVec2(math.cos(a) * cradius, math.sin(a) * cradius)
end
Да с*** е****я геометрия я её рот шатал
 
Последнее редактирование:

chromiusj

Kommando-Leiteinheit Bioresonanztechnik-Replika
Модератор
5,514
3,842
Есть такой вот прототип для рисования секционной сферы по этому примеру

Посмотреть вложение 225903

Но я пока не допёр как её заполнить(PathFillConvex не подходит)
Lua:
function drawCircle3D(pos, step)
    local dl = imgui.GetBackgroundDrawList()
    for i = 0, 360, 6 do
        local a = getPointOnCurve(math.rad(0), math.rad(i), 2, 64, 64)
        local x1, y1 = convert3DCoordsToScreen(pos.x + a.x, pos.y + a.y, pos.z)
        local x2, y2 = convert3DCoordsToScreen(pos.x + a.x, pos.y, pos.z + a.y)
        local x3, y3 = convert3DCoordsToScreen(pos.x, pos.y + a.x, pos.z + a.y)
        dl:PathLineTo(imgui.ImVec2(step == 1 and x1 or step == 2 and x2 or x3, step == 1 and y1 or step == 2 and y2 or y3))
    end
    dl:PathStroke(0xAAFFFFFF, false, 1)
end

imgui.OnFrame(function() return true end, function()
    local pos = Vector3D(10, 10, 5)
    drawCircle3D(pos, 1)
    drawCircle3D(pos, 2)
    drawCircle3D(pos, 3)
end).HideCursor = true

function getPointOnCurve(cstart, cend, cradius, point, max_points)
    local a = cstart + (point / max_points) * (cend - cstart)
    return imgui.ImVec2(math.cos(a) * cradius, math.sin(a) * cradius)
end
Посмотреть вложение 225902

UPD:

Такой вот клубочек тебе сойдёт?)
Lua:
---@param pos > Vector3D
---@param radius > number
---@param segments > number ( 1 - 3 )
---@param color > number ( hex )
---@param linesStem > number ( 1 - 90 ) лучше не указывать вообще, а то ещё игру положишь
function drawSphere3D(pos, radius, segments, color, linesStep)
    local dl = imgui.GetBackgroundDrawList()
    local function drawCircle3D(segment)
        for line = 0, 360, linesStep and linesStep * 4 or 40 do
            for i = 0, 360, linesStep or 10 do
                local a = getPointOnCurve(math.rad(i), math.rad(i), radius, 64, 64)
                local x, y, z
                if segment == 1 then
                    x, y, z =
                        pos.x + a.x,
                        pos.y + a.y * math.sin(math.rad(line)),
                        pos.z + a.y * math.cos(math.rad(line))
                elseif segment == 2 then
                    x, y, z =
                        pos.x + a.x * math.cos(math.rad(line)),
                        pos.y + a.x * math.sin(math.rad(line)),
                        pos.z + a.y
                elseif segment == 3 then
                    x, y, z =
                        pos.x + a.x * math.sin(math.rad(line)),
                        pos.y + a.y,
                        pos.z + a.x * math.cos(math.rad(line))
                end

                if isPointOnScreen(x, y, z, 0) then
                    dl:PathLineTo(imgui.ImVec2(convert3DCoordsToScreen(x, y, z)))
                end
            end
        end
        dl:PathStroke(color, false, 1)
    end

    for segment = 1, (segments and segments <= 3) and segments or 1 do
        drawCircle3D(segment)
    end
end

imgui.OnFrame(function() return true end, function()
    local pos = Vector3D(10, 10, 5)
    drawSphere3D(pos, 5, 3, 0xFFFFFFFF)
end).HideCursor = true

function getPointOnCurve(cstart, cend, cradius, point, max_points)
    local a = cstart + (point / max_points) * (cend - cstart)
    return imgui.ImVec2(math.cos(a) * cradius, math.sin(a) * cradius)
end
Да с*** е****я геометрия я её рот шатал
Гений во плоти,спасибо)
Вообще,я пытался переделать сишные круги с всяких ваших брокенокоров, unknowngamer,но натыкался на непонятные приколы в виде convex,не понимая что с этим делать
Пример: https://www.unknowncheats.me/forum/c-and-c-/125765-drawsphere-optimization.html
(это не имгуи,но все же)
 

Andrinall

Известный
702
518
Вообще,я пытался переделать сишные круги с всяких ваших брокенокоров, unknowngamer,но натыкался на непонятные приколы в виде convex,не понимая что с этим делать
Пример: https://www.unknowncheats.me/forum/c-and-c-/125765-drawsphere-optimization.html
Хз, заняло меньше 10 минут.
Lua:
local imgui = require 'mimgui'
local Vector3D = require 'vector3d'

local PreComputedSpheres = {}

---@param location > Vector3D
---@param radius   > number ( float )
---@param color    > number ( hex )
function DrawPointSphere(draw_list, location, radius, color)
    for _, p in ipairs(PreComputedSpheres) do
        if p.radius == radius then
            local prev
            for _, vertex in ipairs(p.vertices) do
                local point = location + vertex
                if isPointOnScreen(point.x, point.y, point.z, 0.1) then
                    point.x, point.y = convert3DCoordsToScreen(point.x, point.y, point.z)
                    if prev ~= nil then
                        draw_list:PathLineTo(imgui.ImVec2(prev.x, prev.y))
                        draw_list:PathLineTo(imgui.ImVec2(point.x, point.y))
                        draw_list:PathStroke(color, false, 1)
                    end
                    prev = point
                end
            end
            return -- we matched with a precomputed sphere, drew it, so now return
        end
    end

   
    local vert = { vertices = {}, radius } -- add a new vert to pre-compute
    local lati = 16
    local loni = 24
    for lat = 0, lati do
        local a1 = math.pi * (lat + 1) / (lati + 1)
        local sin1 = math.sin(a1)
        local cos1 = math.cos(a1)

        for lon = 0, loni do
            local a2 = (2 * math.pi) * (lon == loni and 0 or lon) / loni
            local sin2 = math.sin(a2)
            local cos2 = math.cos(a2)

            local point = Vector3D(sin1 * cos2, cos1, sin1 * sin2) * radius
            table.insert(vert.vertices, point)
        end
    end
    vert.radius = radius
    table.insert(PreComputedSpheres, vert)
end

imgui.OnFrame(function() return true end, function()
    local dl = imgui.GetBackgroundDrawList()
    for i = 0, 100, 10 do
        DrawPointSphere(dl, Vector3D(i, i, 10), i / 15, 0xFFFFFFFF)
    end
end).HideCursor = true
1703509168992.png


UPD: чутка подправил моменты, херящие отрисовку множества сфер разного радиуса
1703510444069.png
 
Последнее редактирование:

chromiusj

Kommando-Leiteinheit Bioresonanztechnik-Replika
Модератор
5,514
3,842
Хз, заняло меньше 10 минут.
Lua:
local imgui = require 'mimgui'
local Vector3D = require 'vector3d'

function table.copy(t)
    local t2 = {}
    for k,v in pairs(t) do
        t2[k] = v
    end
    return t2
end

local SphereVertices = {
    vertices = {},
    radius, itterations
}

local PreComputedSpheres = {}

---@param location > Vector3D
---@param radius   > number ( float )
---@param color    > number ( hex )
function DrawPointSphere(draw_list, location, radius, color)
    for _, p in ipairs(PreComputedSpheres) do
        if p.radius == radius then
            local prev
            for i = 1, p.itterations do -- ?? may be not +1
                local point = location
                point = point + p.vertices[i]
                if isPointOnScreen(point.x, point.y, point.z, 0.1) then
                    point.x, point.y = convert3DCoordsToScreen(point.x, point.y, point.z)
                    if i ~= 1 and prev ~= nil then
                        draw_list:PathLineTo(imgui.ImVec2(prev.x, prev.y))
                        draw_list:PathLineTo(imgui.ImVec2(point.x, point.y))
                        draw_list:PathStroke(color, false, 1)
                    end
                    prev = point
                end
            end
            return -- we matched with a precomputed sphere, drew it, so now return
        end
    end

    local vert = table.copy(SphereVertices) -- add a new vert to pre-compute
    vert.itterations = 0
    local lati = 16
    local loni = 24
    for lat = 0, lati do
        local a1 = math.pi * (lat + 1) / (lati + 1)
        local sin1 = math.sin(a1)
        local cos1 = math.cos(a1)

        for lon = 0, loni do
            local a2 = (2 * math.pi) * (lon == loni and 0 or lon) / loni
            local sin2 = math.sin(a2)
            local cos2 = math.cos(a2)

            local point = Vector3D(sin1 * cos2, cos1, sin1 * sin2) * radius

            vert.radius = radius
            vert.itterations = vert.itterations + 1
            table.insert(vert.vertices, point)
        end
    end
    table.insert(PreComputedSpheres, vert)
end

imgui.OnFrame(function() return true end, function()
    DrawPointSphere(imgui.GetBackgroundDrawList(), Vector3D(10, 10, 7), 10, 0xFFFFFFFF)
end).HideCursor = true
Посмотреть вложение 225947
да вы магистр ффи,векторов и мимгуи,как я вижу,спасибо ещё раз!
 
  • Нравится
Реакции: Andrinall