refactor(zones): perf, args, and insideZone

lib.zones.new should take a single argument containing all
data related to the new zone, then append new fields to the table.
No need for a distance check and 'nearby', instead check if player
is inside the polygon.
Use a function ref instead of closures for debug (drawPolygon).
This commit is contained in:
Linden
2022-04-25 21:33:56 +10:00
parent adb110d8d8
commit 94a460903d

View File

@@ -5,99 +5,75 @@ local function removeZone(self)
zones[self.id] = nil zones[self.id] = nil
end end
local nearby = {} local function debug(self)
local points = self.polygon()
for i = 1, #points do
if i == #points then
DrawPoly(points[i], points[1], self.centroid, 255, 0, 0, 50)
DrawPoly(points[1], points[i], self.centroid, 255, 0, 0, 50)
else
DrawPoly(points[i], points[i + 1], self.centroid, 255, 0, 0, 50)
DrawPoly(points[i + 1], points[i], self.centroid, 255, 0, 0, 50)
end
end
end
local inside = {}
local tick local tick
CreateThread(function() CreateThread(function()
while true do while true do
local coords = GetEntityCoords(cache.ped) local coords = GetEntityCoords(cache.ped)
Wait(300) Wait(300)
table.wipe(nearby) table.wipe(inside)
for _, zone in pairs(zones) do for _, zone in pairs(zones) do
local distance = #(coords - zone.polygon:centroid()) local contains = zone.polygon:contains(coords, zone.thickness)
if distance <= zone.inRange then if contains then
if zone.nearby then if zone.inside then
nearby[#nearby + 1] = zone inside[#inside + 1] = zone
end end
if zone.polygon:contains(coords, zone.thickness) then if zone.onEnter and not zone.insideZone then
if zone.onEnter and not zone.inside then zone.insideZone = true
zone.inside = true zone:onEnter()
zone:onEnter() end
end elseif zone.insideZone then
elseif zone.inside then zone.insideZone = nil
if zone.onExit then zone:onExit() end if zone.onExit then
zone.inside = nil zone:onExit()
end end
end end
end end
if not tick then if not tick then
if #nearby > 0 then if #inside > 0 then
tick = SetInterval(function() tick = SetInterval(function()
for i = 1, #nearby do for i = 1, #inside do
nearby[i]:nearby() inside[i]:inside()
if nearby[i].debug then if inside[i].debug then
nearby[i]:drawPolygon() inside[i]:debug()
end end
end end
end) end)
end end
elseif #nearby == 0 then elseif #inside == 0 then
tick = ClearInterval(tick) tick = ClearInterval(tick)
end end
end end
end) end)
return { return {
new = function(points, thickness, data) new = function(data)
local id = #zones + 1 data.id = #zones + 1
local self = { data.thickness = data.thickness or 2
id = id, data.polygon = glm.polygon.new(data.points)
thickness = thickness, data.remove = removeZone
polygon = glm.polygon.new(points), data.centroid = data.polygon:centroid()
remove = removeZone data.debug = data.debug and debug
}
if data then zones[data.id] = data
for k, v in pairs(data) do return data
self[k] = v
end
end
if self.debug and not self.nearby then
self.nearby = function() end
end
local centroid = self.polygon:centroid()
local length = #self.polygon
self.maxDistance = 0
for i = 1, length do
local difference = #(centroid - points[i])
if difference > self.maxDistance then
self.maxDistance = difference
end
end
self.inRange = self.inRange or self.maxDistance * 1.5
self.drawPolygon = function()
local points = self.polygon()
for i = 1, #points do
if i == #points then
DrawPoly(points[i], points[1], centroid, 255, 0, 0, 50)
DrawPoly(points[1], points[i], centroid, 255, 0, 0, 50)
else
DrawPoly(points[i], points[i + 1], centroid, 255, 0, 0, 50)
DrawPoly(points[i + 1], points[i], centroid, 255, 0, 0, 50)
end
end
end
zones[id] = self
return self
end end
} }