Files
ox_lib/resource/zoneCreator/client.lua
2022-10-01 15:24:51 +10:00

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)) / 2,
center + vec(-(width * cosH - length * sinH), (length * cosH + width * sinH)) / 2,
center + vec(-(width * cosH + length * sinH), -(length * cosH - width * sinH)) / 2,
center + vec((width * cosH - length * sinH), -(length * cosH + width * sinH)) / 2,
}
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 < 0 then
heading += 360
end
elseif IsDisabledControlJustReleased(0, 44) then -- q
change = true
heading += steps[2][step]
if heading >= 360 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' },
})