From 3777b9bec5e261d8aa9574a9e86e2b5220293772 Mon Sep 17 00:00:00 2001 From: Infernalz <51412133+Infernalz92@users.noreply.github.com> Date: Sun, 1 Oct 2023 00:57:51 +0200 Subject: [PATCH 1/7] Create CircleZone.lua Added missing file --- creation/client/CircleZone.lua | 51 ++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 creation/client/CircleZone.lua diff --git a/creation/client/CircleZone.lua b/creation/client/CircleZone.lua new file mode 100644 index 0000000..e063ff1 --- /dev/null +++ b/creation/client/CircleZone.lua @@ -0,0 +1,51 @@ +local function handleInput(radius, center, useZ) + local delta = 0.05 + -- BlockWeaponWheelThisFrame() + if IsDisabledControlPressed(2, Keys["CTRL"]) then -- ctrl held down + delta = 0.01 + end + if IsDisabledControlJustPressed(2, Keys["MWDOWN"]) then + if IsDisabledControlPressed(2, Keys["LALT"]) then -- alt held down + return radius, vector3(center.x, center.y, center.z - delta), useZ + end + return math.max(0.0, radius - delta), center, useZ + end + if IsDisabledControlJustPressed(2, Keys["MWUP"]) then + if IsDisabledControlPressed(2, Keys["LALT"]) then -- alt held down + return radius, vector3(center.x, center.y, center.z + delta), useZ + end + return radius + delta, center, useZ + end + + if IsControlJustPressed(2, Keys["Z"]) then -- Z pressed + return radius, center, not useZ + end + + local rot = GetGameplayCamRot(2) + center = handleArrowInput(center, rot.z) + + return radius, center, useZ +end + +function circleStart(name, radius, useZ) + local center = GetEntityCoords(PlayerPedId()) + useZ = useZ or false + createdZone = CircleZone:Create(center, radius, {name = tostring(name), useZ = useZ}) + Citizen.CreateThread(function() + LocalPlayer.state:set("PolyZoneCreation", true, true) + while createdZone do + DisableControls() + radius, center, useZ = handleInput(radius, center, useZ) + createdZone:setRadius(radius) + createdZone:setCenter(center) + createdZone.useZ = useZ + Wait(0) + end + LocalPlayer.state:set("PolyZoneCreation", false, true) + end) +end + +function circleFinish() + TriggerServerEvent("polyzone:printCircle", + {name=createdZone.name, center=createdZone.center, radius=createdZone.radius, useZ=createdZone.useZ}) +end From ce9153e9422ce135c7e9f407863842500238e4a4 Mon Sep 17 00:00:00 2001 From: Infernalz <51412133+Infernalz92@users.noreply.github.com> Date: Sun, 1 Oct 2023 00:59:03 +0200 Subject: [PATCH 2/7] Create commands.lua Added missing file --- creation/client/commands.lua | 68 ++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 creation/client/commands.lua diff --git a/creation/client/commands.lua b/creation/client/commands.lua new file mode 100644 index 0000000..d4d878d --- /dev/null +++ b/creation/client/commands.lua @@ -0,0 +1,68 @@ +RegisterCommand("pzcreate", function(src, args) + local zoneType = args[1] + if zoneType == nil then + TriggerEvent('chat:addMessage', { + color = { 255, 0, 0}, + multiline = true, + args = {"Me", "Please add zone type to create (poly, circle, box)!"} + }) + return + end + if zoneType ~= 'poly' and zoneType ~= 'circle' and zoneType ~= 'box' then + TriggerEvent('chat:addMessage', { + color = { 255, 0, 0}, + multiline = true, + args = {"Me", "Zone type must be one of: poly, circle, box"} + }) + return + end + local name = nil + if #args >= 2 then name = args[2] + else name = GetUserInput("Enter name of zone:") end + if name == nil or name == "" then + TriggerEvent('chat:addMessage', { + color = { 255, 0, 0}, + multiline = true, + args = {"Me", "Please add a name!"} + }) + return + end + TriggerEvent("polyzone:pzcreate", zoneType, name, args) +end) + +RegisterCommand("pzadd", function(src, args) + TriggerEvent("polyzone:pzadd") +end) + +RegisterCommand("pzundo", function(src, args) + TriggerEvent("polyzone:pzundo") +end) + +RegisterCommand("pzfinish", function(src, args) + TriggerEvent("polyzone:pzfinish") +end) + +RegisterCommand("pzlast", function(src, args) + TriggerEvent("polyzone:pzlast") +end) + +RegisterCommand("pzcancel", function(src, args) + TriggerEvent("polyzone:pzcancel") +end) + +RegisterCommand("pzcomboinfo", function (src, args) + TriggerEvent("polyzone:pzcomboinfo") +end) + +Citizen.CreateThread(function() + TriggerEvent('chat:addSuggestion', '/pzcreate', 'Starts creation of a zone for PolyZone of one of the available types: circle, box, poly', { + {name="zoneType", help="Zone Type (required)"}, + }) + + TriggerEvent('chat:addSuggestion', '/pzadd', 'Adds point to zone.', {}) + TriggerEvent('chat:addSuggestion', '/pzundo', 'Undoes the last point added.', {}) + TriggerEvent('chat:addSuggestion', '/pzfinish', 'Finishes and prints zone.', {}) + TriggerEvent('chat:addSuggestion', '/pzlast', 'Starts creation of the last zone you finished (only works on BoxZone and CircleZone)', {}) + TriggerEvent('chat:addSuggestion', '/pzcancel', 'Cancel zone creation.', {}) + TriggerEvent('chat:addSuggestion', '/pzcomboinfo', 'Prints some useful info for all created ComboZones', {}) +end) From f6103dcbbb4fa05d49bc0621f14d20e7542f09f7 Mon Sep 17 00:00:00 2001 From: Infernalz <51412133+Infernalz92@users.noreply.github.com> Date: Sun, 1 Oct 2023 00:59:30 +0200 Subject: [PATCH 3/7] Create creation.lua Added missing file --- creation/client/creation.lua | 157 +++++++++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 creation/client/creation.lua diff --git a/creation/client/creation.lua b/creation/client/creation.lua new file mode 100644 index 0000000..af40c10 --- /dev/null +++ b/creation/client/creation.lua @@ -0,0 +1,157 @@ +lastCreatedZoneType = nil +lastCreatedZone = nil +createdZoneType = nil +createdZone = nil +drawZone = false + +RegisterNetEvent("polyzone:pzcreate") +AddEventHandler("polyzone:pzcreate", function(zoneType, name, args) + if createdZone ~= nil then + TriggerEvent('chat:addMessage', { + color = { 255, 0, 0}, + multiline = true, + args = {"Me", "A shape is already being created!"} + }) + return + end + + if zoneType == 'poly' then + polyStart(name) + elseif zoneType == "circle" then + local radius = nil + if #args >= 3 then radius = tonumber(args[3]) + else radius = tonumber(GetUserInput("Enter radius:")) end + if radius == nil then + TriggerEvent('chat:addMessage', { + color = { 255, 0, 0}, + multiline = true, + args = {"Me", "CircleZone requires a radius (must be a number)!"} + }) + return + end + circleStart(name, radius) + elseif zoneType == "box" then + local length = nil + if #args >= 3 then length = tonumber(args[3]) + else length = tonumber(GetUserInput("Enter length:")) end + if length == nil or length < 0.0 then + TriggerEvent('chat:addMessage', { + color = { 255, 0, 0}, + multiline = true, + args = {"Me", "BoxZone requires a length (must be a positive number)!"} + }) + return + end + local width = nil + if #args >= 4 then width = tonumber(args[4]) + else width = tonumber(GetUserInput("Enter width:")) end + if width == nil or width < 0.0 then + TriggerEvent('chat:addMessage', { + color = { 255, 0, 0}, + multiline = true, + args = {"Me", "BoxZone requires a width (must be a positive number)!"} + }) + return + end + boxStart(name, 0, length, width) + else + return + end + createdZoneType = zoneType + drawZone = true + drawThread() +end) + +RegisterNetEvent("polyzone:pzfinish") +AddEventHandler("polyzone:pzfinish", function() + if createdZone == nil then + return + end + + if createdZoneType == 'poly' then + polyFinish() + elseif createdZoneType == "circle" then + circleFinish() + elseif createdZoneType == "box" then + boxFinish() + end + + TriggerEvent('chat:addMessage', { + color = { 0, 255, 0}, + multiline = true, + args = {"Me", "Check your server root folder for polyzone_created_zones.txt to get the zone!"} + }) + + lastCreatedZoneType = createdZoneType + lastCreatedZone = createdZone + + drawZone = false + createdZone = nil + createdZoneType = nil +end) + +RegisterNetEvent("polyzone:pzlast") +AddEventHandler("polyzone:pzlast", function() + if createdZone ~= nil or lastCreatedZone == nil then + return + end + if lastCreatedZoneType == 'poly' then + TriggerEvent('chat:addMessage', { + color = { 0, 255, 0}, + multiline = true, + args = {"Me", "The command pzlast only supports BoxZone and CircleZone for now"} + }) + + end + + local name = GetUserInput("Enter name (or leave empty to reuse last zone's name):") + if name == nil then + return + elseif name == "" then + name = lastCreatedZone.name + end + createdZoneType = lastCreatedZoneType + if createdZoneType == 'box' then + local minHeight, maxHeight + if lastCreatedZone.minZ then + minHeight = lastCreatedZone.center.z - lastCreatedZone.minZ + end + if lastCreatedZone.maxZ then + maxHeight = lastCreatedZone.maxZ - lastCreatedZone.center.z + end + boxStart(name, lastCreatedZone.offsetRot, lastCreatedZone.length, lastCreatedZone.width, minHeight, maxHeight) + elseif createdZoneType == 'circle' then + circleStart(name, lastCreatedZone.radius, lastCreatedZone.useZ) + end + drawZone = true + drawThread() +end) + +RegisterNetEvent("polyzone:pzcancel") +AddEventHandler("polyzone:pzcancel", function() + if createdZone == nil then + return + end + + TriggerEvent('chat:addMessage', { + color = {255, 0, 0}, + multiline = true, + args = {"Me", "Zone creation canceled!"} + }) + + drawZone = false + createdZone = nil + createdZoneType = nil +end) + +-- Drawing +function drawThread() + Citizen.CreateThread(function() + while drawZone do + if createdZone then + createdZone:draw() + end + Wait(0) + end + end) +end From 935ba5ab77869d20ac6d90ab0a22bd7326541388 Mon Sep 17 00:00:00 2001 From: Infernalz <51412133+Infernalz92@users.noreply.github.com> Date: Sun, 1 Oct 2023 01:00:35 +0200 Subject: [PATCH 4/7] Create PolyZone.lua Added missing file --- creation/client/PolyZone.lua | 62 ++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 creation/client/PolyZone.lua diff --git a/creation/client/PolyZone.lua b/creation/client/PolyZone.lua new file mode 100644 index 0000000..911ad03 --- /dev/null +++ b/creation/client/PolyZone.lua @@ -0,0 +1,62 @@ +local minZ, maxZ = nil, nil + +local function handleInput(center) + local rot = GetGameplayCamRot(2) + center = handleArrowInput(center, rot.z) + return center +end + +function polyStart(name) + local coords = GetEntityCoords(PlayerPedId()) + createdZone = PolyZone:Create({vector2(coords.x, coords.y)}, {name = tostring(name), useGrid=false}) + Citizen.CreateThread(function() + LocalPlayer.state:set("PolyZoneCreation", true, true) + while createdZone do + -- Have to convert the point to a vector3 prior to calling handleInput, + -- then convert it back to vector2 afterwards + lastPoint = createdZone.points[#createdZone.points] + lastPoint = vector3(lastPoint.x, lastPoint.y, 0.0) + lastPoint = handleInput(lastPoint) + createdZone.points[#createdZone.points] = lastPoint.xy + Wait(0) + end + LocalPlayer.state:set("PolyZoneCreation", false, true) + end) + minZ, maxZ = coords.z, coords.z +end + +function polyFinish() + TriggerServerEvent("polyzone:printPoly", + {name=createdZone.name, points=createdZone.points, minZ=minZ, maxZ=maxZ}) +end + +RegisterNetEvent("polyzone:pzadd") +AddEventHandler("polyzone:pzadd", function() + if createdZone == nil or createdZoneType ~= 'poly' then + return + end + + local coords = GetEntityCoords(PlayerPedId()) + + if (coords.z > maxZ) then + maxZ = coords.z + end + + if (coords.z < minZ) then + minZ = coords.z + end + + createdZone.points[#createdZone.points + 1] = vector2(coords.x, coords.y) +end) + +RegisterNetEvent("polyzone:pzundo") +AddEventHandler("polyzone:pzundo", function() + if createdZone == nil or createdZoneType ~= 'poly' then + return + end + + createdZone.points[#createdZone.points] = nil + if #createdZone.points == 0 then + TriggerEvent("polyzone:pzcancel") + end +end) From 2bec2376861774352a05868f795dfca96ad80c18 Mon Sep 17 00:00:00 2001 From: Infernalz <51412133+Infernalz92@users.noreply.github.com> Date: Sun, 1 Oct 2023 01:01:15 +0200 Subject: [PATCH 5/7] Create utils.lua Added missing file --- creation/client/utils.lua | 75 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 creation/client/utils.lua diff --git a/creation/client/utils.lua b/creation/client/utils.lua new file mode 100644 index 0000000..5231f79 --- /dev/null +++ b/creation/client/utils.lua @@ -0,0 +1,75 @@ +-- GetUserInput function inspired by vMenu (https://github.com/TomGrobbe/vMenu/blob/master/vMenu/CommonFunctions.cs) +function GetUserInput(windowTitle, defaultText, maxInputLength) + -- Create the window title string. + local resourceName = string.upper(GetCurrentResourceName()) + local textEntry = resourceName .. "_WINDOW_TITLE" + if windowTitle == nil then + windowTitle = "Enter:" + end + AddTextEntry(textEntry, windowTitle) + + -- Display the input box. + DisplayOnscreenKeyboard(1, textEntry, "", defaultText or "", "", "", "", maxInputLength or 30) + Wait(0) + -- Wait for a result. + while true do + local keyboardStatus = UpdateOnscreenKeyboard(); + if keyboardStatus == 3 then -- not displaying input field anymore somehow + return nil + elseif keyboardStatus == 2 then -- cancelled + return nil + elseif keyboardStatus == 1 then -- finished editing + return GetOnscreenKeyboardResult() + else + Wait(0) + end + end +end + +function handleArrowInput(center, heading) + delta = 0.05 + if IsDisabledControlPressed(2, Keys["CTRL"]) then -- ctrl held down + delta = 0.01 + end + + if IsControlPressed(2, Keys["UP"]) then -- arrow up + local newCenter = PolyZone.rotate(center.xy, vector2(center.x, center.y + delta), heading) + return vector3(newCenter.x, newCenter.y, center.z) + end + if IsControlPressed(2, Keys["DOWN"]) then -- arrow down + local newCenter = PolyZone.rotate(center.xy, vector2(center.x, center.y - delta), heading) + return vector3(newCenter.x, newCenter.y, center.z) + end + if IsControlPressed(2, Keys["LEFT"]) then -- arrow left + local newCenter = PolyZone.rotate(center.xy, vector2(center.x - delta, center.y), heading) + return vector3(newCenter.x, newCenter.y, center.z) + end + if IsControlPressed(2, Keys["RIGHT"]) then -- arrow right + local newCenter = PolyZone.rotate(center.xy, vector2(center.x + delta, center.y), heading) + return vector3(newCenter.x, newCenter.y, center.z) + end + + return center +end +Keys = { + ["MWUP"] = 0x3076E97C, + ["MWDOWN"] = 0x8BDE7443, + ["CTRL"] = 0xDB096B85, + ["SHIFT"] = 0x8FFC75D6, + ["LALT"] = 0x8AAA0AD4, + ["Z"] = 0x26E9DC00, + ["UP"] = 0x6319DB71, + ["DOWN"] = 0x05CA7C52, + ["LEFT"] = 0xA65EBAB4, + ["RIGHT"] = 0xDEB34313, +} + + + +function DisableControls() + DisableControlAction(2, Keys["MWUP"], true) + DisableControlAction(2, Keys["MWDOWN"], true) + DisableControlAction(2, Keys["CTRL"], true) + DisableControlAction(2, Keys["SHIFT"], true) + DisableControlAction(2, Keys["LALT"], true) +end From 16ad5a6bb90fd618d76b292347631d6c4492b781 Mon Sep 17 00:00:00 2001 From: Infernalz <51412133+Infernalz92@users.noreply.github.com> Date: Sun, 1 Oct 2023 01:02:12 +0200 Subject: [PATCH 6/7] Create BoxZone.lua Added missing file --- creation/client/BoxZone.lua | 106 ++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 creation/client/BoxZone.lua diff --git a/creation/client/BoxZone.lua b/creation/client/BoxZone.lua new file mode 100644 index 0000000..6733eb1 --- /dev/null +++ b/creation/client/BoxZone.lua @@ -0,0 +1,106 @@ +local function handleInput(useZ, heading, length, width, center) + if not useZ then + local scaleDelta, headingDelta = 0.2, 5 + if IsDisabledControlPressed(2, Keys["CTRL"]) then -- ctrl held down + scaleDelta, headingDelta = 0.05, 1 + end + + if IsDisabledControlJustReleased(2, Keys["MWDOWN"]) then + if IsDisabledControlPressed(2, Keys["LALT"]) then -- alt held down + return heading, length, math.max(0.0, width - scaleDelta), center + end + if IsDisabledControlPressed(2, Keys["SHIFT"]) then -- shift held down + return heading, math.max(0.0, length - scaleDelta), width, center + end + return (heading - headingDelta) % 360, length, width, center + end + + if IsDisabledControlJustReleased(2, Keys["MWUP"]) then + if IsDisabledControlPressed(2, Keys["LALT"]) then -- alt held down + return heading, length, math.max(0.0, width + scaleDelta), center + end + if IsDisabledControlPressed(2, Keys["SHIFT"]) then -- shift held down + return heading, math.max(0.0, length + scaleDelta), width, center + end + return (heading + headingDelta) % 360, length, width, center + end + end + + local rot = GetGameplayCamRot(2) + center = handleArrowInput(center, rot.z) + + return heading, length, width, center +end + +function handleZ(minZ, maxZ) + local delta = 0.2 + if IsDisabledControlPressed(2, Keys["CTRL"]) then -- ctrl held down + delta = 0.05 + end + + if IsDisabledControlJustReleased(2, Keys["MWDOWN"]) then + if IsDisabledControlPressed(2, Keys["LALT"]) then -- alt held down + return minZ - delta, maxZ + end + if IsDisabledControlPressed(2, Keys["SHIFT"]) then -- shift held down + return minZ, maxZ - delta + end + return minZ - delta, maxZ - delta + end + + if IsDisabledControlJustReleased(2, Keys["MWUP"]) then + if IsDisabledControlPressed(2, Keys["LALT"]) then -- alt held down + return minZ + delta, maxZ + end + if IsDisabledControlPressed(2, Keys["SHIFT"]) then -- shift held down + return minZ, maxZ + delta + end + return minZ + delta, maxZ + delta + end + return minZ, maxZ +end + +function boxStart(name, heading, length, width, minHeight, maxHeight) + local center = GetEntityCoords(PlayerPedId()) + createdZone = BoxZone:Create(center, length, width, {name = tostring(name)}) + local useZ, minZ, maxZ = false, center.z - 1.0, center.z + 3.0 + if minHeight then + minZ = center.z - minHeight + createdZone.minZ = minZ + end + if maxHeight then + maxZ = center.z + maxHeight + createdZone.maxZ = maxZ + end + Citizen.CreateThread(function() + LocalPlayer.state:set("PolyZoneCreation", true, true) + while createdZone do + DisableControls() + if IsControlJustPressed(2, Keys["Z"]) then -- Z pressed + useZ = not useZ + if useZ then + createdZone.debugColors.walls = {255, 0, 0} + else + createdZone.debugColors.walls = {0, 255, 0} + end + end + heading, length, width, center = handleInput(useZ, heading, length, width, center) + if useZ then + minZ, maxZ = handleZ(minZ, maxZ) + createdZone.minZ = minZ + createdZone.maxZ = maxZ + end + createdZone:setLength(length) + createdZone:setWidth(width) + createdZone:setHeading(heading) + createdZone:setCenter(center) + Wait(0) + end + LocalPlayer.state:set("PolyZoneCreation", false, true) + end) +end + +function boxFinish() + TriggerServerEvent("polyzone:printBox", + {name=createdZone.name, center=createdZone.center, length=createdZone.length, width=createdZone.width, heading=createdZone.offsetRot, minZ=createdZone.minZ, maxZ=createdZone.maxZ}) +end From 61f5b1f5652089164652a6178c7d4656665a14d6 Mon Sep 17 00:00:00 2001 From: Infernalz <51412133+Infernalz92@users.noreply.github.com> Date: Sun, 1 Oct 2023 01:02:54 +0200 Subject: [PATCH 7/7] Create creation.lua Added missing file --- creation/server/creation.lua | 76 ++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 creation/server/creation.lua diff --git a/creation/server/creation.lua b/creation/server/creation.lua new file mode 100644 index 0000000..08957af --- /dev/null +++ b/creation/server/creation.lua @@ -0,0 +1,76 @@ +RegisterNetEvent("polyzone:printPoly") +AddEventHandler("polyzone:printPoly", function(zone) + file = io.open('polyzone_created_zones.txt', "a") + io.output(file) + local output = parsePoly(zone) + io.write(output) + io.close(file) +end) + +RegisterNetEvent("polyzone:printCircle") +AddEventHandler("polyzone:printCircle", function(zone) + file = io.open('polyzone_created_zones.txt', "a") + io.output(file) + local output = parseCircle(zone) + io.write(output) + io.close(file) +end) + +RegisterNetEvent("polyzone:printBox") +AddEventHandler("polyzone:printBox", function(zone) + file = io.open('polyzone_created_zones.txt', "a") + io.output(file) + local output = parseBox(zone) + io.write(output) + io.close(file) +end) + +function round(num, numDecimalPlaces) + local mult = 10^(numDecimalPlaces or 0) + return math.floor(num * mult + 0.5) / mult +end + +function printoutHeader(name) + return "--Name: " .. name .. " | " .. os.date("!%Y-%m-%dT%H:%M:%SZ\n") +end + +function parsePoly(zone) + local printout = printoutHeader(zone.name) + printout = printout .. "PolyZone:Create({\n" + for i=1, #zone.points do + if i ~= #zone.points then + printout = printout .. " vector2(" .. tostring(zone.points[i].x) .. ", " .. tostring(zone.points[i].y) .."),\n" + else + printout = printout .. " vector2(" .. tostring(zone.points[i].x) .. ", " .. tostring(zone.points[i].y) ..")\n" + end + end + printout = printout .. "}, {\n name=\"" .. zone.name .. "\",\n --minZ = " .. zone.minZ .. ",\n --maxZ = " .. zone.maxZ .. "\n})\n\n" + return printout +end + +function parseCircle(zone) + local printout = printoutHeader(zone.name) + printout = printout .. "CircleZone:Create(" + printout = printout .. "vector3(" .. tostring(round(zone.center.x, 2)) .. ", " .. tostring(round(zone.center.y, 2)) .. ", " .. tostring(round(zone.center.z, 2)) .."), " + printout = printout .. tostring(zone.radius) .. ", " + printout = printout .. "{\n name=\"" .. zone.name .. "\",\n useZ=" .. tostring(zone.useZ) .. ",\n --debugPoly=true\n})\n\n" + return printout +end + +function parseBox(zone) + local printout = printoutHeader(zone.name) + printout = printout .. "BoxZone:Create(" + printout = printout .. "vector3(" .. tostring(round(zone.center.x, 2)) .. ", " .. tostring(round(zone.center.y, 2)) .. ", " .. tostring(round(zone.center.z, 2)) .."), " + printout = printout .. tostring(zone.length) .. ", " + printout = printout .. tostring(zone.width) .. ", " + + printout = printout .. "{\n name=\"" .. zone.name .. "\",\n heading=" .. zone.heading .. ",\n --debugPoly=true" + if zone.minZ then + printout = printout .. ",\n minZ=" .. tostring(round(zone.minZ, 2)) + end + if zone.maxZ then + printout = printout .. ",\n maxZ=" .. tostring(round(zone.maxZ, 2)) + end + printout = printout .. "\n})\n\n" + return printout +end