From d9084186376045759dcd5ef4780c5c98cafeb625 Mon Sep 17 00:00:00 2001 From: SNAILX <180862994+SNAILX808@users.noreply.github.com> Date: Tue, 11 Nov 2025 00:57:39 +0100 Subject: [PATCH] Move-refactor-raycast-functions-esx_lib --- [core]/es_extended/client/compat.lua | 23 ++++++- [core]/es_extended/client/functions.lua | 21 ------- [core]/esx_lib/imports/raycast/client.lua | 77 +++++++++++++++++++++++ 3 files changed, 99 insertions(+), 22 deletions(-) create mode 100644 [core]/esx_lib/imports/raycast/client.lua diff --git a/[core]/es_extended/client/compat.lua b/[core]/es_extended/client/compat.lua index 254148ac..feef08bf 100644 --- a/[core]/es_extended/client/compat.lua +++ b/[core]/es_extended/client/compat.lua @@ -1 +1,22 @@ ---All client-side functions outsourced from the Core to the lib will be stored here for compatability, e.g: \ No newline at end of file +--All client-side functions outsourced from the Core to the lib will be stored here for compatability, e.g: + +ESX.Game.GetShapeTestResultSync = xLib.Raycast.GetShapeTestResult +ESX.Game.RaycastScreen = xLib.Raycast.FromScreen +ESX.Game.StartRaycasting = xLib.Raycast.Start +ESX.Game.StopRaycasting = function(raycast) + if raycast and raycast.active then + raycast:Stop() + end +end +ESX.Game.IsRaycastActive = function(raycast) + if raycast and raycast.active then + return raycast:IsActive() + end + return false +end +ESX.Game.GetRaycastResult = function(raycast) + if raycast and raycast.active then + return raycast.result + end + return nil +end \ No newline at end of file diff --git a/[core]/es_extended/client/functions.lua b/[core]/es_extended/client/functions.lua index 953296d2..5e9dbd3b 100644 --- a/[core]/es_extended/client/functions.lua +++ b/[core]/es_extended/client/functions.lua @@ -736,27 +736,6 @@ function ESX.Game.IsSpawnPointClear(coords, maxDistance) return #ESX.Game.GetVehiclesInArea(coords, maxDistance) == 0 end ----@param shape integer The shape to get the test result from ----@return boolean, table, table, integer, integer -function ESX.Game.GetShapeTestResultSync(shape) - local handle, hit, coords, normal, material, entity - repeat - handle, hit, coords, normal, material, entity = GetShapeTestResultIncludingMaterial(shape) - Wait(0) - until handle ~= 1 - return hit, coords, normal, material, entity -end - ----@param depth number The depth to raycast ----@vararg any The arguments to pass to the shape test ----@return table, boolean, table, table, integer, integer -function ESX.Game.RaycastScreen(depth, ...) - local world, normal = GetWorldCoordFromScreenCoord(.5, .5) - local origin = world + normal - local target = world + normal * depth - return target, ESX.Game.GetShapeTestResultSync(StartShapeTestLosProbe(origin.x, origin.y, origin.z, target.x, target.y, target.z, ...)) -end - ---@param entities table The entities to search through ---@param isPlayerEntities boolean Whether the entities are players ---@param coords? table | vector3 The coords to search from diff --git a/[core]/esx_lib/imports/raycast/client.lua b/[core]/esx_lib/imports/raycast/client.lua new file mode 100644 index 00000000..f0464be5 --- /dev/null +++ b/[core]/esx_lib/imports/raycast/client.lua @@ -0,0 +1,77 @@ +xLib.Raycast = {} +xLib.Raycast.__index = xLib.Raycast + +local unpack = table.unpack +local GetShapeTestResultIncludingMaterial = GetShapeTestResultIncludingMaterial +local StartShapeTestLosProbe = StartShapeTestLosProbe +local GetWorldCoordFromScreenCoord = GetWorldCoordFromScreenCoord + +---@param shape integer The shape test handle to wait for +---@return boolean, table, table, integer, integer +function xLib.Raycast.GetShapeTestResult(shape) + local handle, hit, coords, normal, material, entity + + repeat + handle, hit, coords, normal, material, entity = GetShapeTestResultIncludingMaterial(shape) + Wait(0) + until handle ~= 1 + + return hit, coords, normal, material, entity +end + +---@param depth number The raycast distance +---@vararg any Additional arguments to pass to shape test +---@return table, boolean, table, table, integer, integer +function xLib.Raycast.FromScreen(depth, ...) + local worldCoords, normalVector = GetWorldCoordFromScreenCoord(0.5, 0.5) + local origin = worldCoords + normalVector + local target = worldCoords + normalVector * depth + return target, xLib.Raycast.GetShapeTestResult(StartShapeTestLosProbe(origin.x, origin.y, origin.z, target.x, target.y, target.z, ...)) +end + +-- Start continuous raycasting +---@param depth number The raycast distance +---@vararg any Additional arguments to pass to shape test +function xLib.Raycast.Start(depth, ...) + local self = setmetatable({}, xLib.Raycast) + + self.refreshRate = refreshRate + self.depth = depth + self.args = {...} + + self.active = true + + self._thread = CreateThread(function() + while self.active do + local target, hit, coords, normal, material, entity = xLib.Raycast.FromScreen(self.depth, unpack(self.args)) + self.result = { + hit = hit, + coords = coords, + normal = normal, + material = material, + entity = entity, + } + Wait(1) + end + end) + + return self +end + +-- Stop raycasting +function xLib.Raycast:Stop() + if not self and not self.active then print('already stopped') return end + self.active = false + if self._thread then + self._thread = nil + end +end + +-- Check if the raycating is active +---@return boolean +function xLib.Raycast:IsActive() + if not self and not self.active then return end + return self.active +end + +return xLib.Raycast