diff --git a/resource/zone creator/client.lua b/resource/zone creator/client.lua new file mode 100644 index 000000000..cf69ad868 --- /dev/null +++ b/resource/zone creator/client.lua @@ -0,0 +1,242 @@ +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 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] = '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] = '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 startCreator(arg) + creatorActive = 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() +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 + startCreator(args[1]) + end + end +end) + +local function closeCreator(cancel) + if not cancel then + if zoneType == 'poly' then + points[#points + 1] = vec(xCoord, yCoord) + end + + lib.inputDialog(('Name your %s Zone'):format(firstToUpper(zoneType)), {'Name'}) + + TriggerServerEvent('ox_lib:saveZone', { + zoneType = zoneType, + name = name, + xCoord = xCoord, + yCoord = yCoord, + zCoord = zCoord, + heading = heading, + height = height, + width = width, + length = length, + points = points + }) + end + + creatorActive = false + controlsActive = false + lib.hideTextUI(true) + zoneType = nil +end + +local function drawLines() + local thickness = vec(0, 0, height / 2) + 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]) + 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 +end + +CreateThread(function() + while true do + Wait(0) + if creatorActive then + if IsDisabledControlJustPressed(0, 73) then -- x + if creatorActive then + controlsActive = not controlsActive + end + end + + if zoneType == 'poly' then + DrawLine(xCoord, yCoord, zCoord + height / 2, xCoord, yCoord, zCoord - height / 2, 255, 42, 24, 225) + + drawLines() + elseif zoneType == 'box' then + local offset = math.rad(heading + 45) + local sinT = math.sin(offset) + local cosT = math.cos(offset) + local center = vec(xCoord, yCoord) + points = { + center + vec(width * sinT, length * cosT), + center + vec(-width * cosT, length * sinT), + center + vec(-width * sinT, -length * cosT), + center + vec(width * cosT, -length * sinT), + } + + 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, false, true, false, false, false) + end + end + + if controlsActive then + DisableAllControlActions() + EnableControlAction(0, 1, true) + EnableControlAction(0, 2, true) + EnableControlAction(0, 245, true) -- t + local change = false + + if IsDisabledControlJustPressed(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 IsDisabledControlJustPressed(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 IsDisabledControlJustPressed(0, 32) then -- w + change = true + yCoord += steps[1][step] + elseif IsDisabledControlJustPressed(0, 33) then -- s + change = true + yCoord -= steps[1][step] + elseif IsDisabledControlJustPressed(0, 35) then -- d + change = true + xCoord += steps[1][step] + elseif IsDisabledControlJustPressed(0, 34) then -- a + change = true + xCoord -= steps[1][step] + elseif IsDisabledControlJustPressed(0, 45) then -- r + change = true + zCoord += steps[1][step] + elseif IsDisabledControlJustPressed(0, 23) then -- f + change = true + zCoord -= steps[1][step] + elseif IsDisabledControlJustPressed(0, 38) then -- e + change = true + heading += steps[2][step] + if heading >= 360 then + heading -= 360 + end + elseif IsDisabledControlJustPressed(0, 44) then -- q + change = true + heading -= steps[2][step] + if heading < 0 then + heading += 360 + end + elseif IsDisabledControlJustPressed(0, 22) then -- space + change = true + if zoneType == 'poly' then + points[#points + 1] = vec(xCoord, yCoord) + end + + local coords = GetEntityCoords(cache.ped) + xCoord = round(coords.x) + yCoord = round(coords.y) + zCoord = round(coords.z) + elseif IsDisabledControlJustPressed(0, 201) then -- enter + closeCreator() + elseif IsDisabledControlJustPressed(0, 200) then -- esc + closeCreator(true) + end + + if change then + updateText() + end + end + end +end) diff --git a/resource/zone creator/server.lua b/resource/zone creator/server.lua new file mode 100644 index 000000000..8b910bfc0 --- /dev/null +++ b/resource/zone creator/server.lua @@ -0,0 +1,116 @@ +local printFunction = false + +--[[ + -- printFunction = true +local poly = lib.zones.poly({ + name = poly, + points = { + vec(447.9, -998.8, 25.8), + vec(450.3, -998.2, 25.8), + vec(449.9, -995.5, 25.8), + vec(447.2, -995.6, 25.8), + vec(446.3, -997.9, 25.8), + }, + thickness = 2, +}) + -- printFunction = false +{ + name = poly, + points = { + vec(447.9, -998.8, 25.8), + vec(450.3, -998.2, 25.8), + vec(449.9, -995.5, 25.8), + vec(447.2, -995.6, 25.8), + vec(446.3, -997.9, 25.8), + }, + thickness = 2, +}, +]] + +local parse = { + poly = function(data) + local points = {} + for i = 1, #data.points do + points[#points + 1] = ('\t\tvec(%s, %s, %s),\n'):format((data.points[i].x), (data.points[i].y), data.zCoord) + end + + local pattern + if printFunction then + pattern = { + 'local poly = lib.zones.poly({\n', + ('\tname = %s,\n'):format(data.name or 'none'), + '\tpoints = {\n', + ('%s\t},\n'):format(table.concat(points)), + ('\tthickness = %s,\n'):format(data.height), + '})\n', + } + else + pattern = { + '{\n', + ('\tname = %s,\n'):format(data.name or 'none'), + '\tpoints = {\n', + ('%s\t},\n'):format(table.concat(points)), + ('\tthickness = %s,\n'):format(data.height), + '},\n' + } + end + + return table.concat(pattern) + end, + box = function(data) + local pattern + if printFunction then + pattern = { + 'local box = lib.zones.box({\n', + ('\tname = %s,\n'):format(data.name or 'none'), + ('\tcoords = vec(%s, %s, %s),\n'):format(data.xCoord, data.yCoord, data.zCoord), + ('\tsize = vec(%s, %s, %s),\n'):format(data.width, data.length, data.height), + ('\trotation = %s,\n'):format(data.heading), + '})\n', + } + else + pattern = { + '{\n', + ('\tname = %s,\n'):format(data.name or 'none'), + ('\tcoords = vec(%s, %s, %s),\n'):format(data.xCoord, data.yCoord, data.zCoord), + ('\tsize = vec(%s, %s, %s),\n'):format(data.width, data.length, data.height), + ('\trotation = %s,\n'):format(data.heading), + '}\n', + } + end + + return table.concat(pattern) + end, + sphere = function(data) + local pattern + if printFunction then + pattern = { + 'local sphere = lib.zones.sphere({\n', + ('\tname = %s,\n'):format(data.name or 'none'), + ('\tcoords = vec(%s, %s, %s),\n'):format(data.xCoord, data.yCoord, data.zCoord), + ('\tradius = %s,\n'):format(data.heading), + '})\n', + } + else + pattern = { + '{\n', + ('\tname = %s,\n'):format(data.name or 'none'), + ('\tcoords = vec(%s, %s, %s),\n'):format(data.xCoord, data.yCoord, data.zCoord), + ('\tradius = %s,\n'):format(data.heading), + '}\n', + } + end + + return table.concat(pattern) + end, +} + +local path = GetResourcePath(GetCurrentResourceName()) .. '/resource/zone creator/created_zones.lua' +path = path:gsub('//', '/') +RegisterServerEvent('ox_lib:saveZone', function(data) + local file = io.open(path, 'a') + io.output(file) + local output = parse[data.zoneType](data) + io.write(output) + io.close(file) +end)