mirror of
https://github.com/CommunityOx/ox_lib.git
synced 2026-08-17 06:56:03 +01:00
add option to display zones as a wireframe, with solid walls, axis helper or both solid walls and axis helper
307 lines
12 KiB
Lua
307 lines
12 KiB
Lua
local creatorActive = false
|
|
local controlsActive = false
|
|
local zoneType, step, xCoord, yCoord, zCoord, heading, height, width, length
|
|
local steps = {{0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10, 25, 50, 100}, {0.25, 0.5, 1, 2.5, 5, 15, 30, 45, 60, 90, 180}}
|
|
local points = {}
|
|
local format = 'array'
|
|
local displayModes = {'basic', 'walls', 'axes', 'both'}
|
|
local displayMode = 1
|
|
|
|
local function firstToUpper(str)
|
|
return (str:gsub("^%l", string.upper))
|
|
end
|
|
|
|
local function updateText()
|
|
local text = {
|
|
('------ Creating %s Zone ------ \n'):format(firstToUpper(zoneType)),
|
|
('Step size [Scroll]: %sm/%s° \n'):format(steps[1][step], steps[2][step]),
|
|
('X coord [A/D]: %s \n'):format(xCoord),
|
|
('Y coord [W/S]: %s \n'):format(yCoord),
|
|
('Z coord [R/F]: %s \n'):format(zCoord),
|
|
}
|
|
|
|
if zoneType == 'poly' then
|
|
text[#text + 1] = ('Height [Shift + Scroll]: %s \n'):format(height)
|
|
text[#text + 1] = ('Cycle display mode [G]: %s \n'):format(firstToUpper(displayModes[displayMode]))
|
|
text[#text + 1] = 'Create new point - [Space] \n'
|
|
elseif zoneType == 'box' then
|
|
text[#text + 1] = ('Heading [Q/E]: %s° \n'):format(heading)
|
|
text[#text + 1] = ('Height [Shift + Scroll]: %s \n'):format(height)
|
|
text[#text + 1] = ('Width [Ctrl + Scroll]: %s \n'):format(width)
|
|
text[#text + 1] = ('Length [Alt + Scroll]: %s \n'):format(length)
|
|
text[#text + 1] = ('Cycle display mode [G]: %s \n'):format(firstToUpper(displayModes[displayMode]))
|
|
text[#text + 1] = 'Recenter - [Space] \n'
|
|
elseif zoneType == 'sphere' then
|
|
text[#text + 1] = ('Size [Shift + Scroll]: %s \n'):format(height)
|
|
text[#text + 1] = 'Recenter - [Space] \n'
|
|
end
|
|
|
|
text[#text + 1] = 'Toggle controls - [X] \n'
|
|
text[#text + 1] = 'Save - [Enter] \n'
|
|
text[#text + 1] = 'Cancel - [Esc]'
|
|
|
|
lib.showTextUI(table.concat(text))
|
|
end
|
|
|
|
local function round(number)
|
|
return number >= 0 and math.floor(number + 0.5) or math.ceil(number - 0.5)
|
|
end
|
|
|
|
local function closeCreator(cancel)
|
|
if not cancel then
|
|
if zoneType == 'poly' then
|
|
points[#points + 1] = vec(xCoord, yCoord)
|
|
end
|
|
|
|
local input = lib.inputDialog(('Name your %s Zone'):format(firstToUpper(zoneType)), {
|
|
{ type = 'input', label = 'Name', placeholder = 'none' },
|
|
{ type = 'select', label = 'Format', default = format, options = {
|
|
{ value = 'function', label = 'Function' },
|
|
{ value = 'array', label = 'Array' },
|
|
{ value = 'target', label = 'Target'},
|
|
}}
|
|
}) or {}
|
|
|
|
format = input[2]
|
|
|
|
TriggerServerEvent('ox_lib:saveZone', {
|
|
zoneType = zoneType,
|
|
name = input[1] or 'none',
|
|
format = format,
|
|
xCoord = xCoord,
|
|
yCoord = yCoord,
|
|
zCoord = zCoord,
|
|
heading = heading,
|
|
height = height,
|
|
width = width,
|
|
length = length,
|
|
points = points
|
|
})
|
|
end
|
|
|
|
creatorActive = false
|
|
controlsActive = false
|
|
lib.hideTextUI()
|
|
zoneType = nil
|
|
end
|
|
|
|
local function drawRectangle(rec)
|
|
DrawPoly(rec[1].x, rec[1].y, rec[1].z, rec[2].x, rec[2].y, rec[2].z, rec[3].x, rec[3].y, rec[3].z, 255, 42, 24, 100)
|
|
DrawPoly(rec[2].x, rec[2].y, rec[2].z, rec[1].x, rec[1].y, rec[1].z, rec[3].x, rec[3].y, rec[3].z, 255, 42, 24, 100)
|
|
DrawPoly(rec[1].x, rec[1].y, rec[1].z, rec[4].x, rec[4].y, rec[4].z, rec[3].x, rec[3].y, rec[3].z, 255, 42, 24, 100)
|
|
DrawPoly(rec[4].x, rec[4].y, rec[4].z, rec[1].x, rec[1].y, rec[1].z, rec[3].x, rec[3].y, rec[3].z, 255, 42, 24, 100)
|
|
end
|
|
|
|
local function drawLines()
|
|
local thickness = vec(0, 0, height / 2)
|
|
local activeA, activeB = vec(xCoord, yCoord, zCoord) + thickness, vec(xCoord, yCoord, zCoord) - thickness
|
|
|
|
if zoneType == 'poly' then
|
|
DrawLine(activeA.x, activeA.y, activeA.z, activeB.x, activeB.y, activeB.z, 255, 42, 24, 225)
|
|
end
|
|
|
|
for i = 1, #points do
|
|
points[i] = vec(points[i].x, points[i].y, zCoord)
|
|
local a = points[i] + thickness
|
|
local b = points[i] - thickness
|
|
local c = (points[i + 1] and vec(points[i + 1].x, points[i + 1].y, zCoord) or points[1]) + thickness
|
|
local d = (points[i + 1] and vec(points[i + 1].x, points[i + 1].y, zCoord) or points[1]) - thickness
|
|
local e = points[i]
|
|
local f = (points[i + 1] and vec(points[i + 1].x, points[i + 1].y, zCoord) or points[1])
|
|
|
|
if i == #points and zoneType == 'poly' then
|
|
DrawLine(a.x, a.y, a.z, b.x, b.y, b.z, 255, 42, 24, 225)
|
|
DrawLine(activeA.x, activeA.y, activeA.z, c.x, c.y, c.z, 255, 42, 24, 225)
|
|
DrawLine(activeB.x, activeB.y, activeB.z, d.x, d.y, d.z, 255, 42, 24, 225)
|
|
DrawLine(a.x, a.y, a.z, activeA.x, activeA.y, activeA.z, 255, 42, 24, 225)
|
|
DrawLine(b.x, b.y, b.z, activeB.x, activeB.y, activeB.z, 255, 42, 24, 225)
|
|
DrawLine(xCoord, yCoord, zCoord, f.x, f.y, f.z, 255, 42, 24, 225)
|
|
DrawLine(e.x, e.y, e.z, xCoord, yCoord, zCoord, 255, 42, 24, 225)
|
|
else
|
|
DrawLine(a.x, a.y, a.z, b.x, b.y, b.z, 255, 42, 24, 225)
|
|
DrawLine(a.x, a.y, a.z, c.x, c.y, c.z, 255, 42, 24, 225)
|
|
DrawLine(b.x, b.y, b.z, d.x, d.y, d.z, 255, 42, 24, 225)
|
|
DrawLine(e.x, e.y, e.z, f.x, f.y, f.z, 255, 42, 24, 225)
|
|
end
|
|
|
|
if displayMode == 2 or displayMode == 4 then
|
|
if i == #points and zoneType == 'poly' then
|
|
drawRectangle({a, b, activeB, activeA})
|
|
drawRectangle({activeA, activeB, d, c})
|
|
else
|
|
drawRectangle({a, b, d, c})
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local function startCreator(arg)
|
|
creatorActive = true
|
|
controlsActive = true
|
|
zoneType = arg
|
|
|
|
step = 5
|
|
local coords = GetEntityCoords(cache.ped)
|
|
xCoord = round(coords.x) + 0.0
|
|
yCoord = round(coords.y) + 0.0
|
|
zCoord = round(coords.z) + 0.0
|
|
heading = 0.0
|
|
height = 4.0
|
|
width = 4.0
|
|
length = 4.0
|
|
points = {}
|
|
|
|
updateText()
|
|
|
|
while creatorActive do
|
|
Wait(0)
|
|
|
|
if IsDisabledControlJustReleased(0, 73) then -- x
|
|
if creatorActive then
|
|
controlsActive = not controlsActive
|
|
end
|
|
end
|
|
|
|
if displayMode == 3 or displayMode == 4 then
|
|
DrawLine(xCoord, yCoord, zCoord, xCoord + 2, yCoord, zCoord, 0, 0, 255, 225)
|
|
DrawLine(xCoord, yCoord, zCoord, xCoord, yCoord + 2, zCoord, 0, 0, 255, 225)
|
|
DrawLine(xCoord, yCoord, zCoord, xCoord, yCoord, zCoord + 2, 0, 0, 255, 225)
|
|
end
|
|
|
|
if zoneType == 'poly' then
|
|
drawLines()
|
|
elseif zoneType == 'box' then
|
|
local rad = math.rad(heading)
|
|
local sinH = math.sin(rad)
|
|
local cosH = math.cos(rad)
|
|
local center = vec(xCoord, yCoord)
|
|
---@type vector2[]
|
|
points = {
|
|
center + vec((width * cosH + length * sinH), (length * cosH - width * sinH)),
|
|
center + vec(-(width * cosH - length * sinH), (length * cosH + width * sinH)),
|
|
center + vec(-(width * cosH + length * sinH), -(length * cosH - width * sinH)),
|
|
center + vec((width * cosH - length * sinH), -(length * cosH + width * sinH)),
|
|
}
|
|
|
|
drawLines()
|
|
elseif zoneType == 'sphere' then
|
|
DrawMarker(28, xCoord, yCoord, zCoord, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, height, height, height, 255, 42, 24, 100, false, false, 0, true, false, false, false)
|
|
end
|
|
|
|
if controlsActive then
|
|
DisableAllControlActions()
|
|
EnableControlAction(0, 1, true)
|
|
EnableControlAction(0, 2, true)
|
|
EnableControlAction(0, 245, true) -- t
|
|
local change = false
|
|
|
|
if IsDisabledControlJustReleased(0, 17) then -- scroll up
|
|
if IsDisabledControlPressed(0, 21) then -- shift held down
|
|
change = true
|
|
height += steps[1][step]
|
|
elseif IsDisabledControlPressed(0, 36) then -- ctrl held down
|
|
change = true
|
|
width += steps[1][step]
|
|
elseif IsDisabledControlPressed(0, 19) then -- alt held down
|
|
change = true
|
|
length += steps[1][step]
|
|
elseif step < 11 then
|
|
change = true
|
|
step += 1
|
|
end
|
|
elseif IsDisabledControlJustReleased(0, 16) then -- scroll down
|
|
if IsDisabledControlPressed(0, 21) then -- shift held down
|
|
change = true
|
|
if height - steps[1][step] > 0 then
|
|
height -= steps[1][step]
|
|
end
|
|
elseif IsDisabledControlPressed(0, 36) then -- ctrl held down
|
|
change = true
|
|
if width - steps[1][step] > 0 then
|
|
width -= steps[1][step]
|
|
end
|
|
elseif IsDisabledControlPressed(0, 19) then -- alt held down
|
|
change = true
|
|
if length - steps[1][step] > 0 then
|
|
length -= steps[1][step]
|
|
end
|
|
elseif step > 1 then
|
|
change = true
|
|
step -= 1
|
|
end
|
|
elseif IsDisabledControlJustReleased(0, 32) then -- w
|
|
change = true
|
|
yCoord += steps[1][step]
|
|
elseif IsDisabledControlJustReleased(0, 33) then -- s
|
|
change = true
|
|
yCoord -= steps[1][step]
|
|
elseif IsDisabledControlJustReleased(0, 35) then -- d
|
|
change = true
|
|
xCoord += steps[1][step]
|
|
elseif IsDisabledControlJustReleased(0, 34) then -- a
|
|
change = true
|
|
xCoord -= steps[1][step]
|
|
elseif IsDisabledControlJustReleased(0, 45) then -- r
|
|
change = true
|
|
zCoord += steps[1][step]
|
|
elseif IsDisabledControlJustReleased(0, 23) then -- f
|
|
change = true
|
|
zCoord -= steps[1][step]
|
|
elseif IsDisabledControlJustReleased(0, 38) then -- e
|
|
change = true
|
|
heading += steps[2][step]
|
|
if heading >= 360 then
|
|
heading -= 360
|
|
end
|
|
elseif IsDisabledControlJustReleased(0, 44) then -- q
|
|
change = true
|
|
heading -= steps[2][step]
|
|
if heading < 0 then
|
|
heading += 360
|
|
end
|
|
elseif IsDisabledControlJustReleased(0, 47) then -- g
|
|
change = true
|
|
if displayMode == #displayModes then
|
|
displayMode = 1
|
|
else
|
|
displayMode += 1
|
|
end
|
|
elseif IsDisabledControlJustReleased(0, 22) then -- space
|
|
change = true
|
|
if zoneType == 'poly' then
|
|
points[#points + 1] = vec2(xCoord, yCoord)
|
|
end
|
|
|
|
coords = GetEntityCoords(cache.ped)
|
|
xCoord = round(coords.x)
|
|
yCoord = round(coords.y)
|
|
elseif IsDisabledControlJustReleased(0, 201) then -- enter
|
|
closeCreator()
|
|
elseif IsDisabledControlJustReleased(0, 200) then -- esc
|
|
SetPauseMenuActive(false)
|
|
closeCreator(true)
|
|
end
|
|
|
|
if change then
|
|
updateText()
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
RegisterCommand('zone', function(source, args, rawCommand)
|
|
if args[1] == 'poly' or args[1] == 'box' or args[1] == 'sphere' then
|
|
if creatorActive then
|
|
lib.notify({title = 'Already creating a zone', type = 'error'})
|
|
else
|
|
CreateThread(function()
|
|
startCreator(args[1])
|
|
end)
|
|
end
|
|
end
|
|
end, true)
|
|
|
|
TriggerEvent('chat:addSuggestion', '/zone', 'Starts creation of the specified zone', {
|
|
{ name = 'zoneType', help = 'poly, box, sphere' },
|
|
})
|