Files
ox_lib/imports/points/client.lua

183 lines
4.8 KiB
Lua
Raw Normal View History

---@class PointProperties
---@field coords vector3
---@field distance number
2022-10-02 20:19:35 +11:00
---@field onEnter? fun(self: CPoint)
---@field onExit? fun(self: CPoint)
---@field nearby? fun(self: CPoint)
---@field [string] any
---@class CPoint : PointProperties
---@field id number
---@field currentDistance number
---@field isClosest? boolean
---@field remove fun()
---@type table<number, CPoint>
local points = {}
---@type CPoint[]
local nearbyPoints = {}
local nearbyCount = 0
---@type CPoint?
local closestPoint
local tick
2022-04-14 10:58:17 +00:00
local function removePoint(self)
if closestPoint?.id == self.id then
closestPoint = nil
end
2025-03-10 16:28:44 +11:00
lib.grid.removeEntry(self)
points[self.id] = nil
end
CreateThread(function()
2025-03-10 16:28:44 +11:00
while true do
if nearbyCount ~= 0 then
2025-03-10 16:28:44 +11:00
table.wipe(nearbyPoints)
nearbyCount = 0
end
2025-03-10 16:28:44 +11:00
local coords = GetEntityCoords(cache.ped)
local newPoints = lib.grid.getNearbyEntries(coords, function(entry) return entry.remove == removePoint end) --[[@as CPoint[] ]]
local cellX, cellY = lib.grid.getCellPosition(coords)
cache.coords = coords
closestPoint = nil
2025-03-10 16:28:44 +11:00
if cellX ~= cache.lastCellX or cellY ~= cache.lastCellY then
for i = 1, #nearbyPoints do
local point = nearbyPoints[i]
2025-03-10 16:28:44 +11:00
if point.inside then
local distance = #(coords - point.coords)
2025-03-10 16:28:44 +11:00
if distance > point.radius then
if point.onExit then point:onExit() end
2022-03-16 01:18:10 +00:00
2025-03-10 16:28:44 +11:00
point.inside = nil
point.currentDistance = nil
end
2025-03-10 16:28:44 +11:00
end
end
cache.lastCellX = cellX
cache.lastCellY = cellY
end
for i = 1, #newPoints do
local point = newPoints[i]
local distance = #(coords - point.coords)
if distance <= point.radius then
point.currentDistance = distance
if not closestPoint or distance < (closestPoint.currentDistance or point.radius) then
if closestPoint then closestPoint.isClosest = nil end
point.isClosest = true
closestPoint = point
end
2022-04-14 11:08:56 +00:00
2025-03-10 16:28:44 +11:00
if point.nearby then
nearbyCount += 1
nearbyPoints[nearbyCount] = point
end
2025-03-10 16:28:44 +11:00
if point.onEnter and not point.inside then
point.inside = true
point:onEnter()
end
elseif point.currentDistance then
if point.onExit then point:onExit() end
point.inside = nil
point.currentDistance = nil
end
end
if not tick then
if nearbyCount ~= 0 then
tick = SetInterval(function()
for i = nearbyCount, 1, -1 do
local point = nearbyPoints[i]
2025-03-10 16:28:44 +11:00
if point and point.nearby then
point:nearby()
end
2025-03-10 16:28:44 +11:00
end
end)
end
elseif nearbyCount == 0 then
tick = ClearInterval(tick)
end
Wait(300)
end
end)
local function toVector(coords)
local _type = type(coords)
if _type ~= 'vector3' then
if _type == 'table' or _type == 'vector4' then
return vec3(coords[1] or coords.x, coords[2] or coords.y, coords[3] or coords.z)
end
error(("expected type 'vector3' or 'table' (received %s)"):format(_type))
end
return coords
end
2025-03-10 16:28:44 +11:00
lib.points = {}
---@return CPoint
---@overload fun(data: PointProperties): CPoint
---@overload fun(coords: vector3, distance: number, data?: PointProperties): CPoint
function lib.points.new(...)
local args = { ... }
local id = #points + 1
local self
-- Support sending a single argument containing point data
if type(args[1]) == 'table' then
self = args[1]
self.id = id
self.remove = removePoint
else
-- Backwards compatibility for original implementation (args: coords, distance, data)
self = {
id = id,
coords = args[1],
remove = removePoint,
}
end
self.coords = toVector(self.coords)
self.distance = self.distance or args[2]
self.radius = self.distance
if args[3] then
for k, v in pairs(args[3]) do
self[k] = v
end
end
lib.grid.addEntry(self)
points[id] = self
return self
end
function lib.points.getAllPoints() return points end
function lib.points.getNearbyPoints() return nearbyPoints end
---@return CPoint?
function lib.points.getClosestPoint() return closestPoint end
---@deprecated
lib.points.closest = lib.points.getClosestPoint
return lib.points